markdown-magic 3.4.2 → 3.6.1

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.
Files changed (51) hide show
  1. package/README.md +18 -16
  2. package/cli.js +1 -1
  3. package/package.json +12 -12
  4. package/{lib → src}/block-parser.js +4 -0
  5. package/{lib → src}/index.js +1 -1
  6. package/{lib → src}/process-contents.js +28 -4
  7. package/{lib → src}/transforms/file.js +6 -23
  8. package/{lib → src}/transforms/index.js +8 -6
  9. package/{lib → src}/transforms/remote.js +13 -1
  10. package/src/transforms/sectionToc.js +37 -0
  11. package/src/transforms/toc.js +107 -0
  12. package/src/utils/details.js +15 -0
  13. package/src/utils/format-md.js +33 -0
  14. package/{lib → src}/utils/toc.js +33 -7
  15. package/lib/transforms/sectionToc.js +0 -18
  16. package/lib/transforms/toc.js +0 -31
  17. /package/{lib → src}/argparse/README.md +0 -0
  18. /package/{lib → src}/argparse/argparse.js +0 -0
  19. /package/{lib → src}/argparse/argparse.test.js +0 -0
  20. /package/{lib → src}/argparse/index.js +0 -0
  21. /package/{lib → src}/argparse/splitOutsideQuotes.js +0 -0
  22. /package/{lib → src}/argparse/splitOutsideQuotes.test.js +0 -0
  23. /package/{lib → src}/block-parser-js.test.js +0 -0
  24. /package/{lib → src}/block-parser.test.js +0 -0
  25. /package/{lib → src}/cli.js +0 -0
  26. /package/{lib → src}/cli.test.js +0 -0
  27. /package/{lib → src}/defaults.js +0 -0
  28. /package/{lib → src}/globparse.js +0 -0
  29. /package/{lib → src}/globparse.test.js +0 -0
  30. /package/{lib → src}/index.test.js +0 -0
  31. /package/{lib → src}/process-file.js +0 -0
  32. /package/{lib → src}/transforms/code/index.js +0 -0
  33. /package/{lib → src}/transforms/code/resolve-github-file.js +0 -0
  34. /package/{lib → src}/transforms/code/resolve-github-file.test.js +0 -0
  35. /package/{lib → src}/transforms/wordCount.js +0 -0
  36. /package/{lib → src}/types.js +0 -0
  37. /package/{lib → src}/utils/fs.js +0 -0
  38. /package/{lib → src}/utils/fs.test.js +0 -0
  39. /package/{lib → src}/utils/hash-file.js +0 -0
  40. /package/{lib → src}/utils/index.js +0 -0
  41. /package/{lib → src}/utils/load-config.js +0 -0
  42. /package/{lib → src}/utils/logs.js +0 -0
  43. /package/{lib → src}/utils/regex-timeout.js +0 -0
  44. /package/{lib → src}/utils/regex.js +0 -0
  45. /package/{lib → src}/utils/remoteRequest.js +0 -0
  46. /package/{lib → src}/utils/sortOrder.js +0 -0
  47. /package/{lib → src}/utils/string-break.js +0 -0
  48. /package/{lib → src}/utils/syntax.js +0 -0
  49. /package/{lib → src}/utils/text.js +0 -0
  50. /package/{lib → src}/utils/text.test.js +0 -0
  51. /package/{lib → src}/utils/toposort.js +0 -0
