markdown-magic 3.6.4 → 3.7.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 CHANGED
@@ -43,6 +43,8 @@ This `README.md` is generated with `markdown-magic` [view the raw file](https://
43
43
  - [> CODE](#-code)
44
44
  - [> FILE](#-file)
45
45
  - [> REMOTE](#-remote)
46
+ - [> fileTree](#-filetree)
47
+ - [> install](#-install)
46
48
  - [Inline transforms](#inline-transforms)
47
49
  - [Legacy v1 & v2 plugins](#legacy-v1--v2-plugins)
48
50
  - [Adding Custom Transforms](#adding-custom-transforms)
@@ -267,7 +269,7 @@ Markdown Magic comes with a couple of built-in transforms for you to use or you
267
269
  Generate table of contents from markdown file
268
270
 
269
271
  **Options:**
270
- - `firsth1` - *boolean* - (optional): Show first h1 of doc in table of contents. Default `false`
272
+ - `firstH1` - *boolean* - (optional): Show first h1 of doc in table of contents. Default `false`
271
273
  - `collapse` - *boolean* - (optional): Collapse the table of contents in a detail accordion. Default `false`
272
274
  - `collapseText` - *string* - (optional): Text the toc accordion summary
273
275
  - `excludeText` - *string* - (optional): Text to exclude in the table of contents. Default `Table of Contents`
@@ -362,6 +364,99 @@ Default `matchWord` is `doc-gen`
362
364
 
363
365
  ---
364
366
 
367
+ | Name | Type | Description |
368
+ |:---------------------------|:---------------:|:-----------|
369
+ | `content` | `string` | The current content of the comment block. |
370
+ | `options` | `object` | The options passed in from the comment declaration. |
371
+
372
+ ### > fileTree
373
+
374
+ Generate a file tree table of contents
375
+
376
+ **Options:**
377
+ - `src` (optional): The directory path to generate the file tree for. Default `.` (current directory)
378
+ - `maxDepth` (optional): Maximum depth to traverse in the directory tree. Default `3`
379
+ - `includeFiles` (optional): Whether to include files in the tree or just directories. Default `true`
380
+ - `exclude` (optional): Array of glob patterns to exclude from the tree. Default `[]`
381
+ - `showSize` (optional): Whether to show file sizes. Default `false`
382
+ - `format` (optional): Output format: "tree" or "list". Default `"tree"`
383
+
384
+ **Example:**
385
+ ```md
386
+ <!-- doc-gen fileTree src="./src" maxDepth=2 -->
387
+ file tree will be generated here
388
+ <!-- end-doc-gen -->
389
+ ```
390
+
391
+ **Example Output (tree format):**
392
+ ```
393
+ └── src/
394
+ ├── transforms/
395
+ │ ├── code/
396
+ │ │ ...
397
+ │ ├── fileTree.js
398
+ │ ├── index.js
399
+ │ └── toc.js
400
+ ├── utils/
401
+ │ ├── fs.js
402
+ │ ├── logs.js
403
+ │ └── text.js
404
+ └── index.js
405
+ ```
406
+
407
+ **Example Output (list format):**
408
+ ```md
409
+ - **src/**
410
+ - **transforms/**
411
+ - **code/**
412
+ - ...
413
+ - fileTree.js
414
+ - index.js
415
+ - toc.js
416
+ - **utils/**
417
+ - fs.js
418
+ - logs.js
419
+ - text.js
420
+ - index.js
421
+ ```
422
+
423
+ **Example with file sizes:**
424
+ ```
425
+ └── src/
426
+ ├── index.js (15.2 KB)
427
+ └── package.json (552 B)
428
+ ```
429
+
430
+ Default `matchWord` is `doc-gen`
431
+
432
+ ---
433
+
434
+ | Name | Type | Description |
435
+ |:---------------------------|:---------------:|:-----------|
436
+ | `content` | `string` | The current content of the comment block. |
437
+ | `options` | `object` | The options passed in from the comment declaration. |
438
+
439
+ ### > install
440
+
441
+ Generate installation instructions in a markdown table format
442
+
443
+ **Options:**
444
+ - `packageName` (optional): The name of the package to install. If not provided, will try to read from package.json
445
+ - `isDev` (optional): Whether to install the package as a dev dependency. Default `false`
446
+ - `header` (optional): The header to use for the installation instructions. Default `# Installation`
447
+ - `body` (optional): The body to use for the installation instructions. Default `Install the \`${packageName}\` cli using your favorite package manager.`
448
+
449
+ **Example:**
450
+ ```md
451
+ <!-- doc-gen install -->
452
+ Installation instructions will be generated here
453
+ <!-- end-doc-gen -->
454
+ ```
455
+
456
+ Default `matchWord` is `doc-gen`
457
+
458
+ ---
459
+
365
460
  | Name | Type | Description |
366
461
  |:---------------------------|:---------------:|:-----------|
367
462
  | `content` | `string` | The current content of the comment block. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdown-magic",
3
- "version": "3.6.4",
3
+ "version": "3.7.0",
4
4
  "description": "Automatically update markdown files with content from external sources",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/index.js CHANGED
@@ -1,10 +1,11 @@
1
1
  const path = require('path')
2
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+
3
+ const moduleAlias = require('module-alias') // "Fix" for punycode dep warning in node 22+
4
+ moduleAlias.addAlias('punycode', 'punycode/') // "Fix" for punycode dep warning in node 22+
5
5
  const { glob, globWithGit } = require('smart-glob')
6
6
  const codeTransform = require('./transforms/code')
7
7
  const fileTransform = require('./transforms/file')
8
+ const fileTreeTransform = require('./transforms/fileTree')
8
9
  const tocTransform = require('./transforms/toc')
9
10
  const sectionTocTransform = require('./transforms/sectionToc')
10
11
  const wordCountTransform = require('./transforms/wordCount')
@@ -32,6 +33,7 @@ const LINE = '──────────────────────
32
33
  const defaultTransforms = {
33
34
  CODE: codeTransform,
34
35
  FILE: fileTransform,
36
+ fileTree: fileTreeTransform,
35
37
  TOC: tocTransform,
36
38
  sectionToc: sectionTocTransform,
37
39
  wordCount: wordCountTransform,
@@ -113,7 +115,7 @@ const defaultOptions = {
113
115
  })
114
116
  */
115
117
  async function markdownMagic(globOrOpts = {}, options = {}) {
116
- const hrstart = process.hrtime.bigint()
118
+ const hrStart = process.hrtime.bigint()
117
119
  let opts = options || {}
118
120
  let globPat
119
121
  if (typeof globOrOpts === 'string' || Array.isArray(globOrOpts)) {
@@ -134,12 +136,13 @@ async function markdownMagic(globOrOpts = {}, options = {}) {
134
136
  useGitGlob = false,
135
137
  failOnMissingTransforms = false,
136
138
  failOnMissingRemote = true,
137
- dryRun = false,
138
139
  debug = false,
139
140
  syntax = 'md',
140
141
  silent = false,
141
142
  } = opts
142
143
 
144
+ let dryRun = opts.dryRun || opts.dry || opts.plan || false
145
+
143
146
  // @ts-ignore
144
147
  const outputDir = output.directory || opts.outputDir
145
148
  const removeComments = output.removeComments || false
@@ -203,7 +206,8 @@ async function markdownMagic(globOrOpts = {}, options = {}) {
203
206
  opts.globPattern = globs
204
207
 
205
208
  logger(LINE)
206
- success(` Markdown Magic Starting...`, silent, ' ')
209
+ const dryRunPostFix = (dryRun) ? ' - Dry run' : ''
210
+ success(` Markdown Magic Starting...${dryRunPostFix}`, silent, '✨ ')
207
211
  logger(`${LINE}\n`)
208
212
 
209
213
  info(` Searching for comment blocks...`, silent, '🔎 ')
@@ -213,9 +217,9 @@ async function markdownMagic(globOrOpts = {}, options = {}) {
213
217
  logger(`Searching: `, globs)
214
218
 
215
219
  if (dryRun || debug) {
220
+ logger()
216
221
  info(`Glob patterns:`, silent)
217
222
  logger(globs)
218
- logger()
219
223
  /*
220
224
  process.exit(1)
221
225
  /** */
@@ -360,7 +364,7 @@ async function markdownMagic(globOrOpts = {}, options = {}) {
360
364
  const sortedItems = sortedIds.map(id => blocks.find(item => item.id === id)).filter(Boolean);
361
365
 
362
366
  // topoSort(blocks)
363
- const orderedFiles = sortedItems.map((item) => item.id)
367
+ const orderedFiles = sortedItems.map((block) => block.id)
364
368
  // console.log('sortedItems', sortedItems)
365
369
  // console.log('orderedFiles', orderedFiles)
366
370
 
@@ -674,8 +678,17 @@ async function markdownMagic(globOrOpts = {}, options = {}) {
674
678
  process.exit(1)
675
679
  /** */
676
680
  logger()
677
- info(` Results:`, silent, "💫 ")
678
681
 
682
+ if (dryRun) {
683
+ logger('Dry run complete. Exiting markdown magic early.')
684
+ return {
685
+ errors,
686
+ filesChanged: [],
687
+ results: plan
688
+ }
689
+ }
690
+
691
+ info(` Results:`, silent, "💫 ")
679
692
  /*
680
693
  TODO:
681
694
  - Output to new file
@@ -686,14 +699,14 @@ async function markdownMagic(globOrOpts = {}, options = {}) {
686
699
  logErrors(errors)
687
700
  }
688
701
 
689
- const elasped = convertHrtime(process.hrtime.bigint() - hrstart)
702
+ const elapsed = convertHrtime(process.hrtime.bigint() - hrStart)
690
703
 
691
704
  logger()
692
705
  logger(`${LINE}`)
693
- success(`Markdown Magic Done. ${elasped.seconds} seconds`, silent)
706
+ success(`Markdown Magic Done. ${elapsed.seconds} seconds`, silent)
694
707
  logger(`${LINE}`)
695
708
  return {
696
- // @TODO maybe seperate changed and output files
709
+ // @TODO maybe separate changed and output files
697
710
  filesChanged: plan.filter(({ isChanged, isNewPath }) => isChanged || isNewPath).map(({ outputPath }) => outputPath),
698
711
  results: plan,
699
712
  errors,
@@ -0,0 +1,213 @@
1
+ const fs = require('fs')
2
+ const path = require('path')
3
+
4
+ /**
5
+ * Options for configuring the file tree table of contents.
6
+ * @typedef {Object} FileTreeTransformOptions
7
+ * @property {string} [src="."] - The directory path to generate the file tree for. Default is `.` (current directory).
8
+ * @property {number} [maxDepth=3] - Maximum depth to traverse in the directory tree. Default is `3`.
9
+ * @property {boolean} [includeFiles=true] - Whether to include files in the tree or just directories. Default is `true`.
10
+ * @property {string[]} [exclude=[]] - Array of glob patterns to exclude from the tree.
11
+ * @property {boolean} [showSize=false] - Whether to show file sizes. Default is `false`.
12
+ * @property {string} [format="tree"] - Output format: "tree" or "list". Default is `"tree"`.
13
+ * @example
14
+ ```md
15
+ <!-- doc-gen fileTree src="./src" maxDepth=2 -->
16
+ file tree will be generated here
17
+ <!-- end-doc-gen -->
18
+ ```
19
+ */
20
+
21
+ /**
22
+ * Generate a file tree table of contents
23
+ * @param {Object} api - The markdown-magic API object
24
+ * @returns {string} The generated file tree markdown
25
+ */
26
+ module.exports = function fileTree(api) {
27
+ const { options, srcPath } = api
28
+ /** @type {FileTreeTransformOptions} */
29
+ const opts = options || {}
30
+
31
+ const targetPath = opts.src || '.'
32
+ const maxDepth = opts.maxDepth ? Number(opts.maxDepth) : 3
33
+ const includeFiles = opts.includeFiles !== false
34
+ const exclude = opts.exclude || []
35
+ const showSize = opts.showSize === true
36
+ const format = opts.format || 'tree'
37
+
38
+ // Resolve the target path relative to the source file
39
+ const fileDir = path.dirname(srcPath)
40
+ const resolvedPath = path.resolve(fileDir, targetPath)
41
+
42
+ try {
43
+ const tree = generateFileTree(resolvedPath, {
44
+ maxDepth,
45
+ includeFiles,
46
+ exclude,
47
+ showSize,
48
+ currentDepth: 0
49
+ })
50
+
51
+ if (format === 'list') {
52
+ return formatAsList(tree)
53
+ }
54
+
55
+ return formatAsTree(tree)
56
+ } catch (error) {
57
+ console.error(`Error generating file tree for ${resolvedPath}:`, error.message)
58
+ return `<!-- Error: Could not generate file tree for ${targetPath} -->`
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Generate file tree structure
64
+ * @param {string} dirPath - Directory path to scan
65
+ * @param {Object} options - Options for tree generation
66
+ * @returns {Object} Tree structure
67
+ */
68
+ function generateFileTree(dirPath, options) {
69
+ const { maxDepth, includeFiles, exclude, showSize, currentDepth } = options
70
+
71
+ if (currentDepth >= maxDepth) {
72
+ return { type: 'directory', name: path.basename(dirPath), children: [], truncated: true }
73
+ }
74
+
75
+ let items
76
+ try {
77
+ items = fs.readdirSync(dirPath)
78
+ } catch (error) {
79
+ return { type: 'directory', name: path.basename(dirPath), children: [], error: true }
80
+ }
81
+
82
+ // Filter out excluded items
83
+ items = items.filter(item => {
84
+ // Skip hidden files and common ignored directories
85
+ if (item.startsWith('.') && !item.match(/\.(md|txt|json)$/)) {
86
+ return false
87
+ }
88
+ if (['node_modules', '.git', '.DS_Store', 'dist', 'build'].includes(item)) {
89
+ return false
90
+ }
91
+
92
+ // Apply custom exclude patterns
93
+ return !exclude.some(pattern => {
94
+ const regex = new RegExp(pattern.replace(/\*/g, '.*'))
95
+ return regex.test(item)
96
+ })
97
+ })
98
+
99
+ const children = []
100
+
101
+ for (const item of items) {
102
+ const itemPath = path.join(dirPath, item)
103
+ const stats = fs.statSync(itemPath)
104
+
105
+ if (stats.isDirectory()) {
106
+ const subTree = generateFileTree(itemPath, {
107
+ ...options,
108
+ currentDepth: currentDepth + 1
109
+ })
110
+ children.push(subTree)
111
+ } else if (includeFiles) {
112
+ children.push({
113
+ type: 'file',
114
+ name: item,
115
+ size: showSize ? stats.size : undefined
116
+ })
117
+ }
118
+ }
119
+
120
+ // Sort: directories first, then files, alphabetically
121
+ children.sort((a, b) => {
122
+ if (a.type !== b.type) {
123
+ return a.type === 'directory' ? -1 : 1
124
+ }
125
+ return a.name.localeCompare(b.name)
126
+ })
127
+
128
+ return {
129
+ type: 'directory',
130
+ name: path.basename(dirPath) || path.basename(path.resolve(dirPath)),
131
+ children
132
+ }
133
+ }
134
+
135
+ /**
136
+ * Format tree as ASCII tree structure
137
+ * @param {Object} tree - Tree structure
138
+ * @returns {string} Formatted tree
139
+ */
140
+ function formatAsTree(tree) {
141
+ const lines = []
142
+
143
+ function traverse(node, prefix = '', isLast = true) {
144
+ const connector = isLast ? '└── ' : '├── '
145
+ const name = node.type === 'directory' ? `${node.name}/` : node.name
146
+ const size = node.size ? ` (${formatBytes(node.size)})` : ''
147
+
148
+ lines.push(`${prefix}${connector}${name}${size}`)
149
+
150
+ if (node.children && node.children.length > 0) {
151
+ const extension = isLast ? ' ' : '│ '
152
+ node.children.forEach((child, index) => {
153
+ const childIsLast = index === node.children.length - 1
154
+ traverse(child, prefix + extension, childIsLast)
155
+ })
156
+ }
157
+
158
+ if (node.truncated) {
159
+ const extension = isLast ? ' ' : '│ '
160
+ lines.push(`${prefix}${extension}...`)
161
+ }
162
+ }
163
+
164
+ traverse(tree)
165
+
166
+ return '```\n' + lines.join('\n') + '\n```'
167
+ }
168
+
169
+ /**
170
+ * Format tree as a list
171
+ * @param {Object} tree - Tree structure
172
+ * @returns {string} Formatted list
173
+ */
174
+ function formatAsList(tree) {
175
+ const lines = []
176
+
177
+ function traverse(node, depth = 0) {
178
+ const indent = ' '.repeat(depth)
179
+ const name = node.type === 'directory' ? `**${node.name}/**` : node.name
180
+ const size = node.size ? ` *(${formatBytes(node.size)})*` : ''
181
+
182
+ lines.push(`${indent}- ${name}${size}`)
183
+
184
+ if (node.children && node.children.length > 0) {
185
+ node.children.forEach(child => {
186
+ traverse(child, depth + 1)
187
+ })
188
+ }
189
+
190
+ if (node.truncated) {
191
+ lines.push(`${indent} - ...`)
192
+ }
193
+ }
194
+
195
+ traverse(tree)
196
+
197
+ return lines.join('\n')
198
+ }
199
+
200
+ /**
201
+ * Format bytes as human readable string
202
+ * @param {number} bytes - Bytes to format
203
+ * @returns {string} Formatted string
204
+ */
205
+ function formatBytes(bytes) {
206
+ if (bytes === 0) return '0 B'
207
+
208
+ const k = 1024
209
+ const sizes = ['B', 'KB', 'MB', 'GB']
210
+ const i = Math.floor(Math.log(bytes) / Math.log(k))
211
+
212
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]
213
+ }
@@ -1,5 +1,6 @@
1
1
  const code = require('./code')
2
2
  const file = require('./file')
3
+ const fileTree = require('./fileTree')
3
4
  const remoteContent = require('./remote')
4
5
  const toc = require('./toc')
5
6
  const sectionToc = require('./sectionToc')
@@ -12,7 +13,7 @@ const transforms = {
12
13
  * Generate table of contents from markdown file
13
14
  *
14
15
  * **Options:**
15
- * - `firsth1` - *boolean* - (optional): Show first h1 of doc in table of contents. Default `false`
16
+ * - `firstH1` - *boolean* - (optional): Show first h1 of doc in table of contents. Default `false`
16
17
  * - `collapse` - *boolean* - (optional): Collapse the table of contents in a detail accordion. Default `false`
17
18
  * - `collapseText` - *string* - (optional): Text the toc accordion summary
18
19
  * - `excludeText` - *string* - (optional): Text to exclude in the table of contents. Default `Table of Contents`
@@ -112,6 +113,73 @@ const transforms = {
112
113
  * @return {string} Updated content to place in the content block
113
114
  */
114
115
  REMOTE: remoteContent,
116
+ /**
117
+ * ### > fileTree
118
+ *
119
+ * Generate a file tree table of contents
120
+ *
121
+ * **Options:**
122
+ * - `src` (optional): The directory path to generate the file tree for. Default `.` (current directory)
123
+ * - `maxDepth` (optional): Maximum depth to traverse in the directory tree. Default `3`
124
+ * - `includeFiles` (optional): Whether to include files in the tree or just directories. Default `true`
125
+ * - `exclude` (optional): Array of glob patterns to exclude from the tree. Default `[]`
126
+ * - `showSize` (optional): Whether to show file sizes. Default `false`
127
+ * - `format` (optional): Output format: "tree" or "list". Default `"tree"`
128
+ *
129
+ * **Example:**
130
+ * ```md
131
+ * <!-- doc-gen fileTree src="./src" maxDepth=2 -->
132
+ * file tree will be generated here
133
+ * <!-- end-doc-gen -->
134
+ * ```
135
+ *
136
+ * **Example Output (tree format):**
137
+ * ```
138
+ * └── src/
139
+ * ├── transforms/
140
+ * │ ├── code/
141
+ * │ │ ...
142
+ * │ ├── fileTree.js
143
+ * │ ├── index.js
144
+ * │ └── toc.js
145
+ * ├── utils/
146
+ * │ ├── fs.js
147
+ * │ ├── logs.js
148
+ * │ └── text.js
149
+ * └── index.js
150
+ * ```
151
+ *
152
+ * **Example Output (list format):**
153
+ * ```md
154
+ * - **src/**
155
+ * - **transforms/**
156
+ * - **code/**
157
+ * - ...
158
+ * - fileTree.js
159
+ * - index.js
160
+ * - toc.js
161
+ * - **utils/**
162
+ * - fs.js
163
+ * - logs.js
164
+ * - text.js
165
+ * - index.js
166
+ * ```
167
+ *
168
+ * **Example with file sizes:**
169
+ * ```
170
+ * └── src/
171
+ * ├── index.js (15.2 KB)
172
+ * └── package.json (552 B)
173
+ * ```
174
+ *
175
+ * Default `matchWord` is `doc-gen`
176
+ *
177
+ * ---
178
+ * @param {string} content The current content of the comment block
179
+ * @param {object} options The options passed in from the comment declaration
180
+ * @return {string} Updated content to place in the content block
181
+ */
182
+ fileTree: fileTree,
115
183
  /**
116
184
  * ### > install
117
185
  *
@@ -33,7 +33,7 @@ module.exports = async function TOC(api) {
33
33
  return sectionToc(api)
34
34
  }
35
35
 
36
- opts.firsth1 = (opts.firsth1) ? true : false
36
+ opts.firsth1 = (opts.firsth1 || opts.firstH1) ? true : false
37
37
  let contents = currentFileContent
38
38
  // console.log('contents', contents)
39
39
 
@@ -54,7 +54,7 @@ module.exports = async function TOC(api) {
54
54
  trimLeadingHeading: true,
55
55
  // maxHeaderLevel: 2, // default: 4
56
56
  // title: '**Table of Contents**',
57
- // isNotitle: true,
57
+ // isNoTitle: true,
58
58
  // isFolding: true,
59
59
  // entryPrefix: '*',
60
60
  // processAll: true,
package/src/types.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Allowed file syntaxes
3
- * @typedef {'md' | 'js' | 'yml' | 'yaml'} SyntaxType
3
+ * @typedef {'md' | 'js' | 'yml' | 'yaml' | 'toml' | 'sql'} SyntaxType
4
4
  */
5
5
 
6
6
  /** @type {SyntaxType} */
@@ -42,6 +42,9 @@ test('getGitignoreContents', async () => {
42
42
  'misc',
43
43
  'misc/**/**.js',
44
44
  "__misc",
45
+ 'large-table.md',
46
+ 'large-table.js',
47
+ 'large-table-data.json',
45
48
  '**/old-test/cool.md',
46
49
  'pids',
47
50
  '*.pid',
@@ -53,6 +53,30 @@ const yaml = {
53
53
  }
54
54
  }
55
55
 
56
+ const sql = {
57
+ tags: ['/*', '*/'],
58
+ pattern: [
59
+ '\/\\*+',
60
+ '\\*+/'
61
+ ],
62
+ singleLineTag: '--',
63
+ singleLinePattern: '--',
64
+ singleLine: '--.*$',
65
+ content: '[\\s\\S]*?'
66
+ }
67
+
68
+ const toml = {
69
+ tags: ['#', '#'],
70
+ pattern: [
71
+ '#+',
72
+ '#+'
73
+ ],
74
+ singleLineTag: '#',
75
+ singleLinePattern: '#+',
76
+ singleLine: '#.*$',
77
+ content: '[ \\t\\S]*?'
78
+ }
79
+
56
80
  const syntaxMap = {
57
81
  // <!-- x -->
58
82
  md: html,
@@ -66,8 +90,12 @@ const syntaxMap = {
66
90
  jsx: jsx,
67
91
  mdx: jsx,
68
92
  // ## x ##
93
+ yml: yaml,
69
94
  yaml: yaml,
70
- yml: yaml
95
+ // -- x
96
+ sql: sql,
97
+ // # x
98
+ toml: toml
71
99
  }
72
100
 
73
101
  // Additional comment syntaxes for future
package/src/utils/text.js CHANGED
@@ -188,11 +188,18 @@ function stripComments(str, syntax = 'md') {
188
188
  const [ openPattern, closePattern ] = syntaxData.pattern
189
189
  const OR = (syntaxData.singleLine) ? `|\\s?[ \\t]*${syntaxData.singleLine}` : ''
190
190
  const CONTENT = syntaxData.content || '[\\s\\S]*?'
191
- const pattern = new RegExp(`\\s?[ \\t]*${openPattern}(${CONTENT})?${closePattern}${OR}`, 'gim')
192
- // console.log('pattern', pattern)
193
- return str.replace(pattern, '')
194
- // https://regex101.com/r/XKHU18/5
195
- return str.replace(/\s?[ \t]*\/\*[\s\S]*?\*\/|\s?[ \t]*\/\/.*$|\/\*{1,}[\n\*]*(\s?[\s\S]*?)?\*+\//gm, '')
191
+
192
+ // Handle multi-line comments
193
+ const multiLinePattern = new RegExp(`\\s?[ \\t]*${openPattern}${CONTENT}${closePattern}`, 'gim')
194
+ let result = str.replace(multiLinePattern, '')
195
+
196
+ // Handle single-line comments if they exist
197
+ if (syntaxData.singleLine) {
198
+ const singleLinePattern = new RegExp(`\\s?[ \\t]*${syntaxData.singleLine}.*$`, 'gm')
199
+ result = result.replace(singleLinePattern, '')
200
+ }
201
+
202
+ return result
196
203
  }
197
204
 
198
205
 
@@ -50,7 +50,7 @@ nice
50
50
  nice={{ value: nice, cool: "true" }}
51
51
  soclose=[jdjdjd, hdhfhfhffh]
52
52
  rad="boss"
53
- cool=true notCool=false
53
+ cool=true notCool=false
54
54
  nooooo={[one, two, 3, 4]}
55
55
  numberZero=0,
56
56
  xyz=999,
@@ -72,7 +72,7 @@ actual content
72
72
  <!-- XYZ:START(cool) xxx
73
73
  hhddh=cool -->
74
74
  wowow
75
- whatever we want 
75
+ whatever we want
76
76
  <!-- XYZ:END -->
77
77
 
78
78
 
@@ -135,7 +135,7 @@ test('Remove Markdown comments', () => {
135
135
  '',
136
136
  '',
137
137
  'wowow',
138
- 'whatever we want ',
138
+ 'whatever we want ',
139
139
  '',
140
140
  '',
141
141
  'xyz',
@@ -297,6 +297,79 @@ test('Convert comment syntax', () => {
297
297
  // assert.equal(typeof parsedValue, 'string')
298
298
  })
299
299
 
300
+ test('Remove TOML comments', () => {
301
+ const parsedValue = stripComments(`
302
+ # This is a TOML comment
303
+ title = "TOML Example"
304
+ # Another comment
305
+ [owner]
306
+ name = "Tom Preston-Werner"
307
+ # Inline comment
308
+ organization = "GitHub" # This is an inline comment
309
+ # Multi-line comment
310
+ # that continues
311
+ # on multiple lines
312
+ created = 1979-05-27T07:32:00Z
313
+
314
+ [database]
315
+ server = "192.168.1.1"
316
+ ports = [ 8001, 8001, 8002 ]
317
+ connection_max = 5000
318
+ enabled = true
319
+ `, 'toml')
320
+
321
+ assert.equal(typeof parsedValue, 'string')
322
+ assert.equal(parsedValue.match(/#/), null)
323
+ assert.equal(parsedValue.split('\n'), [
324
+ '',
325
+ 'title = "TOML Example"',
326
+ '[owner]',
327
+ 'name = "Tom Preston-Werner"',
328
+ 'organization = "GitHub"',
329
+ 'created = 1979-05-27T07:32:00Z',
330
+ '',
331
+ '[database]',
332
+ 'server = "192.168.1.1"',
333
+ 'ports = [ 8001, 8001, 8002 ]',
334
+ 'connection_max = 5000',
335
+ 'enabled = true',
336
+ ''
337
+ ])
338
+ })
339
+
340
+ test('Remove SQL comments', () => {
341
+ const parsedValue = stripComments(`
342
+ -- This is a single line comment
343
+ SELECT * FROM users
344
+ -- Another single line comment
345
+ WHERE id = 1
346
+ /* This is a multi-line
347
+ comment that spans
348
+ multiple lines */
349
+
350
+ AND active = true
351
+ SELECT name -- inline comment
352
+ FROM products
353
+ WHERE price > 100 /* another inline comment */
354
+ `, 'sql')
355
+
356
+ console.log('parsedValue', parsedValue)
357
+ assert.equal(typeof parsedValue, 'string')
358
+ assert.equal(parsedValue.match(/--/), null, 'SQL comments should be removed 1')
359
+ assert.equal(parsedValue.match(/\/\*/), null, 'SQL comments should be removed 2')
360
+ assert.equal(parsedValue.match(/\*\//), null, 'SQL comments should be removed 3')
361
+ assert.equal(parsedValue.split('\n'), [
362
+ '',
363
+ 'SELECT * FROM users',
364
+ 'WHERE id = 1',
365
+ '',
366
+ 'AND active = true',
367
+ 'SELECT name',
368
+ 'FROM products',
369
+ 'WHERE price > 100',
370
+ ''
371
+ ])
372
+ })
300
373
 
301
374
  function logOutput(value) {
302
375
  console.log(value.split('\n'))