diff --git a/README.md b/README.md index 04158f12..53baa8b2 100644 --- a/README.md +++ b/README.md @@ -241,8 +241,6 @@ It is recommended to also include this argument when performing an update on an Use the `--toc-title-padding-before` option to add padding line/s above the TOC which ensures formatters such as prettier will pass; e.g., `doctoc --toc-title-padding-before 1 .` -NOTE: Currently it is only supported to add one line before the title. - By default, - no padding is added above the table of contents title diff --git a/lib/content-generation.js b/lib/content-generation.js index da692c3a..549c5f97 100644 --- a/lib/content-generation.js +++ b/lib/content-generation.js @@ -55,10 +55,44 @@ function escapedStartTag(syntax) { return commentTypes[syntax].escapedStart; } +function tocFooter(footerOptions) { + return tocPart(footerOptions?.padding, footerOptions?.content); +} + +function tocHeader(headerOptions) { + return tocPart(headerOptions?.padding, headerOptions?.content); +} + +function tocTitle(titleOptions, existingTitle) { + if (titleOptions?.remove || (existingTitle === "" && !titleOptions?.content)) return []; + var content; + if (titleOptions?.content){ + content = titleOptions.content; + } + else if(existingTitle){ + content = existingTitle; + } + else{ + content = '**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*'; + } + return tocPart(titleOptions?.padding, content); +} + +function tocPart(padding, content){ + if (content === undefined) return []; + var lines = Array(Number(padding?.before ?? 0)).fill(''); + lines.push(content); + lines.push(...Array(Number(padding?.after ?? 0)).fill('')); + return lines; +} + module.exports = { commentedBlock, escapedStartTag, pragmaMarkers, skipTag, - excludeTag + excludeTag, + tocFooter, + tocHeader, + tocTitle }; diff --git a/lib/transform.js b/lib/transform.js index da89479b..d957d891 100644 --- a/lib/transform.js +++ b/lib/transform.js @@ -153,14 +153,8 @@ function processHeaders(headers, mode) { return headers; } -// When updating an existing TOC, try to preserve the title that was there before. -// Falls back to CLI args (--title, --notitle) or the default title for new TOCs. -function determineTitle(nodes, tocPosition, title, notitle, header) { - var defaultTitle = '**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*'; - - if (notitle) return ""; - if (title) return title; - if (!tocPosition?.existing) return defaultTitle; +function determineTitle(nodes, tocPosition, titleOptions, header) { + if (titleOptions.remove || titleOptions.content || !tocPosition?.existing) return undefined; // Find the TOC's list node so we know where the title region ends var listStartIdx = nodes.children.filter(function (x) { @@ -231,6 +225,7 @@ exports = module.exports = function transform(content, mode, maxHeaderLevel, min options.toc.items ??= {}; options.toc.items.indentation ??= {}; options.toc.list ??= {}; + options.toc.title ??= {}; syntax = syntax || "md"; options.toc.items.indentation.style ??= 'space'; @@ -241,6 +236,8 @@ exports = module.exports = function transform(content, mode, maxHeaderLevel, min var ordered = options.toc.list.format === 'ordered'; options.toc.items.symbols ??= ordered ? undefined : String(entryPrefix || '-').split(','); options.toc.list.style ??= ordered ? 'number' : undefined + options.toc.title.content ??= title; + options.toc.title.remove ??= notitle; var eol = '\n'; eol = detectLineEnding(content, eol); @@ -255,11 +252,6 @@ exports = module.exports = function transform(content, mode, maxHeaderLevel, min minTocItems = 1; } - var padTitle = options?.toc?.title?.padding?.before > 0; - if (options?.toc?.title?.padding?.before === undefined){ - padTitle = notitle || false; - } - // only limit *HTML* headings by default var maxHeaderLevelHtml = maxHeaderLevel || 4; @@ -338,16 +330,15 @@ exports = module.exports = function transform(content, mode, maxHeaderLevel, min if (headers.length >= minTocItems && docNodes.children[docNodes.children.length - 1].loc.end.line >= minLines) { var tocLines = []; - var inferredTitle = determineTitle(docNodes, tocPosition, title, notitle, options?.toc?.header?.content); + var inferredTitle = determineTitle(docNodes, tocPosition, options.toc.title, options.toc.header?.content); var allHeaders = processHeaders(headers, mode); var lowestRank = allHeaders.reduce((min, h) => Math.min(min, h.rank), Infinity); var indentation = options.toc.items.indentation.style === 'tab' ? '\t' : ' '; - if (options?.toc?.header?.content) { tocLines.push(options.toc.header.content); } - if (padTitle && inferredTitle) { tocLines.push(''); } - if (inferredTitle) { tocLines.push(inferredTitle); } + tocLines.push(...contentGenerator.tocHeader(options.toc.header)); + tocLines.push(...contentGenerator.tocTitle(options.toc.title, inferredTitle)); tocLines.push(''); var symbolQty = options.toc.items.symbols?.length || 1; @@ -383,7 +374,7 @@ exports = module.exports = function transform(content, mode, maxHeaderLevel, min })); tocLines.push(''); - if (options?.toc?.footer?.content) { tocLines.push(options.toc.footer.content); } + tocLines.push(...contentGenerator.tocFooter(options.toc.footer)); toc = tocLines.join(eol); }