markdown-magic 4.0.4 → 4.1.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/cli.js CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ // @ts-ignore
2
3
  const mri = require('mri')
3
4
  const { runCli } = require('./src/cli-run')
4
5
  const argv = process.argv.slice(2)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markdown-magic",
3
- "version": "4.0.4",
3
+ "version": "4.1.0",
4
4
  "description": "Automatically update markdown files with content from external sources",
5
5
  "main": "src/index.js",
6
6
  "bin": {
@@ -22,6 +22,11 @@
22
22
  "docs": "node examples/generate-readme.js",
23
23
  "test": "uvu . '.test.([mc]js|[jt]sx?)$'",
24
24
  "cli": "node ./cli.js --path 'README.md' --config ./markdown.config.js",
25
+ "bundle": "npm run bundle:all",
26
+ "bundle:all": "npm run bundle:mac && npm run bundle:linux && npm run bundle:windows",
27
+ "bundle:mac": "bun build ./cli.js --compile --minify --target=bun-darwin-arm64 --outfile dist/md-magic-darwin-arm64 && bun build ./cli.js --compile --minify --target=bun-darwin-x64 --outfile dist/md-magic-darwin-x64",
28
+ "bundle:linux": "bun build ./cli.js --compile --minify --target=bun-linux-x64 --outfile dist/md-magic-linux-x64 && bun build ./cli.js --compile --minify --target=bun-linux-arm64 --outfile dist/md-magic-linux-arm64",
29
+ "bundle:windows": "bun build ./cli.js --compile --minify --target=bun-windows-x64 --outfile dist/md-magic-windows-x64.exe",
25
30
  "postpublish": "git push origin && git push origin --tags",
26
31
  "release:patch": "pnpm version patch --git-tag-version && pnpm publish",
27
32
  "release:minor": "pnpm version minor --git-tag-version && pnpm publish",
@@ -36,9 +41,10 @@
36
41
  },
37
42
  "dependencies": {
38
43
  "@davidwells/md-utils": "0.0.53",
39
- "comment-block-parser": "1.1.1",
40
- "comment-block-replacer": "0.1.3",
41
- "comment-block-transformer": "0.2.2",
44
+ "color-convert": "^2.0.1",
45
+ "comment-block-parser": "1.1.2",
46
+ "comment-block-replacer": "0.1.4",
47
+ "comment-block-transformer": "0.2.3",
42
48
  "globrex": "^0.1.2",
43
49
  "gray-matter": "^4.0.3",
44
50
  "is-glob": "^4.0.3",
@@ -48,11 +54,10 @@
48
54
  "module-alias": "^2.2.3",
49
55
  "mri": "^1.2.0",
50
56
  "node-fetch": "^2.7.0",
51
- "oparser": "^3.0.22",
57
+ "oparser": "^3.0.24",
52
58
  "punycode": "^2.3.1",
53
59
  "smart-glob": "^1.0.2",
54
- "string-width": "^4.2.3",
55
- "sync-request": "^6.1.0"
60
+ "string-width": "^4.2.3"
56
61
  },
57
62
  "devDependencies": {
58
63
  "concordance": "^5.0.1",
@@ -65,5 +70,5 @@
65
70
  "publishConfig": {
66
71
  "access": "public"
67
72
  },
68
- "gitHead": "c67e6884103de807711ff608e100e1e0a211c2d8"
73
+ "gitHead": "4c7432d3518d9c6eac0019df43863ffc5857d417"
69
74
  }
package/src/cli-run.js CHANGED
@@ -1,8 +1,11 @@
1
1
  const path = require('path')
2
+ const fs = require('fs')
2
3
  const { loadConfig } = require('./utils/load-config')
3
4
  const { findUp } = require('./utils/fs')
4
5
  const { markdownMagic } = require('./')
6
+ const { processFile } = require('comment-block-replacer')
5
7
  const { parse } = require('oparser')
8
+ const defaultTransforms = require('./transforms')
6
9
  const { getGlobGroupsFromArgs } = require('./globparse')
7
10
  // const { deepLog } = require('./utils/logs')
8
11
  // const { uxParse } = require('./argparse/argparse')
@@ -10,6 +13,75 @@ const argv = process.argv.slice(2)
10
13
  const cwd = process.cwd()
11
14
  const defaultConfigPath = 'md.config.js'
12
15
 
16
+ /**
17
+ * Render markdown with ANSI styling for terminal output
18
+ * @param {string} content
19
+ */
20
+ // async function renderMarkdown(content) {
21
+ // const { render, themes } = await import('markdansi')
22
+ // const githubDark = {
23
+ // ...themes.default,
24
+ // heading: { color: 'white', bold: true },
25
+ // strong: { bold: true },
26
+ // emph: { italic: true },
27
+ // inlineCode: { color: 'yellow' },
28
+ // blockCode: { color: 'white' },
29
+ // link: { color: 'cyan', underline: true },
30
+ // quote: { color: 'gray', italic: true },
31
+ // hr: { color: 'gray', dim: true },
32
+ // listMarker: { color: 'blue' },
33
+ // tableHeader: { color: 'white', bold: true },
34
+ // tableCell: { color: 'white' },
35
+ // }
36
+ // return render(content, { theme: githubDark })
37
+ // }
38
+
39
+ /**
40
+ * Read all data from stdin
41
+ * @returns {Promise<string>}
42
+ */
43
+ function readStdin() {
44
+ return new Promise((resolve, reject) => {
45
+ let data = ''
46
+ process.stdin.setEncoding('utf8')
47
+ process.stdin.on('data', chunk => data += chunk)
48
+ process.stdin.on('end', () => resolve(data))
49
+ process.stdin.on('error', reject)
50
+ })
51
+ }
52
+
53
+ /**
54
+ * Interpret escape sequences in string (e.g., \n -> newline)
55
+ * @param {string} str
56
+ * @returns {string}
57
+ */
58
+ function interpretEscapes(str) {
59
+ if (!str) return str
60
+ return str.replace(/\\n/g, '\n').replace(/\\t/g, '\t')
61
+ }
62
+
63
+ /**
64
+ * Check if string looks like markdown content vs a file path
65
+ * @param {string} str
66
+ * @returns {boolean}
67
+ */
68
+ function isMarkdownContent(str) {
69
+ if (!str) return false
70
+ // Has newlines (real or escaped) = likely content
71
+ if (str.includes('\n') || str.includes('\\n')) return true
72
+ // Has markdown comment blocks = likely content
73
+ if (str.includes('<!--')) return true
74
+ // Check if file exists
75
+ try {
76
+ if (fs.existsSync(str)) return false
77
+ } catch (e) {
78
+ // ignore
79
+ }
80
+ // Has markdown heading at start = likely content
81
+ if (str.startsWith('#')) return true
82
+ return false
83
+ }
84
+
13
85
  async function getBaseDir(opts = {}) {
14
86
  const { currentDir = cwd } = opts
15
87
  const gitDir = await findUp(currentDir, '.git')
@@ -21,6 +93,93 @@ function findSingleDashStrings(arr) {
21
93
  }
22
94
 
23
95
  async function runCli(options = {}, rawArgv) {
96
+ if (options.help || options.h) {
97
+ console.log(`
98
+ Usage: md-magic [options] [files...]
99
+
100
+ Options:
101
+ --files, --file Files or glob patterns to process
102
+ --config Path to config file (default: md.config.js)
103
+ --output Output directory
104
+ --open Opening comment keyword (default: docs)
105
+ --close Closing comment keyword (default: /docs)
106
+ --pretty Render output with ANSI styling
107
+ --dry Dry run - show what would be changed
108
+ --debug Show debug output
109
+ --help, -h Show this help message
110
+ --version, -v Show version
111
+
112
+ Examples:
113
+ md-magic README.md
114
+ md-magic --files "**/*.md"
115
+ md-magic --config ./my-config.js
116
+
117
+ Stdin/stdout mode:
118
+ cat file.md | md-magic
119
+ echo "<!-- docs TOC --><!-- /docs -->" | md-magic
120
+ md-magic "# Title\\n<!-- docs TOC --><!-- /docs -->"
121
+ `)
122
+ return
123
+ }
124
+
125
+ if (options.version || options.v) {
126
+ // @ts-ignore
127
+ const pkg = require('../package.json')
128
+ console.log(`${pkg.name} v${pkg.version}`)
129
+ return
130
+ }
131
+
132
+ // Check if first positional arg is markdown content (before stdin check)
133
+ const firstArg = options._ && options._[0]
134
+ const openKeyword = options.open || 'docs'
135
+ const closeKeyword = options.close || (options.open && options.open !== 'docs' ? `/${options.open}` : '/docs')
136
+ if (firstArg && isMarkdownContent(firstArg)) {
137
+ const content = interpretEscapes(firstArg)
138
+ const result = await processFile({
139
+ content,
140
+ syntax: 'md',
141
+ open: openKeyword,
142
+ close: closeKeyword,
143
+ transforms: defaultTransforms,
144
+ dryRun: true,
145
+ })
146
+ // TODO future pretty option
147
+ // if (options.pretty) {
148
+ // console.log(await renderMarkdown(result.updatedContents))
149
+ // } else {
150
+ // console.log()
151
+ // console.log(result.updatedContents)
152
+ // }
153
+ console.log(result.updatedContents)
154
+ return
155
+ }
156
+
157
+ // Check for stdin pipe (when no positional file args provided)
158
+ const hasNoFileArgs = !options._ || options._.length === 0
159
+ const hasPipedInput = !process.stdin.isTTY && hasNoFileArgs
160
+ if (hasPipedInput) {
161
+ const content = await readStdin()
162
+ if (content.trim()) {
163
+ const result = await processFile({
164
+ content,
165
+ syntax: 'md',
166
+ open: openKeyword,
167
+ close: closeKeyword,
168
+ transforms: defaultTransforms,
169
+ dryRun: true, // Don't write files
170
+ })
171
+ // TODO future pretty option
172
+ // if (options.pretty) {
173
+ // console.log(await renderMarkdown(result.updatedContents))
174
+ // } else {
175
+ // console.log()
176
+ // console.log(result.updatedContents)
177
+ // }
178
+ console.log(result.updatedContents)
179
+ return
180
+ }
181
+ }
182
+
24
183
  let configFile
25
184
  let opts = {}
26
185
 
@@ -39,6 +39,7 @@ test('getGitignoreContents', async () => {
39
39
  'yarn-error.log*',
40
40
  'test/fixtures/output',
41
41
  '_out.md',
42
+ 'dist',
42
43
  'misc',
43
44
  'misc/**/**.js',
44
45
  "__misc",
@@ -1,28 +1,9 @@
1
1
  const fetch = require('node-fetch')
2
- const request = require('sync-request')
3
2
 
4
3
  function formatUrl(url = '') {
5
4
  return url.match(/^https?:\/\//) ? url : `https://${url}`
6
5
  }
7
6
 
8
- function remoteRequestSync(url, settings = {}, srcPath) {
9
- let body
10
- const finalUrl = formatUrl(url)
11
- try {
12
- // @ts-expect-error
13
- const res = request('GET', finalUrl)
14
- body = res.getBody('utf8')
15
- } catch (e) {
16
- console.log(`⚠️ WARNING: REMOTE URL "${finalUrl}" NOT FOUND`)
17
- const msg = (e.message || '').split('\n')[0] + `\nFix "${url}" value in ${srcPath}`
18
- console.log(msg)
19
- if (settings.failOnMissingRemote) {
20
- throw new Error(msg)
21
- }
22
- }
23
- return body
24
- }
25
-
26
7
  async function remoteRequest(url, settings = {}, srcPath) {
27
8
  let body
28
9
  const finalUrl = formatUrl(url)
@@ -45,7 +26,6 @@ async function remoteRequest(url, settings = {}, srcPath) {
45
26
  }
46
27
 
47
28
  module.exports = {
48
- remoteRequestSync,
49
29
  remoteRequest
50
30
  }
51
31