markdown-magic 3.4.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -16
- package/cli.js +1 -1
- package/package-lock.json +1127 -0
- package/package.json +14 -12
- package/src/.DS_Store +0 -0
- package/{lib → src}/block-parser.js +4 -0
- package/{lib → src}/cli.js +0 -0
- package/{lib → src}/index.js +4 -1
- package/{lib → src}/process-contents.js +28 -4
- package/src/transforms/file.js +75 -0
- package/{lib → src}/transforms/index.js +8 -6
- package/src/transforms/sectionToc.js +37 -0
- package/src/transforms/toc.js +107 -0
- package/src/utils/.DS_Store +0 -0
- package/src/utils/details.js +15 -0
- package/{lib → src}/utils/toc.js +33 -7
- package/lib/transforms/file.js +0 -42
- package/lib/transforms/sectionToc.js +0 -18
- package/lib/transforms/toc.js +0 -31
- /package/{lib → src}/argparse/README.md +0 -0
- /package/{lib → src}/argparse/argparse.js +0 -0
- /package/{lib → src}/argparse/argparse.test.js +0 -0
- /package/{lib → src}/argparse/index.js +0 -0
- /package/{lib → src}/argparse/splitOutsideQuotes.js +0 -0
- /package/{lib → src}/argparse/splitOutsideQuotes.test.js +0 -0
- /package/{lib → src}/block-parser-js.test.js +0 -0
- /package/{lib → src}/block-parser.test.js +0 -0
- /package/{lib → src}/cli.test.js +0 -0
- /package/{lib → src}/defaults.js +0 -0
- /package/{lib → src}/globparse.js +0 -0
- /package/{lib → src}/globparse.test.js +0 -0
- /package/{lib → src}/index.test.js +0 -0
- /package/{lib → src}/process-file.js +0 -0
- /package/{lib → src}/transforms/code/index.js +0 -0
- /package/{lib → src}/transforms/code/resolve-github-file.js +0 -0
- /package/{lib → src}/transforms/code/resolve-github-file.test.js +0 -0
- /package/{lib → src}/transforms/remote.js +0 -0
- /package/{lib → src}/transforms/wordCount.js +0 -0
- /package/{lib → src}/types.js +0 -0
- /package/{lib → src}/utils/fs.js +0 -0
- /package/{lib → src}/utils/fs.test.js +0 -0
- /package/{lib → src}/utils/hash-file.js +0 -0
- /package/{lib → src}/utils/index.js +0 -0
- /package/{lib → src}/utils/load-config.js +0 -0
- /package/{lib → src}/utils/logs.js +0 -0
- /package/{lib → src}/utils/regex-timeout.js +0 -0
- /package/{lib → src}/utils/regex.js +0 -0
- /package/{lib → src}/utils/remoteRequest.js +0 -0
- /package/{lib → src}/utils/sortOrder.js +0 -0
- /package/{lib → src}/utils/string-break.js +0 -0
- /package/{lib → src}/utils/syntax.js +0 -0
- /package/{lib → src}/utils/text.js +0 -0
- /package/{lib → src}/utils/text.test.js +0 -0
- /package/{lib → src}/utils/toposort.js +0 -0
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdown-magic",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.5.0",
|
|
4
4
|
"description": "Automatically update markdown files with content from external sources",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"markdown": "./cli.js",
|
|
8
8
|
"md-magic": "./cli.js",
|
|
@@ -13,23 +13,23 @@
|
|
|
13
13
|
"package.json",
|
|
14
14
|
"package-lock.json",
|
|
15
15
|
"cli.js",
|
|
16
|
-
"
|
|
16
|
+
"src"
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"types": "tsc",
|
|
20
20
|
"emit-types": "tsc --noEmit false --emitDeclarationOnly true",
|
|
21
21
|
"docs": "node examples/generate-readme.js",
|
|
22
|
-
"test": "npm run test:
|
|
23
|
-
"test:
|
|
22
|
+
"test": "npm run test:src && npm run test:test && echo 'tests done'",
|
|
23
|
+
"test:src": "uvu src '.test.([mc]js|[jt]sx?)$'",
|
|
24
24
|
"test:test": "uvu test '.test.([mc]js|[jt]sx?)$'",
|
|
25
|
-
"test:block": "uvu
|
|
26
|
-
"test:cli": "uvu
|
|
27
|
-
"test:md": "uvu
|
|
28
|
-
"test:fs": "uvu
|
|
29
|
-
"test:js": "uvu
|
|
25
|
+
"test:block": "uvu src 'block-parser.test.([mc]js|[jt]sx?)$'",
|
|
26
|
+
"test:cli": "uvu src 'cli.test.([mc]js|[jt]sx?)$'",
|
|
27
|
+
"test:md": "uvu src 'md.test.([mc]js|[jt]sx?)$'",
|
|
28
|
+
"test:fs": "uvu src 'fs.test.([mc]js|[jt]sx?)$'",
|
|
29
|
+
"test:js": "uvu src 'block-parser-js.test.([mc]js|[jt]sx?)$'",
|
|
30
30
|
"test:errors": "uvu test 'errors.test.([mc]js|[jt]sx?)$'",
|
|
31
31
|
"test:transforms": "uvu test 'transforms.test.([mc]js|[jt]sx?)$'",
|
|
32
|
-
"test:text": "uvu
|
|
32
|
+
"test:text": "uvu src 'text.test.([mc]js|[jt]sx?)$'",
|
|
33
33
|
"cli": "node ./cli.js --path 'README.md' --config ./markdown.config.js",
|
|
34
34
|
"publish": "git push origin && git push origin --tags",
|
|
35
35
|
"release:patch": "npm version patch && npm publish",
|
|
@@ -44,16 +44,18 @@
|
|
|
44
44
|
"url": "https://github.com/DavidWells/markdown-magic"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@davidwells/md-utils": "
|
|
47
|
+
"@davidwells/md-utils": "0.0.52",
|
|
48
48
|
"globrex": "^0.1.2",
|
|
49
49
|
"gray-matter": "^4.0.3",
|
|
50
50
|
"is-glob": "^4.0.3",
|
|
51
51
|
"is-local-path": "^0.1.6",
|
|
52
52
|
"is-valid-path": "^0.1.1",
|
|
53
53
|
"micro-mdx-parser": "^1.1.0",
|
|
54
|
+
"module-alias": "^2.2.3",
|
|
54
55
|
"mri": "^1.2.0",
|
|
55
56
|
"node-fetch": "^2.7.0",
|
|
56
57
|
"oparser": "^3.0.22",
|
|
58
|
+
"punycode": "^2.3.1",
|
|
57
59
|
"smart-glob": "^1.0.2",
|
|
58
60
|
"string-width": "^4.2.3",
|
|
59
61
|
"sync-request": "^6.1.0"
|
package/src/.DS_Store
ADDED
|
Binary file
|
|
@@ -139,6 +139,8 @@ Details:
|
|
|
139
139
|
// console.log('openEnd', openEnd)
|
|
140
140
|
// console.log('options', options)
|
|
141
141
|
|
|
142
|
+
// context.hasNoBlankLine = content.indexOf('\n') === -1
|
|
143
|
+
|
|
142
144
|
const blockData = {
|
|
143
145
|
index: blockIndex,
|
|
144
146
|
type: transformType,
|
|
@@ -180,6 +182,8 @@ Details:
|
|
|
180
182
|
newBlocks.push(blockData)
|
|
181
183
|
}
|
|
182
184
|
|
|
185
|
+
// console.log("NEW BLOCKS", newBlocks)
|
|
186
|
+
// process.exit(1)
|
|
183
187
|
return {
|
|
184
188
|
// Close but no single line newPattern: newGetBlockRegex({ openComment, commentClose, start: START, ending: END }),
|
|
185
189
|
// pattern: regexToUse,
|
package/{lib → src}/cli.js
RENAMED
|
File without changes
|
package/{lib → src}/index.js
RENAMED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
|
+
// @TODO remove this once we have swapped out node-fetch@2.7
|
|
3
|
+
const moduleAlias = require('module-alias') // "Fix" for puncode dep warning in node 22+
|
|
4
|
+
moduleAlias.addAlias('punycode', 'punycode/') // "Fix" for puncode dep warning in node 22+
|
|
2
5
|
const { glob, globWithGit } = require('smart-glob')
|
|
3
6
|
const codeTransform = require('./transforms/code')
|
|
4
7
|
const fileTransform = require('./transforms/file')
|
|
@@ -16,7 +19,7 @@ const { parseMarkdown } = require('@davidwells/md-utils')
|
|
|
16
19
|
const { success, error, info, convertHrtime, deepLog } = require('./utils/logs')
|
|
17
20
|
const { OPEN_WORD, CLOSE_WORD, DEFAULT_GLOB_PATTERN } = require('./defaults')
|
|
18
21
|
const { getBlockRegex, parseBlocks } = require('./block-parser')
|
|
19
|
-
const toposort = require('./utils/toposort')
|
|
22
|
+
const toposort = require('./utils/toposort')
|
|
20
23
|
// const { hashFile } = require('./utils/hash-file')
|
|
21
24
|
// const { getBlockRegex } = require('./block-parser')
|
|
22
25
|
// const diff = require('../misc/old-test/utils/diff')
|
|
@@ -105,6 +105,7 @@ async function processContents(text, config) {
|
|
|
105
105
|
/* Apply Before middleware to all transforms */
|
|
106
106
|
const match = await applyMiddleware(originalMatch, md, beforeMiddleware)
|
|
107
107
|
const { block, content, open, close, transform, options, context } = match
|
|
108
|
+
// console.log("MATCH", match)
|
|
108
109
|
const closeTag = close.value
|
|
109
110
|
const openTag = open.value
|
|
110
111
|
|
|
@@ -151,6 +152,7 @@ async function processContents(text, config) {
|
|
|
151
152
|
|
|
152
153
|
// console.log('returnedContent', returnedContent)
|
|
153
154
|
// process.exit(1)
|
|
155
|
+
|
|
154
156
|
|
|
155
157
|
if (returnedContent) {
|
|
156
158
|
tempContent = returnedContent
|
|
@@ -207,8 +209,27 @@ async function processContents(text, config) {
|
|
|
207
209
|
preserveIndent = block.indentation.length
|
|
208
210
|
}
|
|
209
211
|
// console.log('preserveIndent', preserveIndent)
|
|
210
|
-
|
|
211
|
-
|
|
212
|
+
let addTrailingNewline = ''
|
|
213
|
+
if (context.isMultiline && !fix.endsWith('\n') && fix !== '' && closeTag.indexOf('\n') === -1) {
|
|
214
|
+
addTrailingNewline = '\n'
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
let addLeadingNewline = ''
|
|
218
|
+
if (context.isMultiline && !fix.startsWith('\n') && fix !== '' && openTag.indexOf('\n') === -1) {
|
|
219
|
+
addLeadingNewline = '\n'
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
let fixWrapper = ''
|
|
223
|
+
/* If block wasn't multiline but the contents ARE multiline fix the block */
|
|
224
|
+
if (!context.isMultiline && fix.indexOf('\n') > -1) {
|
|
225
|
+
fixWrapper = '\n'
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// console.log("OPEN TAG", `"${openTag}"`)
|
|
229
|
+
// console.log("CLOSE TAG", `"${closeTag}"`)
|
|
230
|
+
|
|
231
|
+
const indent = addLeadingNewline + indentString(fix, preserveIndent) + addTrailingNewline
|
|
232
|
+
const newCont = `${openTag}${fixWrapper}${indent}${fixWrapper}${closeTag}`
|
|
212
233
|
/* Replace original contents */
|
|
213
234
|
// Must use replacer function because strings get coerced to regex or something
|
|
214
235
|
const newContents = md.replace(block.value, () => newCont)
|
|
@@ -257,6 +278,9 @@ async function processContents(text, config) {
|
|
|
257
278
|
|
|
258
279
|
// console.log('srcPath', srcPath)
|
|
259
280
|
// console.log('outputPath', outputPath)
|
|
281
|
+
// console.log('updatedContents', updatedContents)
|
|
282
|
+
// console.log('text', text)
|
|
283
|
+
// process.exit(1)
|
|
260
284
|
const result = {
|
|
261
285
|
/* Has markdown content changed? */
|
|
262
286
|
isChanged: text !== updatedContents,
|
|
@@ -415,8 +439,8 @@ function sortTranforms(foundTransForms, registeredTransforms) {
|
|
|
415
439
|
if (!foundTransForms) return []
|
|
416
440
|
return foundTransForms.sort((a, b) => {
|
|
417
441
|
// put table of contents (TOC) at end of tranforms
|
|
418
|
-
if (a.transform === 'TOC') return 1
|
|
419
|
-
if (b.transform === 'TOC') return -1
|
|
442
|
+
if (a.transform === 'TOC' || a.transform === 'sectionToc') return 1
|
|
443
|
+
if (b.transform === 'TOC' || b.transform === 'sectionToc') return -1
|
|
420
444
|
return 0
|
|
421
445
|
}).map((item) => {
|
|
422
446
|
if (getTransform(item.transform, registeredTransforms)) {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const isLocalPath = require('is-local-path')
|
|
4
|
+
const { findFrontmatter } = require('@davidwells/md-utils/find-frontmatter')
|
|
5
|
+
const { removeLeadingH1 } = require('@davidwells/md-utils/string-utils')
|
|
6
|
+
|
|
7
|
+
module.exports = function FILE(api) {
|
|
8
|
+
/*
|
|
9
|
+
console.log('FILE API', api)
|
|
10
|
+
/** */
|
|
11
|
+
const { options, srcPath } = api
|
|
12
|
+
if (!options.src) {
|
|
13
|
+
return false
|
|
14
|
+
}
|
|
15
|
+
let fileContents = ''
|
|
16
|
+
if (isLocalPath(options.src)) {
|
|
17
|
+
const fileDir = path.dirname(srcPath)
|
|
18
|
+
const resolvedFilePath = path.resolve(fileDir, options.src)
|
|
19
|
+
try {
|
|
20
|
+
// console.log('READFILE', resolvedFilePath)
|
|
21
|
+
fileContents = fs.readFileSync(resolvedFilePath, 'utf8')
|
|
22
|
+
} catch (e) {
|
|
23
|
+
// if demo path. Todo probably remove
|
|
24
|
+
if (options.src === './path/to/file') {
|
|
25
|
+
return api.content
|
|
26
|
+
}
|
|
27
|
+
console.log(`FILE NOT FOUND ${resolvedFilePath}`)
|
|
28
|
+
throw e
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// trim leading and trailing spaces/line breaks in code and keeps the indentation of the first non-empty line
|
|
33
|
+
fileContents = fileContents.replace(/^(?:[\t ]*(?:\r?\n|\r))+|\s+$/g, '')
|
|
34
|
+
|
|
35
|
+
if (options.removeLeadingH1) {
|
|
36
|
+
fileContents = removeLeadingH1(fileContents)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const isMarkdown = path.extname(options.src).toLowerCase() === '.md'
|
|
40
|
+
// Shift headers up or down by the specified number of levels if shiftHeaders is enabled and file is markdown
|
|
41
|
+
if (options.shiftHeaders && isMarkdown) {
|
|
42
|
+
fileContents = fileContents.replace(/^(#{1,6})\s/gm, (match, hashes) => {
|
|
43
|
+
const currentLevel = hashes.length;
|
|
44
|
+
const shiftAmount = options.shiftHeaders;
|
|
45
|
+
const newLevel = Math.max(1, Math.min(6, currentLevel + shiftAmount));
|
|
46
|
+
return '#'.repeat(newLevel) + ' ';
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/* automatically trim frontmatter if file is markdown */
|
|
51
|
+
if (isMarkdown && options.trimFrontmatter !== false) {
|
|
52
|
+
const frontmatter = findFrontmatter(fileContents)
|
|
53
|
+
if (frontmatter && frontmatter.frontMatterRaw) {
|
|
54
|
+
fileContents = fileContents.replace(frontmatter.frontMatterRaw, '')
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (options.textBefore) {
|
|
59
|
+
fileContents = `${options.textBefore}${fileContents}`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (options.textAfter) {
|
|
63
|
+
fileContents = `${fileContents}${options.textAfter}`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return fileContents
|
|
67
|
+
|
|
68
|
+
return `<!-- The below content is automatically added from ${options.src} -->
|
|
69
|
+
${fileContents}`
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// maybe support...
|
|
73
|
+
function legacyCODE(content, options, config) {
|
|
74
|
+
|
|
75
|
+
}
|
|
@@ -2,6 +2,7 @@ const code = require('./code')
|
|
|
2
2
|
const file = require('./file')
|
|
3
3
|
const remoteContent = require('./remote')
|
|
4
4
|
const toc = require('./toc')
|
|
5
|
+
const sectionToc = require('./sectionToc')
|
|
5
6
|
|
|
6
7
|
const transforms = {
|
|
7
8
|
/**
|
|
@@ -11,8 +12,8 @@ const transforms = {
|
|
|
11
12
|
*
|
|
12
13
|
* **Options:**
|
|
13
14
|
* - `firsth1` - *boolean* - (optional): Show first h1 of doc in table of contents. Default `false`
|
|
14
|
-
* - `collapse` - *boolean* - (optional): Collapse the table of contents in a detail
|
|
15
|
-
* - `collapseText` - *string* - (optional): Text the toc
|
|
15
|
+
* - `collapse` - *boolean* - (optional): Collapse the table of contents in a detail accordion. Default `false`
|
|
16
|
+
* - `collapseText` - *string* - (optional): Text the toc accordion summary
|
|
16
17
|
* - `excludeText` - *string* - (optional): Text to exclude in the table of contents. Default `Table of Contents`
|
|
17
18
|
* - `maxDepth` - *number* - (optional): Max depth of headings. Default 4
|
|
18
19
|
*
|
|
@@ -23,7 +24,7 @@ const transforms = {
|
|
|
23
24
|
* <!-- end-doc-gen -->
|
|
24
25
|
* ```
|
|
25
26
|
*
|
|
26
|
-
* Default `
|
|
27
|
+
* Default `matchWord` is `doc-gen`
|
|
27
28
|
*
|
|
28
29
|
* ---
|
|
29
30
|
* @param {string} content The current content of the comment block
|
|
@@ -31,6 +32,7 @@ const transforms = {
|
|
|
31
32
|
* @return {string} Updated content to place in the content block
|
|
32
33
|
*/
|
|
33
34
|
TOC: toc,
|
|
35
|
+
sectionToc: sectionToc,
|
|
34
36
|
/**
|
|
35
37
|
* ### > CODE
|
|
36
38
|
*
|
|
@@ -55,7 +57,7 @@ const transforms = {
|
|
|
55
57
|
* <!-- end-doc-gen -->
|
|
56
58
|
* ```
|
|
57
59
|
*
|
|
58
|
-
* Default `
|
|
60
|
+
* Default `matchWord` is `doc-gen`
|
|
59
61
|
*
|
|
60
62
|
* ---
|
|
61
63
|
* @param {string} content The current content of the comment block
|
|
@@ -78,7 +80,7 @@ const transforms = {
|
|
|
78
80
|
* <!-- end-doc-gen -->
|
|
79
81
|
* ```
|
|
80
82
|
*
|
|
81
|
-
* Default `
|
|
83
|
+
* Default `matchWord` is `doc-gen`
|
|
82
84
|
*
|
|
83
85
|
* ---
|
|
84
86
|
* @param {string} content The current content of the comment block
|
|
@@ -101,7 +103,7 @@ const transforms = {
|
|
|
101
103
|
* <!-- end-doc-gen -->
|
|
102
104
|
* ```
|
|
103
105
|
*
|
|
104
|
-
* Default `
|
|
106
|
+
* Default `matchWord` is `doc-gen`
|
|
105
107
|
*
|
|
106
108
|
* ---
|
|
107
109
|
* @param {string} content The current content of the comment block
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// const { generateToc } = require('../utils/toc')
|
|
2
|
+
const { generateToc } = require('@davidwells/md-utils')
|
|
3
|
+
const { findClosestParentHeading } = require('@davidwells/md-utils/find-headings')
|
|
4
|
+
const { readFile } = require('../utils/fs')
|
|
5
|
+
const details = require('../utils/details')
|
|
6
|
+
|
|
7
|
+
module.exports = async function sectionToc(api) {
|
|
8
|
+
const { options, currentFileContent, originalFileContent, srcPath, getBlockDetails } = api
|
|
9
|
+
const opts = options || {}
|
|
10
|
+
let { collapseText, collapse } = opts
|
|
11
|
+
/* Sub table of contents */
|
|
12
|
+
const originalBlock = getBlockDetails(originalFileContent)
|
|
13
|
+
const closestHeading = findClosestParentHeading(originalFileContent, originalBlock.block.start)
|
|
14
|
+
// console.log('closestHeading', closestHeading)
|
|
15
|
+
|
|
16
|
+
const subToc = await generateToc(currentFileContent, {
|
|
17
|
+
...opts,
|
|
18
|
+
normalizeLevels: true,
|
|
19
|
+
// Set sub table of contents
|
|
20
|
+
subSection: closestHeading,
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
if (closestHeading) {
|
|
24
|
+
const headingText = closestHeading.text
|
|
25
|
+
// console.log('BEFORE', linesBefore)
|
|
26
|
+
// console.log('closest parent heading', closestHeading)
|
|
27
|
+
// console.log('headingText', headingText)
|
|
28
|
+
collapseText = collapseText || `${headingText} contents`
|
|
29
|
+
// https://regex101.com/r/MB85zm/1
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (collapse || collapseText) {
|
|
33
|
+
return details(subToc.text, collapseText)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return subToc.text
|
|
37
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const { generateToc } = require('@davidwells/md-utils')
|
|
2
|
+
const { removeLeadingAndTrailingLineBreaks, escapeRegexString } = require('../utils/regex')
|
|
3
|
+
const sectionToc = require('./sectionToc')
|
|
4
|
+
/**
|
|
5
|
+
* Options for configuring the table of contents.
|
|
6
|
+
* @typedef {Object} ToCTransformOptions
|
|
7
|
+
* @property {boolean} [firsth1=false] - Show the first h1 of the document in the table of contents. Default is `false`.
|
|
8
|
+
* @property {boolean} [collapse=false] - Collapse the table of contents in a detail accordion. Default is `false`.
|
|
9
|
+
* @property {string} [collapseText] - Text for the summary of the table of contents accordion.
|
|
10
|
+
* @property {string} [excludeText="Table of Contents"] - Text to exclude in the table of contents. Default is `Table of Contents`.
|
|
11
|
+
* @property {number} [maxDepth=4] - Maximum depth of headings to include in the table of contents. Default is `4`.
|
|
12
|
+
* @example
|
|
13
|
+
```md
|
|
14
|
+
<!-- doc-gen (TOC) -->
|
|
15
|
+
toc will be generated here
|
|
16
|
+
<!-- end-doc-gen -->
|
|
17
|
+
```
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
module.exports = async function TOC(api) {
|
|
21
|
+
// console.log("TOC API", api)
|
|
22
|
+
const { currentFileContent, srcPath, getBlockDetails } = api
|
|
23
|
+
/** @type {ToCTransformOptions} */
|
|
24
|
+
const options = api.options || {}
|
|
25
|
+
// console.log("TOC OPTIONS", options)
|
|
26
|
+
|
|
27
|
+
// process.exit(1)
|
|
28
|
+
const opts = options || {}
|
|
29
|
+
const includeToc = opts.includeToc || false
|
|
30
|
+
const isSub = opts.sub
|
|
31
|
+
|
|
32
|
+
if (isSub) {
|
|
33
|
+
return sectionToc(api)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
opts.firsth1 = (opts.firsth1) ? true : false
|
|
37
|
+
let contents = currentFileContent
|
|
38
|
+
// console.log('contents', contents)
|
|
39
|
+
|
|
40
|
+
let collapseText = opts.collapseText
|
|
41
|
+
|
|
42
|
+
let debugFileMatch
|
|
43
|
+
// console.log('config', config.originalPath)
|
|
44
|
+
// debugFileMatch = config.originalPath.match(/packages\/analytics\/README\.md/)
|
|
45
|
+
|
|
46
|
+
// https://www.npmjs.com/package/@technote-space/toc-generator
|
|
47
|
+
const tocOptions = {
|
|
48
|
+
// mode: 'github.com', // github.com | bitbucket.org | gitlab.com | nodejs.org | ghost.org (default: github.com)
|
|
49
|
+
//isCustomMode: true,
|
|
50
|
+
openingComment: '',
|
|
51
|
+
closingComment: '',
|
|
52
|
+
maxDepth: (opts.maxDepth) ? Number(opts.maxDepth) : 4,
|
|
53
|
+
normalizeLevels: true,
|
|
54
|
+
trimLeadingHeading: true,
|
|
55
|
+
// maxHeaderLevel: 2, // default: 4
|
|
56
|
+
// title: '**Table of Contents**',
|
|
57
|
+
// isNotitle: true,
|
|
58
|
+
// isFolding: true,
|
|
59
|
+
// entryPrefix: '*',
|
|
60
|
+
// processAll: true,
|
|
61
|
+
// updateOnly: true,
|
|
62
|
+
// openingComment: '<!-- toc -->',
|
|
63
|
+
// closingComment: '<!-- tocstop --> ',
|
|
64
|
+
// checkOpeningComments: ['<!-- toc '],
|
|
65
|
+
// checkClosingComments: ['<!-- tocstop '],
|
|
66
|
+
// isCustomMode: false,
|
|
67
|
+
// customTemplate: '<p align="center">${ITEMS}</p>',
|
|
68
|
+
// itemTemplate: '<a href="${LINK}">${TEXT}</a>',
|
|
69
|
+
// separator: '<span>|</span>',
|
|
70
|
+
// footer: 'end',
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Exclude Table of contents section from toc */
|
|
74
|
+
if (!includeToc) {
|
|
75
|
+
tocOptions.filter = (item) => {
|
|
76
|
+
const text = item.text.trim().toLowerCase()
|
|
77
|
+
return text !== 'table of contents' && text !== 'toc'
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const tocObject = generateToc(contents, tocOptions)
|
|
82
|
+
// console.log("TOC OPTIONS", contents)
|
|
83
|
+
// console.log("TOC OBJECT", tocObject)
|
|
84
|
+
// process.exit(1)
|
|
85
|
+
// let outputText = t.wrappedToc || ''
|
|
86
|
+
let outputText = tocObject.text || ''
|
|
87
|
+
|
|
88
|
+
// console.log('outputText')
|
|
89
|
+
// console.log(outputText)
|
|
90
|
+
//process.exit(1)
|
|
91
|
+
|
|
92
|
+
// If collapse wrap in <details>
|
|
93
|
+
if (opts.collapse || opts.collapseText) {
|
|
94
|
+
return `<details>
|
|
95
|
+
<summary>${collapseText || 'Table of Contents'}</summary>
|
|
96
|
+
|
|
97
|
+
${outputText
|
|
98
|
+
// Replace leading double spaces
|
|
99
|
+
.replace(/^\n*/g, '')
|
|
100
|
+
// Replace trailing double spaces
|
|
101
|
+
.replace(/\n*$/g, '')
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
</details>`
|
|
105
|
+
}
|
|
106
|
+
return outputText.replace(removeLeadingAndTrailingLineBreaks, '')
|
|
107
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function details(text, title) {
|
|
2
|
+
const summaryRender = title ? `\n<summary>${title}</summary>` : ''
|
|
3
|
+
return `<details>${summaryRender}
|
|
4
|
+
|
|
5
|
+
${text
|
|
6
|
+
// Replace leading double spaces
|
|
7
|
+
.replace(/^\n*/g, '')
|
|
8
|
+
// Replace trailing double spaces
|
|
9
|
+
.replace(/\n*$/g, '')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
</details>`
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
module.exports = details
|
package/{lib → src}/utils/toc.js
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { generateToc
|
|
1
|
+
const { generateToc } = require('@davidwells/md-utils')
|
|
2
2
|
const { removeLeadingAndTrailingLineBreaks, escapeRegexString } = require('./regex')
|
|
3
3
|
const { findMinIndent } = require('./text')
|
|
4
4
|
const { readFile } = require('./fs')
|
|
@@ -28,7 +28,7 @@ const { readFile } = require('./fs')
|
|
|
28
28
|
* @param {TocAPI} api
|
|
29
29
|
* @returns
|
|
30
30
|
*/
|
|
31
|
-
async function
|
|
31
|
+
async function odlGenerateToc({
|
|
32
32
|
options = {},
|
|
33
33
|
fileContent,
|
|
34
34
|
srcPath,
|
|
@@ -57,7 +57,9 @@ async function generateToc({
|
|
|
57
57
|
//isCustomMode: true,
|
|
58
58
|
openingComment: '',
|
|
59
59
|
closingComment: '',
|
|
60
|
-
|
|
60
|
+
maxDepth: (opts.maxDepth) ? Number(opts.maxDepth) : 4,
|
|
61
|
+
normalizeLevels: true,
|
|
62
|
+
trimLeadingHeading: true,
|
|
61
63
|
// maxHeaderLevel: 2, // default: 4
|
|
62
64
|
// title: '**Table of Contents**',
|
|
63
65
|
// isNotitle: true,
|
|
@@ -75,12 +77,35 @@ async function generateToc({
|
|
|
75
77
|
// separator: '<span>|</span>',
|
|
76
78
|
// footer: 'end',
|
|
77
79
|
}
|
|
78
|
-
|
|
79
|
-
const tocObject = generateTocUtils(contents)
|
|
80
|
-
|
|
80
|
+
// console.log("TOC OPTIONS", contents)
|
|
81
|
+
const tocObject = generateTocUtils(contents, tocOptions)
|
|
82
|
+
// console.log("TOC OBJECT", tocObject)
|
|
83
|
+
// process.exit(1)
|
|
81
84
|
// let outputText = t.wrappedToc || ''
|
|
82
85
|
let outputText = tocObject.text || ''
|
|
83
86
|
|
|
87
|
+
console.log('outputText')
|
|
88
|
+
console.log(outputText)
|
|
89
|
+
//process.exit(1)
|
|
90
|
+
|
|
91
|
+
// If collapse wrap in <details>
|
|
92
|
+
if (opts.collapse) {
|
|
93
|
+
return `<details>
|
|
94
|
+
<summary>${collapseText || 'Table of Contents'}</summary>
|
|
95
|
+
|
|
96
|
+
${outputText
|
|
97
|
+
// Replace leading double spaces
|
|
98
|
+
.replace(/^\n*/g, '')
|
|
99
|
+
// Replace trailing double spaces
|
|
100
|
+
.replace(/\n*$/g, '')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
</details>`
|
|
104
|
+
}
|
|
105
|
+
console.log("OUTPUT TEXT", outputText)
|
|
106
|
+
return outputText.replace(removeLeadingAndTrailingLineBreaks, '')
|
|
107
|
+
process.exit(1)
|
|
108
|
+
|
|
84
109
|
if (debugFileMatch) {
|
|
85
110
|
console.log('before firsth1 removal', outputText)
|
|
86
111
|
}
|
|
@@ -282,6 +307,7 @@ ${outputText
|
|
|
282
307
|
|
|
283
308
|
</details>`
|
|
284
309
|
}
|
|
310
|
+
console.log("OUTPUT TEXT", outputText)
|
|
285
311
|
return outputText.replace(removeLeadingAndTrailingLineBreaks, '')
|
|
286
312
|
}
|
|
287
313
|
|
|
@@ -315,5 +341,5 @@ function excludeTocItem(str, excludeText) {
|
|
|
315
341
|
}
|
|
316
342
|
|
|
317
343
|
module.exports = {
|
|
318
|
-
|
|
344
|
+
odlGenerateToc
|
|
319
345
|
}
|
package/lib/transforms/file.js
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const isLocalPath = require('is-local-path')
|
|
4
|
-
|
|
5
|
-
module.exports = function FILE(api) {
|
|
6
|
-
/*
|
|
7
|
-
console.log('FILE API', api)
|
|
8
|
-
/** */
|
|
9
|
-
const { options, srcPath } = api
|
|
10
|
-
if (!options.src) {
|
|
11
|
-
return false
|
|
12
|
-
}
|
|
13
|
-
let fileContents = ''
|
|
14
|
-
if (isLocalPath(options.src)) {
|
|
15
|
-
const fileDir = path.dirname(srcPath)
|
|
16
|
-
const resolvedFilePath = path.resolve(fileDir, options.src)
|
|
17
|
-
try {
|
|
18
|
-
// console.log('READFILE', resolvedFilePath)
|
|
19
|
-
fileContents = fs.readFileSync(resolvedFilePath, 'utf8')
|
|
20
|
-
} catch (e) {
|
|
21
|
-
// if demo path. Todo probably remove
|
|
22
|
-
if (options.src === './path/to/file') {
|
|
23
|
-
return api.content
|
|
24
|
-
}
|
|
25
|
-
console.log(`FILE NOT FOUND ${resolvedFilePath}`)
|
|
26
|
-
throw e
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// trim leading and trailing spaces/line breaks in code and keeps the indentation of the first non-empty line
|
|
31
|
-
fileContents = fileContents.replace(/^(?:[\t ]*(?:\r?\n|\r))+|\s+$/g, '')
|
|
32
|
-
|
|
33
|
-
return fileContents
|
|
34
|
-
|
|
35
|
-
return `<!-- The below content is automatically added from ${options.src} -->
|
|
36
|
-
${fileContents}`
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// maybe support...
|
|
40
|
-
function legacyCODE(content, options, config) {
|
|
41
|
-
|
|
42
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
const { generateToc } = require('../utils/toc')
|
|
2
|
-
|
|
3
|
-
module.exports = async function sectionToc(api) {
|
|
4
|
-
// console.log("sectionToc", api)
|
|
5
|
-
const { options, currentFileContent, srcPath, getBlockDetails } = api
|
|
6
|
-
const opts = options || {}
|
|
7
|
-
const subToc = await generateToc({
|
|
8
|
-
options: {
|
|
9
|
-
...opts,
|
|
10
|
-
// Set sub table of contents
|
|
11
|
-
sub: true
|
|
12
|
-
},
|
|
13
|
-
fileContent: currentFileContent,
|
|
14
|
-
srcPath,
|
|
15
|
-
getBlockDetails: getBlockDetails
|
|
16
|
-
})
|
|
17
|
-
return subToc
|
|
18
|
-
}
|
package/lib/transforms/toc.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
const { generateToc } = require('../utils/toc')
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Options for configuring the table of contents.
|
|
5
|
-
* @typedef {Object} ToCTransformOptions
|
|
6
|
-
* @property {boolean} [firsth1=false] - Show the first h1 of the document in the table of contents. Default is `false`.
|
|
7
|
-
* @property {boolean} [collapse=false] - Collapse the table of contents in a detail accordion. Default is `false`.
|
|
8
|
-
* @property {string} [collapseText] - Text for the summary of the table of contents accordion.
|
|
9
|
-
* @property {string} [excludeText="Table of Contents"] - Text to exclude in the table of contents. Default is `Table of Contents`.
|
|
10
|
-
* @property {number} [maxDepth=4] - Maximum depth of headings to include in the table of contents. Default is `4`.
|
|
11
|
-
* @example
|
|
12
|
-
```md
|
|
13
|
-
<!-- doc-gen (TOC) -->
|
|
14
|
-
toc will be generated here
|
|
15
|
-
<!-- end-doc-gen -->
|
|
16
|
-
```
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
module.exports = async function TOC(api) {
|
|
20
|
-
// console.log("TOC API", api)
|
|
21
|
-
const { currentFileContent, srcPath, getBlockDetails } = api
|
|
22
|
-
/** @type {ToCTransformOptions} */
|
|
23
|
-
const options = api.options || {}
|
|
24
|
-
const toc = await generateToc({
|
|
25
|
-
options,
|
|
26
|
-
srcPath,
|
|
27
|
-
getBlockDetails: getBlockDetails,
|
|
28
|
-
fileContent: currentFileContent,
|
|
29
|
-
})
|
|
30
|
-
return toc
|
|
31
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/{lib → src}/cli.test.js
RENAMED
|
File without changes
|
/package/{lib → src}/defaults.js
RENAMED
|
File without changes
|