markdown-magic 2.6.1 → 3.0.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 +6 -10
- package/cli.js +5 -82
- package/lib/block-parser-js.test.js +179 -0
- package/lib/block-parser.js +389 -0
- package/lib/{utils/new-parser.test.js → block-parser.test.js} +168 -50
- package/lib/cli.js +234 -0
- package/lib/cli.test.js +409 -0
- package/lib/defaults.js +12 -0
- package/lib/index.js +319 -184
- package/lib/index.test.js +11 -0
- package/lib/options-parser.js +498 -0
- package/lib/options-parser.test.js +1237 -0
- package/lib/process-contents.js +330 -0
- package/lib/process-file.js +34 -0
- package/lib/transforms/code.js +67 -22
- package/lib/transforms/file.js +13 -10
- package/lib/transforms/remote.js +9 -6
- package/lib/transforms/toc.js +136 -64
- package/lib/transforms/wordCount.js +5 -0
- package/lib/utils/fs.js +340 -0
- package/lib/utils/fs.test.js +268 -0
- package/lib/utils/html-to-json/compat.js +42 -0
- package/lib/utils/html-to-json/format.js +64 -0
- package/lib/utils/html-to-json/index.js +37 -0
- package/lib/utils/html-to-json/lexer.js +345 -0
- package/lib/utils/html-to-json/parser.js +146 -0
- package/lib/utils/html-to-json/stringify.js +37 -0
- package/lib/utils/html-to-json/tags.js +171 -0
- package/lib/utils/index.js +19 -0
- package/{cli-utils.js → lib/utils/load-config.js} +2 -6
- package/lib/utils/logs.js +89 -0
- package/lib/utils/md/filters.js +20 -0
- package/lib/utils/md/find-code-blocks.js +80 -0
- package/lib/utils/md/find-date.js +32 -0
- package/lib/utils/md/find-frontmatter.js +94 -0
- package/lib/utils/md/find-frontmatter.test.js +17 -0
- package/lib/utils/md/find-html-tags.js +105 -0
- package/lib/utils/md/find-images.js +102 -0
- package/lib/utils/md/find-links.js +202 -0
- package/lib/utils/md/find-unmatched-html-tags.js +33 -0
- package/lib/utils/md/fixtures/2022-01-22-date-in-filename.md +14 -0
- package/lib/utils/md/fixtures/file-with-frontmatter.md +32 -0
- package/lib/utils/md/fixtures/file-with-links.md +143 -0
- package/lib/utils/md/md.test.js +37 -0
- package/lib/utils/md/parse.js +122 -0
- package/lib/utils/md/utils.js +19 -0
- package/lib/utils/regex-timeout.js +83 -0
- package/lib/utils/regex.js +38 -5
- package/lib/utils/remoteRequest.js +54 -0
- package/lib/utils/syntax.js +79 -0
- package/lib/utils/text.js +260 -0
- package/lib/utils/text.test.js +311 -0
- package/package.json +25 -25
- package/index.js +0 -46
- package/lib/processFile.js +0 -154
- package/lib/transforms/index.js +0 -114
- package/lib/updateContents.js +0 -125
- package/lib/utils/_md.test.js +0 -63
- package/lib/utils/new-parser.js +0 -412
- package/lib/utils/weird-parse.js +0 -230
- package/lib/utils/weird-parse.test.js +0 -217
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
const { test } = require('uvu')
|
|
2
|
+
const assert = require('uvu/assert')
|
|
3
|
+
const { stripComments, dedentString, convertCommentSyntax } = require('./text')
|
|
4
|
+
const { deepLog } = require('./logs')
|
|
5
|
+
|
|
6
|
+
const md = `<h1 id="jdjdj">Netlify + FaunaDB
|
|
7
|
+
<a href="https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example&stack=fauna">
|
|
8
|
+
<img src="https://www.netlify.com/img/deploy/button.svg">
|
|
9
|
+
</a>
|
|
10
|
+
</h1>
|
|
11
|
+
|
|
12
|
+
foo o <!-- XYZ:START functionName foo={{ rad: 'yellow' }} -->
|
|
13
|
+
|
|
14
|
+
nice
|
|
15
|
+
<!-- XYZ:END -->
|
|
16
|
+
|
|
17
|
+
<!-- XYZ:START functionName foo={{ rad: 'yellow' }} -->
|
|
18
|
+
wooooooo
|
|
19
|
+
<!-- XYZ:END -->
|
|
20
|
+
|
|
21
|
+
<!-- XYZ:START {functionName} foo={{ rad: 'blue' }} -->
|
|
22
|
+
cool
|
|
23
|
+
<!-- XYZ:END -->
|
|
24
|
+
|
|
25
|
+
<!-- XYZ:START {functionName} foo={{ rad: 'red' }} -->
|
|
26
|
+
rad
|
|
27
|
+
<!-- XYZ:END -->
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
<!-- XYZ:START [wootName] foo=['one', 'two'] -->
|
|
31
|
+
nice
|
|
32
|
+
<!-- XYZ:END -->
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
<!-- XYZ:START -->
|
|
36
|
+
lol
|
|
37
|
+
<!-- XYZ:END -->
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
<!-- xyz:start (lowerCase) foo=['one', 'two'] heading=false -->
|
|
41
|
+
nice
|
|
42
|
+
<!-- XYZ:END -->
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
<!-- XYZ:START(cool)
|
|
46
|
+
width={999}
|
|
47
|
+
height={{111}}
|
|
48
|
+
numberAsString="12345"
|
|
49
|
+
great={["scoot", "sco ot", 'scooo ttt']}
|
|
50
|
+
nice={{ value: nice, cool: "true" }}
|
|
51
|
+
soclose=[jdjdjd, hdhfhfhffh]
|
|
52
|
+
rad="boss"
|
|
53
|
+
cool=true notCool=false
|
|
54
|
+
nooooo={[one, two, 3, 4]}
|
|
55
|
+
numberZero=0,
|
|
56
|
+
xyz=999,
|
|
57
|
+
nope=false,
|
|
58
|
+
// comment
|
|
59
|
+
yes={true} -->
|
|
60
|
+
|
|
61
|
+
actual content
|
|
62
|
+
|
|
63
|
+
<!-- XYZ:END -->
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
<img src="https://www.netlify.com/img/deploy/button.svg"/>
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
<img src="https://www.hehhehehehe.com/img/deploy/button.svg" />
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
<!-- XYZ:START(cool) xxx
|
|
73
|
+
hhddh=cool -->
|
|
74
|
+
wowow
|
|
75
|
+
whatever we want
|
|
76
|
+
<!-- XYZ:END -->
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
<!-- XYZ:START(hhh) -->
|
|
80
|
+
xyz
|
|
81
|
+
<!-- XYZ:END -->
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
<!-- XYZ:START(cool) isCool -->
|
|
85
|
+
nice
|
|
86
|
+
<!-- XYZ:END -->
|
|
87
|
+
|
|
88
|
+
`
|
|
89
|
+
|
|
90
|
+
test('Remove Markdown comments', () => {
|
|
91
|
+
const parsedValue = stripComments(md, {
|
|
92
|
+
syntax: 'md'
|
|
93
|
+
})
|
|
94
|
+
/*
|
|
95
|
+
console.log('parsedValue')
|
|
96
|
+
logOutput(parsedValue)
|
|
97
|
+
/** */
|
|
98
|
+
assert.equal(typeof parsedValue, 'string')
|
|
99
|
+
assert.equal(parsedValue.match(/-->/), null)
|
|
100
|
+
assert.equal(parsedValue.match(/<!--/), null)
|
|
101
|
+
assert.equal(parsedValue.split('\n'), [
|
|
102
|
+
'<h1 id="jdjdj">Netlify + FaunaDB ',
|
|
103
|
+
' <a href="https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example&stack=fauna">',
|
|
104
|
+
' <img src="https://www.netlify.com/img/deploy/button.svg">',
|
|
105
|
+
' </a>',
|
|
106
|
+
'</h1>',
|
|
107
|
+
'',
|
|
108
|
+
'foo o',
|
|
109
|
+
'',
|
|
110
|
+
'nice',
|
|
111
|
+
'',
|
|
112
|
+
'wooooooo',
|
|
113
|
+
'',
|
|
114
|
+
'cool',
|
|
115
|
+
'',
|
|
116
|
+
'rad',
|
|
117
|
+
'',
|
|
118
|
+
'',
|
|
119
|
+
'nice',
|
|
120
|
+
'',
|
|
121
|
+
'',
|
|
122
|
+
'lol',
|
|
123
|
+
'',
|
|
124
|
+
'',
|
|
125
|
+
'nice',
|
|
126
|
+
'',
|
|
127
|
+
'',
|
|
128
|
+
'',
|
|
129
|
+
'actual content',
|
|
130
|
+
'',
|
|
131
|
+
'',
|
|
132
|
+
'',
|
|
133
|
+
'<img src="https://www.netlify.com/img/deploy/button.svg"/>',
|
|
134
|
+
'',
|
|
135
|
+
'',
|
|
136
|
+
'<img src="https://www.hehhehehehe.com/img/deploy/button.svg" />',
|
|
137
|
+
'',
|
|
138
|
+
'',
|
|
139
|
+
'wowow',
|
|
140
|
+
'whatever we want ',
|
|
141
|
+
'',
|
|
142
|
+
'',
|
|
143
|
+
'xyz',
|
|
144
|
+
'',
|
|
145
|
+
'',
|
|
146
|
+
'nice',
|
|
147
|
+
'',
|
|
148
|
+
''
|
|
149
|
+
])
|
|
150
|
+
})
|
|
151
|
+
|
|
152
|
+
test('Remove Javascript comments', () => {
|
|
153
|
+
const parsedValue = stripComments(`
|
|
154
|
+
/*
|
|
155
|
+
Fooo bar
|
|
156
|
+
*/
|
|
157
|
+
console.log('cool')
|
|
158
|
+
console.log('multiline')/*
|
|
159
|
+
weird one
|
|
160
|
+
*/
|
|
161
|
+
console.log('inline') /* inline klsjlkajdsalkjd *****/
|
|
162
|
+
|
|
163
|
+
/* inline */
|
|
164
|
+
console.log('nice')
|
|
165
|
+
`, {
|
|
166
|
+
syntax: 'js'
|
|
167
|
+
})
|
|
168
|
+
/*
|
|
169
|
+
console.log('parsedValue')
|
|
170
|
+
logOutput(parsedValue)
|
|
171
|
+
/** */
|
|
172
|
+
assert.equal(typeof parsedValue, 'string')
|
|
173
|
+
assert.equal(parsedValue.match(/\/\*/), null)
|
|
174
|
+
assert.equal(parsedValue.match(/\*\//), null)
|
|
175
|
+
assert.equal(parsedValue.split('\n'), [
|
|
176
|
+
'',
|
|
177
|
+
"console.log('cool')",
|
|
178
|
+
"console.log('multiline')",
|
|
179
|
+
"console.log('inline')",
|
|
180
|
+
'',
|
|
181
|
+
"console.log('nice')",
|
|
182
|
+
''
|
|
183
|
+
])
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
test('Remove YAML comments', () => {
|
|
187
|
+
const parsedValue = stripComments(`
|
|
188
|
+
bob: cool
|
|
189
|
+
# Remove this
|
|
190
|
+
# And this Remove this
|
|
191
|
+
joe: cool
|
|
192
|
+
bill: "cool"
|
|
193
|
+
## Remove this
|
|
194
|
+
## And this
|
|
195
|
+
steve: 'cool' # inline comment
|
|
196
|
+
foo:
|
|
197
|
+
bar: lol
|
|
198
|
+
`, {
|
|
199
|
+
syntax: 'yml'
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
/*
|
|
203
|
+
console.log('yml', dedentString(parsedValue))
|
|
204
|
+
console.log('parsedValue')
|
|
205
|
+
// deepLog(parsedValue)
|
|
206
|
+
logOutput(parsedValue)
|
|
207
|
+
/** */
|
|
208
|
+
assert.equal(typeof parsedValue, 'string')
|
|
209
|
+
assert.equal(parsedValue.match(/#/), null)
|
|
210
|
+
assert.equal(parsedValue.split('\n'), [
|
|
211
|
+
'',
|
|
212
|
+
' bob: cool',
|
|
213
|
+
' joe: cool',
|
|
214
|
+
' bill: "cool"',
|
|
215
|
+
" steve: 'cool'",
|
|
216
|
+
' foo:',
|
|
217
|
+
' bar: lol',
|
|
218
|
+
''
|
|
219
|
+
])
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
test('Convert comment syntax', () => {
|
|
223
|
+
const yml = `
|
|
224
|
+
bob: cool
|
|
225
|
+
# Remove this
|
|
226
|
+
# And this Remove this
|
|
227
|
+
joe: cool
|
|
228
|
+
bill: "cool"
|
|
229
|
+
## Remove this
|
|
230
|
+
## And this
|
|
231
|
+
steve: 'cool' # inline comment
|
|
232
|
+
foo:
|
|
233
|
+
bar: lol
|
|
234
|
+
`
|
|
235
|
+
const jsx = convertCommentSyntax(yml, {
|
|
236
|
+
from: 'yml',
|
|
237
|
+
to: 'jsx'
|
|
238
|
+
})
|
|
239
|
+
// logOutput(jsx)
|
|
240
|
+
|
|
241
|
+
assert.equal(jsx.split('\n'), [
|
|
242
|
+
'',
|
|
243
|
+
' bob: cool',
|
|
244
|
+
' {/* Remove this */}',
|
|
245
|
+
' {/* And this Remove this */}',
|
|
246
|
+
' joe: cool',
|
|
247
|
+
' bill: "cool"',
|
|
248
|
+
' {/* Remove this */}',
|
|
249
|
+
' {/* And this */}',
|
|
250
|
+
" steve: 'cool' {/* inline comment */}",
|
|
251
|
+
' foo:',
|
|
252
|
+
' bar: lol',
|
|
253
|
+
''
|
|
254
|
+
])
|
|
255
|
+
|
|
256
|
+
const js = convertCommentSyntax(yml, {
|
|
257
|
+
from: 'yml',
|
|
258
|
+
to: 'js'
|
|
259
|
+
})
|
|
260
|
+
// logOutput(js)
|
|
261
|
+
|
|
262
|
+
assert.equal(js.split('\n'), [
|
|
263
|
+
'',
|
|
264
|
+
' bob: cool',
|
|
265
|
+
' /* Remove this */',
|
|
266
|
+
' /* And this Remove this */',
|
|
267
|
+
' joe: cool',
|
|
268
|
+
' bill: "cool"',
|
|
269
|
+
' /* Remove this */',
|
|
270
|
+
' /* And this */',
|
|
271
|
+
" steve: 'cool' /* inline comment */",
|
|
272
|
+
' foo:',
|
|
273
|
+
' bar: lol',
|
|
274
|
+
''
|
|
275
|
+
])
|
|
276
|
+
|
|
277
|
+
const html = convertCommentSyntax(yml, {
|
|
278
|
+
from: 'yml',
|
|
279
|
+
to: 'html'
|
|
280
|
+
})
|
|
281
|
+
// logOutput(html)
|
|
282
|
+
|
|
283
|
+
assert.equal(html.split('\n'), [
|
|
284
|
+
'',
|
|
285
|
+
' bob: cool',
|
|
286
|
+
' <!-- Remove this -->',
|
|
287
|
+
' <!-- And this Remove this -->',
|
|
288
|
+
' joe: cool',
|
|
289
|
+
' bill: "cool"',
|
|
290
|
+
' <!-- Remove this -->',
|
|
291
|
+
' <!-- And this -->',
|
|
292
|
+
" steve: 'cool' <!-- inline comment -->",
|
|
293
|
+
' foo:',
|
|
294
|
+
' bar: lol',
|
|
295
|
+
''
|
|
296
|
+
])
|
|
297
|
+
|
|
298
|
+
// //*
|
|
299
|
+
// console.log('parsedValue')
|
|
300
|
+
// // deepLog(parsedValue)
|
|
301
|
+
// logOutput(parsedValue)
|
|
302
|
+
// /** */
|
|
303
|
+
// assert.equal(typeof parsedValue, 'string')
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
function logOutput(value) {
|
|
308
|
+
console.log(value.split('\n'))
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
test.run()
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "markdown-magic",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0",
|
|
4
4
|
"description": "Automatically update markdown files with content from external sources",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "lib/index.js",
|
|
6
6
|
"bin": {
|
|
7
7
|
"markdown": "./cli.js",
|
|
8
8
|
"md-magic": "./cli.js"
|
|
@@ -10,18 +10,25 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"README.md",
|
|
12
12
|
"package.json",
|
|
13
|
-
"
|
|
13
|
+
"package-lock.json",
|
|
14
14
|
"cli.js",
|
|
15
|
-
"cli-utils.js",
|
|
16
15
|
"/lib"
|
|
17
16
|
],
|
|
18
17
|
"scripts": {
|
|
19
18
|
"docs": "node examples/generate-readme.js",
|
|
20
|
-
"
|
|
21
|
-
"test": "
|
|
22
|
-
"test:
|
|
19
|
+
"test": "npm run test:lib && npm run test:test && echo 'tests done'",
|
|
20
|
+
"test:lib": "uvu lib '.test.([mc]js|[jt]sx?)$'",
|
|
21
|
+
"test:test": "uvu test '.test.([mc]js|[jt]sx?)$'",
|
|
22
|
+
"test:options": "uvu lib 'options-parser.test.([mc]js|[jt]sx?)$'",
|
|
23
|
+
"test:block": "uvu lib 'block-parser.test.([mc]js|[jt]sx?)$'",
|
|
24
|
+
"test:cli": "uvu lib 'cli.test.([mc]js|[jt]sx?)$'",
|
|
25
|
+
"test:md": "uvu lib 'md.test.([mc]js|[jt]sx?)$'",
|
|
26
|
+
"test:fs": "uvu lib 'fs.test.([mc]js|[jt]sx?)$'",
|
|
27
|
+
"test:js": "uvu lib 'block-parser-js.test.([mc]js|[jt]sx?)$'",
|
|
28
|
+
"test:errors": "uvu test 'errors.test.([mc]js|[jt]sx?)$'",
|
|
29
|
+
"test:transforms": "uvu test 'transforms.test.([mc]js|[jt]sx?)$'",
|
|
30
|
+
"test:text": "uvu lib 'text.test.([mc]js|[jt]sx?)$'",
|
|
23
31
|
"cli": "node ./cli.js --path 'README.md' --config ./markdown.config.js",
|
|
24
|
-
"lint": "eslint .",
|
|
25
32
|
"publish": "git push origin && git push origin --tags",
|
|
26
33
|
"release:patch": "npm version patch && npm publish",
|
|
27
34
|
"release:minor": "npm version minor && npm publish",
|
|
@@ -36,29 +43,22 @@
|
|
|
36
43
|
},
|
|
37
44
|
"dependencies": {
|
|
38
45
|
"@technote-space/doctoc": "2.4.7",
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"globby": "^10.0.2",
|
|
46
|
+
"globrex": "^0.1.2",
|
|
47
|
+
"gray-matter": "^4.0.3",
|
|
48
|
+
"is-glob": "^4.0.3",
|
|
43
49
|
"is-local-path": "^0.1.6",
|
|
50
|
+
"is-valid-path": "^0.1.1",
|
|
44
51
|
"json-alexander": "^0.1.8",
|
|
45
|
-
"
|
|
52
|
+
"mri": "^1.2.0",
|
|
53
|
+
"smart-glob": "^1.0.2",
|
|
46
54
|
"sync-request": "^6.1.0"
|
|
47
55
|
},
|
|
48
56
|
"devDependencies": {
|
|
49
|
-
"ava": "^3.15.0",
|
|
50
|
-
"doxxx": "^1.0.0",
|
|
51
|
-
"rimraf": "^3.0.2",
|
|
52
|
-
"sinon": "^11.1.1",
|
|
53
|
-
"uvu": "^0.5.1",
|
|
54
57
|
"ansi-styles": "^4.2.1",
|
|
55
58
|
"concordance": "^5.0.1",
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
"test/**/*.test.js"
|
|
61
|
-
],
|
|
62
|
-
"verbose": true
|
|
59
|
+
"doxxx": "^1.0.0",
|
|
60
|
+
"rimraf": "^3.0.2",
|
|
61
|
+
"safe-chalk": "^1.0.0",
|
|
62
|
+
"uvu": "^0.5.1"
|
|
63
63
|
}
|
|
64
64
|
}
|
package/index.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
const globby = require('globby')
|
|
2
|
-
const processFile = require('./lib/processFile')
|
|
3
|
-
/**
|
|
4
|
-
* ### API
|
|
5
|
-
* ```js
|
|
6
|
-
* markdownMagic(filePath, config, callback)
|
|
7
|
-
* ```
|
|
8
|
-
* - `filePaths` - *String or Array* - Path or glob pattern. Uses [globby patterns](https://github.com/sindresorhus/multimatch/blob/master/test.js)
|
|
9
|
-
* - `config` - See configuration options below
|
|
10
|
-
* - `callback` - callback to run after markdown updates
|
|
11
|
-
*
|
|
12
|
-
* @param {string} filePath - Path to markdown file
|
|
13
|
-
* @param {object} [config] - configuration object
|
|
14
|
-
* @param {Function} [callback] - callback function with updated contents
|
|
15
|
-
*/
|
|
16
|
-
module.exports = async function markdownMagic(filePaths, config, callback) {
|
|
17
|
-
const files = globby.sync(filePaths)
|
|
18
|
-
const configuration = config || {}
|
|
19
|
-
if (!callback && typeof configuration === 'function') {
|
|
20
|
-
callback = configuration // eslint-disable-line
|
|
21
|
-
} else if (typeof config === 'object' && config.callback) {
|
|
22
|
-
// set callback in config for CLI usage
|
|
23
|
-
callback = config.callback // eslint-disable-line
|
|
24
|
-
}
|
|
25
|
-
if (!files.length) {
|
|
26
|
-
callback && callback('No files matched')
|
|
27
|
-
console.log('No files matched pattern', filePaths)
|
|
28
|
-
return false
|
|
29
|
-
}
|
|
30
|
-
configuration.originalFilePaths = files
|
|
31
|
-
|
|
32
|
-
const data = files.map(async (file) => {
|
|
33
|
-
const x = await processFile(file, configuration)
|
|
34
|
-
return x
|
|
35
|
-
})
|
|
36
|
-
|
|
37
|
-
const values = await Promise.all(data)
|
|
38
|
-
|
|
39
|
-
if (callback) {
|
|
40
|
-
callback(null, values)
|
|
41
|
-
}
|
|
42
|
-
return values
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// expose globby for use in plugins
|
|
46
|
-
module.exports.globby = globby
|
package/lib/processFile.js
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const mkdirp = require('mkdirp')
|
|
3
|
-
const path = require('path')
|
|
4
|
-
const merge = require('deepmerge')
|
|
5
|
-
const transforms = require('./transforms')
|
|
6
|
-
const regexUtils = require('./utils/regex')
|
|
7
|
-
const pluginSortOrder = require('./utils/sortOrder')
|
|
8
|
-
const updateContents = require('./updateContents')
|
|
9
|
-
const cwd = process.cwd()
|
|
10
|
-
|
|
11
|
-
module.exports = async function processFile(filePath, config) {
|
|
12
|
-
let content
|
|
13
|
-
try {
|
|
14
|
-
content = fs.readFileSync(filePath, 'utf8')
|
|
15
|
-
} catch (e) {
|
|
16
|
-
console.log(`FILE NOT FOUND ${filePath}`)
|
|
17
|
-
throw e
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* ### Configuration Options
|
|
21
|
-
*/
|
|
22
|
-
const defaultConfig = {
|
|
23
|
-
/**
|
|
24
|
-
* - `transforms` - *object* - (optional) Custom commands to transform block contents, see transforms & custom transforms sections below.
|
|
25
|
-
* @type {Object}
|
|
26
|
-
*/
|
|
27
|
-
transforms: transforms,
|
|
28
|
-
/**
|
|
29
|
-
* - `outputDir` - *string* - (optional) Change output path of new content. Default behavior is replacing the original file
|
|
30
|
-
* @type {string}
|
|
31
|
-
*/
|
|
32
|
-
outputDir: path.dirname(filePath),
|
|
33
|
-
/**
|
|
34
|
-
* - `matchWord` - *string* - (optional) Comment pattern to look for & replace inner contents. Default `AUTO-GENERATED-CONTENT`
|
|
35
|
-
* @type {string}
|
|
36
|
-
* @default [AUTO-GENERATED-CONTENT]
|
|
37
|
-
*/
|
|
38
|
-
matchWord: 'AUTO-GENERATED-CONTENT',
|
|
39
|
-
/**
|
|
40
|
-
* - `DEBUG` - *Boolean* - (optional) set debug flag to `true` to inspect the process
|
|
41
|
-
* @type {boolean}
|
|
42
|
-
*/
|
|
43
|
-
DEBUG: false,
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const userConfig = (config && typeof config === 'object') ? config : {}
|
|
47
|
-
const mergedConfig = merge(defaultConfig, userConfig)
|
|
48
|
-
|
|
49
|
-
const registeredTransforms = Object.keys(mergedConfig.transforms)
|
|
50
|
-
// Set originalPath constant
|
|
51
|
-
mergedConfig.originalPath = filePath
|
|
52
|
-
// contents of original MD file
|
|
53
|
-
mergedConfig.originalContent = content
|
|
54
|
-
// set default outputContents for first pass for single commands
|
|
55
|
-
mergedConfig.outputContent = content
|
|
56
|
-
|
|
57
|
-
const regex = regexUtils.matchCommentBlock(mergedConfig.matchWord)
|
|
58
|
-
// console.log(regex)
|
|
59
|
-
const match = content.match(regex)
|
|
60
|
-
const transformsFound = []
|
|
61
|
-
|
|
62
|
-
if (match) {
|
|
63
|
-
let commentMatches
|
|
64
|
-
let matchIndex = 0
|
|
65
|
-
while ((commentMatches = regex.exec(content)) !== null) {
|
|
66
|
-
if (commentMatches.index === regex.lastIndex) {
|
|
67
|
-
regex.lastIndex++ // This is necessary to avoid infinite loops
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// console.log('commentMatches', commentMatches)
|
|
71
|
-
// const command = `Transform ${commentMatches[2]}`
|
|
72
|
-
// console.log(command)
|
|
73
|
-
transformsFound.push({
|
|
74
|
-
spaces: commentMatches[1], // Preserve indentation
|
|
75
|
-
transform: commentMatches[2],
|
|
76
|
-
match: match[matchIndex]
|
|
77
|
-
})
|
|
78
|
-
// wait
|
|
79
|
-
matchIndex++
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// console.log('registeredTransforms', registeredTransforms)
|
|
83
|
-
|
|
84
|
-
const transformsToRun = pluginSortOrder(registeredTransforms, transformsFound)
|
|
85
|
-
if (mergedConfig.DEBUG) {
|
|
86
|
-
console.log('↓ transformsToRun')
|
|
87
|
-
console.log(transformsToRun)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const fileName = path.basename(filePath)
|
|
91
|
-
const outputFilePath = path.join(mergedConfig.outputDir, fileName)
|
|
92
|
-
|
|
93
|
-
// create folder path if doesnt exist
|
|
94
|
-
mkdirp.sync(mergedConfig.outputDir)
|
|
95
|
-
|
|
96
|
-
// run sort
|
|
97
|
-
let transformMsg = ''
|
|
98
|
-
for (const element of transformsToRun) {
|
|
99
|
-
// console.log('element', element)
|
|
100
|
-
transformMsg += ` ⁕ ${element.transform} \n`
|
|
101
|
-
// console.log('order', element.transform)
|
|
102
|
-
const newContent = await updateContents(element.match, mergedConfig)
|
|
103
|
-
const firstLineIndentation = element.spaces
|
|
104
|
-
const contentWithIndentation = newContent.split('\n').join(`\n` + element.spaces)
|
|
105
|
-
const preserveTabs = `${firstLineIndentation}${contentWithIndentation}`
|
|
106
|
-
|
|
107
|
-
content = content.replace(element.match, preserveTabs)
|
|
108
|
-
mergedConfig.outputContent = content
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
let notFoundNotice
|
|
112
|
-
if (!transformMsg) {
|
|
113
|
-
// console.log('config', config)
|
|
114
|
-
const notFound = transformsFound.map((x) => {
|
|
115
|
-
return `"${x.transform}"`
|
|
116
|
-
})
|
|
117
|
-
notFoundNotice = notFound
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// console.log('transformMsg', transformMsg)
|
|
121
|
-
|
|
122
|
-
const msg = outputFilePath.replace(cwd, '')
|
|
123
|
-
|
|
124
|
-
if (transformMsg) {
|
|
125
|
-
console.log(`✔ ${msg} Updated`)
|
|
126
|
-
// update file contents
|
|
127
|
-
fs.writeFileSync(outputFilePath, content)
|
|
128
|
-
console.log(` Transforms run`)
|
|
129
|
-
console.log(transformMsg)
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (notFoundNotice) {
|
|
133
|
-
const word = notFoundNotice.length > 1 ? 'transforms' : 'transform'
|
|
134
|
-
console.log(`ℹ Notice:`)
|
|
135
|
-
console.log(` Missing ${word} ${notFoundNotice.join(',')} in ${msg}`)
|
|
136
|
-
console.log()
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// set return values
|
|
141
|
-
mergedConfig.outputFilePath = outputFilePath
|
|
142
|
-
mergedConfig.outputContent = content
|
|
143
|
-
|
|
144
|
-
return mergedConfig
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
if (mergedConfig.DEBUG) {
|
|
148
|
-
console.log(`↓ ${filePath}`)
|
|
149
|
-
console.log(`[No match] <!-- ${mergedConfig.matchWord} --> comment found`)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// no match return original contents
|
|
153
|
-
return mergedConfig
|
|
154
|
-
}
|
package/lib/transforms/index.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
const code = require('./code')
|
|
2
|
-
const file = require('./file')
|
|
3
|
-
const remoteContent = require('./remote')
|
|
4
|
-
const toc = require('./toc')
|
|
5
|
-
|
|
6
|
-
const transforms = {
|
|
7
|
-
/**
|
|
8
|
-
* ### > TOC
|
|
9
|
-
*
|
|
10
|
-
* Generate table of contents from markdown file
|
|
11
|
-
*
|
|
12
|
-
* **Options:**
|
|
13
|
-
* - `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
|
|
16
|
-
* - `excludeText` - *string* - (optional): Text to exclude in the table of contents. Default `Table of Contents`
|
|
17
|
-
* - `maxDepth` - *number* - (optional): Max depth of headings. Default 4
|
|
18
|
-
*
|
|
19
|
-
* **Example:**
|
|
20
|
-
* ```md
|
|
21
|
-
* <!-- AUTO-GENERATED-CONTENT:START (TOC) -->
|
|
22
|
-
* toc will be generated here
|
|
23
|
-
* <!-- AUTO-GENERATED-CONTENT:END -->
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
|
|
27
|
-
*
|
|
28
|
-
* ---
|
|
29
|
-
* @param {string} content The current content of the comment block
|
|
30
|
-
* @param {object} options The options passed in from the comment declaration
|
|
31
|
-
* @return {string} Updated content to place in the content block
|
|
32
|
-
*/
|
|
33
|
-
TOC: toc,
|
|
34
|
-
/**
|
|
35
|
-
* ### > CODE
|
|
36
|
-
*
|
|
37
|
-
* Get code from file or URL and put in markdown
|
|
38
|
-
*
|
|
39
|
-
* **Options:**
|
|
40
|
-
* - `src`: The relative path to the code to pull in, or the `URL` where the raw code lives
|
|
41
|
-
* - `syntax` (optional): Syntax will be inferred by fileType if not specified
|
|
42
|
-
* - `header` (optional): Will add header comment to code snippet. Useful for pointing to relative source directory or adding live doc links
|
|
43
|
-
* - `lines` (optional): a range with lines of code which will then be replaced with code from the file. The line range should be defined as: "lines=*startLine*-*EndLine*" (for example: "lines=22-44"). Please see the example below
|
|
44
|
-
*
|
|
45
|
-
* **Example:**
|
|
46
|
-
* ```md
|
|
47
|
-
* <!-- AUTO-GENERATED-CONTENT:START (CODE:src=./relative/path/to/code.js) -->
|
|
48
|
-
* This content will be dynamically replaced with code from the file
|
|
49
|
-
* <!-- AUTO-GENERATED-CONTENT:END -->
|
|
50
|
-
* ```
|
|
51
|
-
*
|
|
52
|
-
* ```md
|
|
53
|
-
* <!-- AUTO-GENERATED-CONTENT:START (CODE:src=./relative/path/to/code.js&lines=22-44) -->
|
|
54
|
-
* This content will be dynamically replaced with code from the file lines 22 through 44
|
|
55
|
-
* <!-- AUTO-GENERATED-CONTENT:END -->
|
|
56
|
-
* ```
|
|
57
|
-
*
|
|
58
|
-
* Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
|
|
59
|
-
*
|
|
60
|
-
* ---
|
|
61
|
-
* @param {string} content The current content of the comment block
|
|
62
|
-
* @param {object} options The options passed in from the comment declaration
|
|
63
|
-
* @return {string} Updated inner contents of the comment block
|
|
64
|
-
*/
|
|
65
|
-
CODE: code,
|
|
66
|
-
/**
|
|
67
|
-
* ### > FILE
|
|
68
|
-
*
|
|
69
|
-
* Get local file contents.
|
|
70
|
-
*
|
|
71
|
-
* **Options:**
|
|
72
|
-
* - `src`: The relative path to the file to pull in
|
|
73
|
-
*
|
|
74
|
-
* **Example:**
|
|
75
|
-
* ```md
|
|
76
|
-
* <!-- AUTO-GENERATED-CONTENT:START (FILE:src=./path/to/file) -->
|
|
77
|
-
* This content will be dynamically replaced from the local file
|
|
78
|
-
* <!-- AUTO-GENERATED-CONTENT:END -->
|
|
79
|
-
* ```
|
|
80
|
-
*
|
|
81
|
-
* Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
|
|
82
|
-
*
|
|
83
|
-
* ---
|
|
84
|
-
* @param {string} content The current content of the comment block
|
|
85
|
-
* @param {object} options The options passed in from the comment declaration
|
|
86
|
-
* @return {string} Updated content to place in the content block
|
|
87
|
-
*/
|
|
88
|
-
FILE: file,
|
|
89
|
-
/**
|
|
90
|
-
* ### > REMOTE
|
|
91
|
-
*
|
|
92
|
-
* Get any remote Data and put in markdown
|
|
93
|
-
*
|
|
94
|
-
* **Options:**
|
|
95
|
-
* - `url`: The URL of the remote content to pull in
|
|
96
|
-
*
|
|
97
|
-
* **Example:**
|
|
98
|
-
* ```md
|
|
99
|
-
* <!-- AUTO-GENERATED-CONTENT:START (REMOTE:url=http://url-to-raw-md-file.md) -->
|
|
100
|
-
* This content will be dynamically replaced from the remote url
|
|
101
|
-
* <!-- AUTO-GENERATED-CONTENT:END -->
|
|
102
|
-
* ```
|
|
103
|
-
*
|
|
104
|
-
* Default `MATCHWORD` is `AUTO-GENERATED-CONTENT`
|
|
105
|
-
*
|
|
106
|
-
* ---
|
|
107
|
-
* @param {string} content The current content of the comment block
|
|
108
|
-
* @param {object} options The options passed in from the comment declaration
|
|
109
|
-
* @return {string} Updated content to place in the content block
|
|
110
|
-
*/
|
|
111
|
-
REMOTE: remoteContent,
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
module.exports = transforms
|