package/README.md CHANGED
@@ -19,7 +19,7 @@ This `README.md` is generated with `markdown-magic` [view the raw file](https://
19
19
  [Video demo](http://www.youtube.com/watch?v=4V2utrvxwJ8) • [Example Repo](https://github.com/DavidWells/repo-using-markdown-magic)
20
20
 
21
21
  ## Table of Contents
22
- <!-- ⛔️ MD-MAGIC-EXAMPLE:START TOC collapse=true collapseText="Click to expand" -->
22
+ <!-- ⛔️ MD-MAGIC-EXAMPLE:START TOC collapseText="Click to expand" -->
23
23
  <details>
24
24
  <summary>Click to expand</summary>
25
25
 
@@ -108,7 +108,7 @@ If you have a `markdown.config.js` file where `markdown-magic` is invoked, it wi
108
108
  ### Running programmatically
109
109
 
110
110
  ```js
111
- const { markdownMagic } = require('../lib')
111
+ const { markdownMagic } = require('../src')
112
112
 
113
113
  /* By default all .md files in cwd will be processed */
114
114
  markdownMagic().then((results) => {
@@ -185,7 +185,7 @@ content to be replaced
185
185
  ```
186
186
  <!-- ⛔️ MD-MAGIC-EXAMPLE:END *-->
187
187
 
188
- <!-- ⛔️ MD-MAGIC-EXAMPLE:START JSDocs path="./lib/index.js" -->
188
+ <!-- ⛔️ MD-MAGIC-EXAMPLE:START JSDocs path="./src/index.js" -->
189
189
  ### API
190
190
 
191
191
  Markdown Magic Instance
@@ -231,7 +231,9 @@ Below is the main config for `markdown-magic`
231
231
  | `dryRun` (optional) | `boolean` | See planned execution of matched blocks. Default: `false` |
232
232
  | `debug` (optional) | `boolean` | See debug details. Default: `false` |
233
233
  | `silent` (optional) | `boolean` | Silence all console output. Default: `false` |
234
+ | `applyTransformsToSource` (optional) | `boolean` | Apply transforms to source file. Default is true. Default: `true` |
234
235
  | `failOnMissingTransforms` (optional) | `boolean` | Fail if transform functions are missing. Default skip blocks. Default: `false` |
236
+ | `failOnMissingRemote` (optional) | `boolean` | Fail if remote file is missing. Default: `true` |
235
237
 
236
238
  #### `OutputConfig`
237
239
 
@@ -259,15 +261,15 @@ Result of markdown processing
259
261
 
260
262
  Markdown Magic comes with a couple of built-in transforms for you to use or you can extend it with your own transforms. See 'Custom Transforms' below.
261
263
 
262
- <!-- ⛔️ MD-MAGIC-EXAMPLE:START JSDocs path="./lib/transforms/index.js" -->
264
+ <!-- ⛔️ MD-MAGIC-EXAMPLE:START JSDocs path="./src/transforms/index.js" -->
263
265
  ### > TOC
264
266
 
265
267
  Generate table of contents from markdown file
266
268
 
267
269
  **Options:**
268
270
  - `firsth1` - *boolean* - (optional): Show first h1 of doc in table of contents. Default `false`
269
- - `collapse` - *boolean* - (optional): Collapse the table of contents in a detail accordian. Default `false`
270
- - `collapseText` - *string* - (optional): Text the toc accordian summary
271
+ - `collapse` - *boolean* - (optional): Collapse the table of contents in a detail accordion. Default `false`
272
+ - `collapseText` - *string* - (optional): Text the toc accordion summary
271
273
  - `excludeText` - *string* - (optional): Text to exclude in the table of contents. Default `Table of Contents`
272
274
  - `maxDepth` - *number* - (optional): Max depth of headings. Default 4
273
275
 
@@ -278,7 +280,7 @@ toc will be generated here
278
280
  <!-- end-doc-gen -->
279
281
  ```
280
282
 
281
- Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
283
+ Default `matchWord` is `doc-gen`
282
284
 
283
285
  ---
284
286
 
@@ -305,12 +307,12 @@ This content will be dynamically replaced with code from the file
305
307
  ```
306
308
 
307
309
  ```md
308
- <!-- doc-gen CODE src="./relative/path/to/code.js" lines=22-44 -->
309
- This content will be dynamically replaced with code from the file lines 22 through 44
310
- <!-- end-doc-gen -->
311
- ```
310
+ <!-- doc-gen CODE src="./relative/path/to/code.js" lines=22-44 -->
311
+ This content will be dynamically replaced with code from the file lines 22 through 44
312
+ <!-- end-doc-gen -->
313
+ ```
312
314
 
313
- Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
315
+ Default `matchWord` is `doc-gen`
314
316
 
315
317
  ---
316
318
 
@@ -333,7 +335,7 @@ This content will be dynamically replaced from the local file
333
335
  <!-- end-doc-gen -->
334
336
  ```
335
337
 
336
- Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
338
+ Default `matchWord` is `doc-gen`
337
339
 
338
340
  ---
339
341
 
@@ -356,7 +358,7 @@ This content will be dynamically replaced from the remote url
356
358
  <!-- end-doc-gen -->
357
359
  ```
358
360
 
359
- Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
361
+ Default `matchWord` is `doc-gen`
360
362
 
361
363
  ---
362
364
 
@@ -414,8 +416,8 @@ The below code is used to generate **this markdown file** via the plugin system.
414
416
  const path = require('path')
415
417
  const { readFileSync } = require('fs')
416
418
  const { parseComments } = require('doxxx')
417
- const { markdownMagic } = require('../lib')
418
- const { deepLog } = require('../lib/utils/logs')
419
+ const { markdownMagic } = require('../src')
420
+ const { deepLog } = require('../src/utils/logs')
419
421
 
420
422
  const config = {
421
423
  matchWord: 'MD-MAGIC-EXAMPLE', // default matchWord is AUTO-GENERATED-CONTENT
package/cli.js CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  const mri = require('mri')
3
- const { runCli } = require('./lib/cli')
3
+ const { runCli } = require('./src/cli')
4
4
  const argv = process.argv.slice(2)
5
5
  const cliArgs = mri(argv)
6
6
 
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "markdown-magic",
3
- "version": "3.4.2",
3
+ "version": "3.6.1",
4
4
  "description": "Automatically update markdown files with content from external sources",
5
- "main": "lib/index.js",
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
- "/lib"
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:lib && npm run test:test && echo 'tests done'",
23
- "test:lib": "uvu lib '.test.([mc]js|[jt]sx?)$'",
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 lib 'block-parser.test.([mc]js|[jt]sx?)$'",
26
- "test:cli": "uvu lib 'cli.test.([mc]js|[jt]sx?)$'",
27
- "test:md": "uvu lib 'md.test.([mc]js|[jt]sx?)$'",
28
- "test:fs": "uvu lib 'fs.test.([mc]js|[jt]sx?)$'",
29
- "test:js": "uvu lib 'block-parser-js.test.([mc]js|[jt]sx?)$'",
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 lib 'text.test.([mc]js|[jt]sx?)$'",
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,7 +44,7 @@
44
44
  "url": "https://github.com/DavidWells/markdown-magic"
45
45
  },
46
46
  "dependencies": {
47
- "@davidwells/md-utils": "^0.0.46",
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",
@@ -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,
@@ -19,7 +19,7 @@ const { parseMarkdown } = require('@davidwells/md-utils')
19
19
  const { success, error, info, convertHrtime, deepLog } = require('./utils/logs')
20
20
  const { OPEN_WORD, CLOSE_WORD, DEFAULT_GLOB_PATTERN } = require('./defaults')
21
21
  const { getBlockRegex, parseBlocks } = require('./block-parser')
22
- const toposort = require('./utils/toposort');
22
+ const toposort = require('./utils/toposort')
23
23
  // const { hashFile } = require('./utils/hash-file')
24
24
  // const { getBlockRegex } = require('./block-parser')
25
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
- const indent = indentString(fix, preserveIndent)
211
- const newCont = `${openTag}${indent}${closeTag}`
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)) {
@@ -1,8 +1,7 @@
1
1
  const path = require('path')
2
2
  const fs = require('fs')
3
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')
4
+ const { formatMd } = require('../utils/format-md')
6
5
 
7
6
  module.exports = function FILE(api) {
8
7
  /*
@@ -32,27 +31,11 @@ module.exports = function FILE(api) {
32
31
  // trim leading and trailing spaces/line breaks in code and keeps the indentation of the first non-empty line
33
32
  fileContents = fileContents.replace(/^(?:[\t ]*(?:\r?\n|\r))+|\s+$/g, '')
34
33
 
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
- }
34
+ const ext = path.extname(options.src).toLowerCase()
35
+ const isMarkdown = ext === '.md' || ext === '.markdown' || ext === '.mdown' || ext === '.mdx'
36
+
37
+ if (isMarkdown) {
38
+ fileContents = formatMd(fileContents, options)
56
39
  }
57
40
 
58
41
  if (options.textBefore) {
@@ -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 accordian. Default `false`
15
- * - `collapseText` - *string* - (optional): Text the toc accordian summary
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 `MATCHWORD` is `AUTO-GENERATED-CONTENT`
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 `MATCHWORD` is `AUTO-GENERATED-CONTENT`
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 `MATCHWORD` is `AUTO-GENERATED-CONTENT`
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 `MATCHWORD` is `AUTO-GENERATED-CONTENT`
106
+ * Default `matchWord` is `doc-gen`
105
107
  *
106
108
  * ---
107
109
  * @param {string} content The current content of the comment block
@@ -1,18 +1,30 @@
1
+ const path = require('path')
1
2
  const { remoteRequest } = require('../utils/remoteRequest')
3
+ const { formatMd } = require('../utils/format-md')
2
4
 
3
5
  module.exports = async function REMOTE(api) {
4
6
  // console.log('REMOTE api', api)
5
7
  const { options, content, settings } = api
6
8
  const { regex } = settings
9
+ const remoteUrl = options.url || options.src || options.URL || options.Url
7
10
 
8
11
  // console.log('MAKE REMOTE REQUEST')
9
- const remoteContent = await remoteRequest(options.url, settings, api.srcPath)
12
+ let remoteContent = await remoteRequest(remoteUrl, settings, api.srcPath)
10
13
  if (!remoteContent) {
11
14
  return content
12
15
  }
16
+
17
+ const ext = path.extname(remoteUrl).toLowerCase()
18
+ const isMarkdown = ext === '.md' || ext === '.markdown' || ext === '.mdown' || ext === '.mdx'
19
+
20
+ if (isMarkdown) {
21
+ remoteContent = formatMd(remoteContent, options)
22
+ }
23
+
13
24
  if (options.keepComments) {
14
25
  return remoteContent
15
26
  }
27
+
16
28
  // console.log('REMOTE', remoteContent)
17
29
  return remoteContent.replace(regex.open, '').replace(regex.close, '')
18
30
  }
@@ -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
+ }
@@ -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
@@ -0,0 +1,33 @@
1
+ const { findFrontmatter } = require('@davidwells/md-utils/find-frontmatter')
2
+ const { removeLeadingH1 } = require('@davidwells/md-utils/string-utils')
3
+
4
+ function formatMd(content, options = {}) {
5
+ let fileContents = content
6
+ if (options.removeLeadingH1) {
7
+ fileContents = removeLeadingH1(fileContents)
8
+ }
9
+
10
+ // Shift headers up or down by the specified number of levels if shiftHeaders is enabled and file is markdown
11
+ if (options.shiftHeaders) {
12
+ fileContents = fileContents.replace(/^(#{1,6})\s/gm, (match, hashes) => {
13
+ const currentLevel = hashes.length;
14
+ const shiftAmount = options.shiftHeaders;
15
+ const newLevel = Math.max(1, Math.min(6, currentLevel + shiftAmount));
16
+ return '#'.repeat(newLevel) + ' ';
17
+ })
18
+ }
19
+
20
+ /* automatically trim frontmatter if file is markdown */
21
+ if (options.trimFrontmatter !== false) {
22
+ const frontmatter = findFrontmatter(fileContents)
23
+ if (frontmatter && frontmatter.frontMatterRaw) {
24
+ fileContents = fileContents.replace(frontmatter.frontMatterRaw, '')
25
+ }
26
+ }
27
+
28
+ return fileContents
29
+ }
30
+
31
+ module.exports = {
32
+ formatMd
33
+ }
@@ -1,4 +1,4 @@
1
- const { generateToc : generateTocUtils } = require('@davidwells/md-utils')
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 generateToc({
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
- maxHeaderLevel: (opts.maxDepth) ? Number(opts.maxDepth) : 4,
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
- generateToc
344
+ odlGenerateToc
319
345
  }
@@ -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
- }
@@ -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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes