markdown-magic 3.2.0 → 3.3.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.
- package/README.md +7 -7
- package/cli.js +4 -3
- package/lib/argparse/README.md +11 -0
- package/lib/argparse/argparse.js +317 -0
- package/lib/argparse/argparse.test.js +370 -0
- package/lib/argparse/index.js +5 -0
- package/lib/argparse/splitOutsideQuotes.js +78 -0
- package/lib/argparse/splitOutsideQuotes.test.js +100 -0
- package/lib/block-parser.js +19 -4
- package/lib/cli.js +80 -192
- package/lib/cli.test.js +0 -387
- package/lib/globparse.js +170 -0
- package/lib/globparse.test.js +412 -0
- package/lib/index.js +51 -7
- package/lib/process-contents.js +14 -7
- package/lib/transforms/code/index.js +58 -8
- package/lib/transforms/file.js +4 -1
- package/lib/transforms/remote.js +1 -0
- package/lib/utils/remoteRequest.js +4 -0
- package/lib/utils/text.js +22 -10
- package/package.json +2 -3
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
const { test } = require('uvu')
|
|
3
|
+
const assert = require('uvu/assert')
|
|
4
|
+
const { deepLog } = require('../utils/logs')
|
|
5
|
+
const { uxParse } = require('./argparse')
|
|
6
|
+
|
|
7
|
+
const DEBUG = true
|
|
8
|
+
const logger = DEBUG ? console.log : () => {}
|
|
9
|
+
const deepLogger = DEBUG ? deepLog : () => {}
|
|
10
|
+
|
|
11
|
+
function logInput(rawArgs, result) {
|
|
12
|
+
logger('\n───────────────────────')
|
|
13
|
+
logger('Input:')
|
|
14
|
+
logger(`CLI ${rawArgs.join(' ')}`)
|
|
15
|
+
if (result) {
|
|
16
|
+
deepLog('result', result)
|
|
17
|
+
}
|
|
18
|
+
logger('───────────────────────\n')
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function stringToArgs(str) {
|
|
22
|
+
return str.split(' ') //.map(x => x.trim()).filter(x => x !== '')
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
test('Exports API', () => {
|
|
26
|
+
assert.equal(typeof uxParse, 'function', 'undefined val')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
const cmd00 = stringToArgs('lol = true cool = false')
|
|
30
|
+
test.only(`CLI ${cmd00.join(' ')}`, () => {
|
|
31
|
+
const result = uxParse(cmd00)
|
|
32
|
+
logInput(cmd00, result)
|
|
33
|
+
assert.equal(result.mergedOptions, { lol: true, cool: false })
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
const cmd000 = stringToArgs('--lol true --cool false')
|
|
37
|
+
test(`CLI ${cmd000.join(' ')}`, () => {
|
|
38
|
+
const result = uxParse(cmd000)
|
|
39
|
+
logInput(cmd000, result)
|
|
40
|
+
assert.equal(result.mergedOptions, { lol: true, cool: false })
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
const cmd0000 = stringToArgs('-lol true -cool false')
|
|
44
|
+
test(`CLI ${cmd0000.join(' ')}`, () => {
|
|
45
|
+
const result = uxParse(cmd0000)
|
|
46
|
+
logInput(cmd0000, result)
|
|
47
|
+
assert.equal(result.mergedOptions, { lol: true, cool: false })
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
const cmd00000 = stringToArgs('-lol -cool ')
|
|
51
|
+
test(`CLI ${cmd00000.join(' ')}`, () => {
|
|
52
|
+
const result = uxParse(cmd00000)
|
|
53
|
+
logInput(cmd00000, result)
|
|
54
|
+
assert.equal(result.mergedOptions, { lol: true, cool: true })
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
const cmd000000 = stringToArgs('--stage prod --cool wild = yolo')
|
|
58
|
+
test(`CLI ${cmd000000.join(' ')}`, () => {
|
|
59
|
+
const result = uxParse(cmd000000)
|
|
60
|
+
logInput(cmd000000, result)
|
|
61
|
+
assert.equal(result.mergedOptions, { stage: 'prod', cool: true, wild: 'yolo' })
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const cmd0 = stringToArgs('-f no word = { foo: bar }')
|
|
65
|
+
test(`Handles single dash options, CLI ${cmd0.join(' ')}`, () => {
|
|
66
|
+
const result = uxParse(cmd0)
|
|
67
|
+
logInput(cmd0, result)
|
|
68
|
+
assert.equal(result.mergedOptions.f, 'no')
|
|
69
|
+
assert.equal(result.mergedOptions.word, { foo: 'bar' })
|
|
70
|
+
assert.equal(result.mergedOptions, { f: 'no', word: { foo: 'bar' } })
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
const cmd1 = stringToArgs('-f -x -xyz ballin -u jimmy')
|
|
74
|
+
test(`flags in a row "CLI ${cmd1.join(' ')}"`, () => {
|
|
75
|
+
const result = uxParse(cmd1)
|
|
76
|
+
deepLog('result', result)
|
|
77
|
+
assert.equal(result.mergedOptions.xyz, 'ballin')
|
|
78
|
+
assert.equal(result.mergedOptions, { f: true, x: true, xyz: 'ballin', u: 'jimmy' })
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const cmd2 = stringToArgs('-f -x -xyz ballin = yo -u jimmy')
|
|
82
|
+
test(`flags in a row two "CLI ${cmd2.join(' ')}"`, () => {
|
|
83
|
+
const result = uxParse(cmd2)
|
|
84
|
+
deepLog('result', result)
|
|
85
|
+
assert.equal(result.mergedOptions.ballin, 'yo')
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
const cmd3 = stringToArgs('-f -x -xyz ballin = yo -u jimmy=timmy')
|
|
89
|
+
test(`flags in a row two "CLI ${cmd3.join(' ')}"`, () => {
|
|
90
|
+
const result = uxParse(cmd3)
|
|
91
|
+
deepLog('result', result)
|
|
92
|
+
assert.equal(result.mergedOptions.jimmy, 'timmy')
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
const cmd4 = stringToArgs(
|
|
96
|
+
'whatever=[uno] -v=false nice -funky no -word { foo: bar } -w yo --what nice -f -x -xyz false -u jimmy --testx --file **.md --u word',
|
|
97
|
+
)
|
|
98
|
+
test(`Handles glob options "CLI ${cmd4.join(' ')}"`, () => {
|
|
99
|
+
const result = uxParse(cmd4)
|
|
100
|
+
deepLog('result', result)
|
|
101
|
+
assert.equal(result.mergedOptions, {
|
|
102
|
+
whatever: ['uno'],
|
|
103
|
+
v: false,
|
|
104
|
+
nice: true,
|
|
105
|
+
funky: 'no',
|
|
106
|
+
word: { foo: 'bar' },
|
|
107
|
+
w: 'yo',
|
|
108
|
+
what: 'nice',
|
|
109
|
+
f: true,
|
|
110
|
+
x: true,
|
|
111
|
+
xyz: false,
|
|
112
|
+
u: [ 'jimmy', 'word' ],
|
|
113
|
+
testx: true,
|
|
114
|
+
file: '**.md',
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
const cmd5 = stringToArgs('--stage prod --cool wild=yolo')
|
|
119
|
+
test(`CLI ${cmd5.join(' ')}"`, () => {
|
|
120
|
+
const result = uxParse(cmd5)
|
|
121
|
+
deepLog('result', result)
|
|
122
|
+
assert.equal(result.mergedOptions, { stage: 'prod', cool: true, wild: 'yolo' })
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const cmd6 = stringToArgs('--stage prod --cool wild=yolo --stage dev')
|
|
126
|
+
test.skip(`Takes last value for same flag "CLI ${cmd6.join(' ')}"`, () => {
|
|
127
|
+
const result = uxParse(cmd6)
|
|
128
|
+
deepLog('result', result)
|
|
129
|
+
assert.equal(result.mergedOptions, { stage: 'dev', cool: true, wild: 'yolo' })
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const cmd7 = stringToArgs('--stage prod --cool wild="yo lo" --stage dev --stage prod')
|
|
133
|
+
test(`Combines duplicate values into a deduplicated array "CLI ${cmd7.join(' ')}"`, () => {
|
|
134
|
+
const result = uxParse(cmd7)
|
|
135
|
+
deepLog('result', result)
|
|
136
|
+
assert.equal(result.mergedOptions, { stage: ['prod', 'dev'], cool: true, wild: 'yo lo' })
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const cmd8 = stringToArgs('-stage prod -cool wild=yolo -stage dev')
|
|
140
|
+
test(`Combines duplicate values into an array "CLI ${cmd8.join(' ')}"`, () => {
|
|
141
|
+
const result = uxParse(cmd8)
|
|
142
|
+
deepLog('result', result)
|
|
143
|
+
assert.equal(result.mergedOptions, { stage: ['prod', 'dev'], cool: true, wild: 'yolo' })
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
const cmd9 = stringToArgs('-stage prod -cool wild=-yolo -stage dev -stage prod')
|
|
147
|
+
test(`Handles values with dashes "CLI ${cmd9.join(' ')}"`, () => {
|
|
148
|
+
const result = uxParse(cmd9)
|
|
149
|
+
deepLog('result', result)
|
|
150
|
+
assert.equal(result.mergedOptions, { stage: ['prod', 'dev'], cool: true, wild: '-yolo' })
|
|
151
|
+
})
|
|
152
|
+
|
|
153
|
+
const cmd10 = stringToArgs('-stage prod -cool wild=--yolo -stage dev -stage prod -stage dev')
|
|
154
|
+
test(`Handles values with dashes "CLI ${cmd10.join(' ')}"`, () => {
|
|
155
|
+
const result = uxParse(cmd10)
|
|
156
|
+
deepLog('result', result)
|
|
157
|
+
assert.equal(result.mergedOptions, { stage: ['prod', 'dev'], cool: true, wild: '--yolo' })
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
const cmd11 = stringToArgs('-stage prod -cool wild="--yolo"')
|
|
161
|
+
test(`Handles values with dashes "CLI ${cmd11.join(' ')}"`, () => {
|
|
162
|
+
const result = uxParse(cmd11)
|
|
163
|
+
deepLog('result', result)
|
|
164
|
+
assert.equal(result.mergedOptions, { stage: 'prod', cool: true, wild: '--yolo' })
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
const cmd12 = stringToArgs('-stage prod wild="yo=lo" -cool ')
|
|
168
|
+
const cmd13 = stringToArgs('wild="yo=lo" -stage prod -cool ')
|
|
169
|
+
const cmd14 = stringToArgs('-stage prod -cool wild="yo=lo"')
|
|
170
|
+
test(`Handles values with equals "CLI ${cmd12.join(' ')}"`, () => {
|
|
171
|
+
const array = [cmd12, cmd13, cmd14]
|
|
172
|
+
for (const cmd of array) {
|
|
173
|
+
const result = uxParse(cmd)
|
|
174
|
+
deepLog('result', result)
|
|
175
|
+
assert.equal(result.mergedOptions, { stage: 'prod', cool: true, wild: 'yo=lo' })
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
const cmd15 = stringToArgs('--param=userPoolId=us-west-1_fjsPJ6Q8J --param=userPoolClientId=19vdp5je9jsjkn488ddl4jvk19')
|
|
180
|
+
test(`Handles array values "CLI ${cmd15.join(' ')}"`, () => {
|
|
181
|
+
const result = uxParse(cmd15)
|
|
182
|
+
deepLog('result', result)
|
|
183
|
+
assert.equal(result.mergedOptions, {
|
|
184
|
+
param: ['userPoolId=us-west-1_fjsPJ6Q8J', 'userPoolClientId=19vdp5je9jsjkn488ddl4jvk19'],
|
|
185
|
+
})
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
const cmd16 = stringToArgs('--param="userPoolId=us-west-1_fjsPJ6Q8J" --param="userPoolClientId=19vdp5je9jsjkn488ddl4jvk19"')
|
|
189
|
+
test(`Strips surrounding quotes "CLI ${cmd16.join(' ')}"`, () => {
|
|
190
|
+
const result = uxParse(cmd16)
|
|
191
|
+
deepLog('result', result)
|
|
192
|
+
assert.equal(result.mergedOptions, {
|
|
193
|
+
param: ['userPoolId=us-west-1_fjsPJ6Q8J', 'userPoolClientId=19vdp5je9jsjkn488ddl4jvk19'],
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
const cmd17 = stringToArgs('--env.stage=prod --env.region=us-east-1')
|
|
198
|
+
test(`Handles dotted properties "CLI ${cmd17.join(' ')}"`, () => {
|
|
199
|
+
const result = uxParse(cmd17)
|
|
200
|
+
deepLog('result', result)
|
|
201
|
+
assert.equal(result.mergedOptions, {
|
|
202
|
+
'env.stage': 'prod',
|
|
203
|
+
'env.region': 'us-east-1'
|
|
204
|
+
})
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
const cmd18 = stringToArgs('--array=[1,2,3] --items=["a","b","c"]')
|
|
208
|
+
test(`Handles array syntax "CLI ${cmd18.join(' ')}"`, () => {
|
|
209
|
+
const result = uxParse(cmd18)
|
|
210
|
+
deepLog('result', result)
|
|
211
|
+
assert.equal(result.mergedOptions, {
|
|
212
|
+
array: [1, 2, 3],
|
|
213
|
+
items: ['a', 'b', 'c']
|
|
214
|
+
})
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
const cmd19 = stringToArgs('--config.json={"foo": "bar", "baz": 123}')
|
|
218
|
+
test(`Handles JSON objects "CLI ${cmd19.join(' ')}"`, () => {
|
|
219
|
+
const result = uxParse(cmd19)
|
|
220
|
+
deepLog('result', result)
|
|
221
|
+
assert.equal(result.mergedOptions, {
|
|
222
|
+
'config.json': { foo: 'bar', baz: 123 }
|
|
223
|
+
})
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
const cmd20 = stringToArgs('--empty --blank="" --null=null --undef=undefined')
|
|
227
|
+
test(`Handles special values "CLI ${cmd20.join(' ')}"`, () => {
|
|
228
|
+
const result = uxParse(cmd20)
|
|
229
|
+
deepLog('result', result)
|
|
230
|
+
assert.equal(result.mergedOptions, {
|
|
231
|
+
empty: true,
|
|
232
|
+
blank: '',
|
|
233
|
+
null: null,
|
|
234
|
+
undef: 'undefined' // @TODO fix this to undefined?
|
|
235
|
+
})
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
// @TODO invert no prefixes?
|
|
239
|
+
const cmd21 = stringToArgs('--flag --no-flag --enable-feature --no-enable-feature')
|
|
240
|
+
test(`Handles boolean flags with no- prefix "CLI ${cmd21.join(' ')}"`, () => {
|
|
241
|
+
const result = uxParse(cmd21)
|
|
242
|
+
deepLog('result', result)
|
|
243
|
+
assert.equal(result.mergedOptions, {
|
|
244
|
+
'no-flag': true,
|
|
245
|
+
flag: true,
|
|
246
|
+
'enable-feature': true,
|
|
247
|
+
'no-enable-feature': true
|
|
248
|
+
})
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
const cmd22 = stringToArgs(`--spaced-string="hello world" --quoted='single quotes'`)
|
|
252
|
+
test(`Handles quoted strings with spaces "CLI ${cmd22.join(' ')}"`, () => {
|
|
253
|
+
const result = uxParse(cmd22)
|
|
254
|
+
deepLog('result', result)
|
|
255
|
+
assert.equal(result.mergedOptions, {
|
|
256
|
+
'spaced-string': 'hello world',
|
|
257
|
+
quoted: 'single quotes'
|
|
258
|
+
})
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
// This one is wrong iirc
|
|
262
|
+
const cmd23 = stringToArgs('--numbers 1 2 3 --strings a b c')
|
|
263
|
+
test.skip(`Handles space-separated values "CLI ${cmd23.join(' ')}"`, () => {
|
|
264
|
+
const result = uxParse(cmd23)
|
|
265
|
+
deepLog('result', result)
|
|
266
|
+
assert.equal(result.mergedOptions, {
|
|
267
|
+
numbers: ['1', '2', '3'],
|
|
268
|
+
strings: ['a', 'b', 'c']
|
|
269
|
+
})
|
|
270
|
+
})
|
|
271
|
+
|
|
272
|
+
const cmd24 = stringToArgs(`--key=value --key="other value" --key='third value'`)
|
|
273
|
+
test(`Handles multiple values for same key with different quote styles "CLI ${cmd24.join(' ')}"`, () => {
|
|
274
|
+
const result = uxParse(cmd24)
|
|
275
|
+
deepLog('result', result)
|
|
276
|
+
assert.equal(result.mergedOptions, {
|
|
277
|
+
key: ['value', 'other value', 'third value']
|
|
278
|
+
})
|
|
279
|
+
})
|
|
280
|
+
|
|
281
|
+
const cmd25 = stringToArgs('-abc -xyz=123 -def="value" -ghi')
|
|
282
|
+
test(`Handles single-letter flags in various formats "CLI ${cmd25.join(' ')}"`, () => {
|
|
283
|
+
const result = uxParse(cmd25, {
|
|
284
|
+
stripSingleDashOptions: true
|
|
285
|
+
})
|
|
286
|
+
deepLog('result', result)
|
|
287
|
+
assert.equal(result.mergedOptions, {
|
|
288
|
+
a: true,
|
|
289
|
+
b: true,
|
|
290
|
+
c: true,
|
|
291
|
+
xyz: 123,
|
|
292
|
+
def: 'value',
|
|
293
|
+
g: true,
|
|
294
|
+
h: true,
|
|
295
|
+
i: true
|
|
296
|
+
})
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
const cmd26 = stringToArgs('--flag=true --flag=false --flag --no-flag')
|
|
300
|
+
test(`Handles multiple boolean assignments "CLI ${cmd26.join(' ')}"`, () => {
|
|
301
|
+
const result = uxParse(cmd26)
|
|
302
|
+
deepLog('result', result)
|
|
303
|
+
assert.equal(result.mergedOptions, {
|
|
304
|
+
flag: [
|
|
305
|
+
true,
|
|
306
|
+
false,
|
|
307
|
+
true,
|
|
308
|
+
],
|
|
309
|
+
'no-flag': true
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
const cmd27 = stringToArgs('-l -a -h')
|
|
315
|
+
test(`Short flags "CLI ${cmd27.join(' ')}"`, () => {
|
|
316
|
+
const result = uxParse(cmd27)
|
|
317
|
+
deepLog('result', result)
|
|
318
|
+
assert.equal(result.mergedOptions, {
|
|
319
|
+
l: true,
|
|
320
|
+
a: true,
|
|
321
|
+
h: true
|
|
322
|
+
})
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
const cmd28 = stringToArgs('-lah = yo')
|
|
326
|
+
test(`flag clustering "CLI ${cmd28.join(' ')}"`, () => {
|
|
327
|
+
const result = uxParse(cmd28, true)
|
|
328
|
+
deepLog('result', result)
|
|
329
|
+
assert.equal(result.mergedOptions, {
|
|
330
|
+
l: true,
|
|
331
|
+
a: true,
|
|
332
|
+
h: true
|
|
333
|
+
})
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
const cmd29 = stringToArgs('test.js --foo 1337 -B hello --mcgee')
|
|
338
|
+
test(`Short flags "CLI ${cmd29.join(' ')}"`, () => {
|
|
339
|
+
const result = uxParse(cmd29)
|
|
340
|
+
deepLog('result', result)
|
|
341
|
+
assert.equal(result.mergedOptions, {
|
|
342
|
+
foo: 1337,
|
|
343
|
+
B: 'hello',
|
|
344
|
+
mcgee: true
|
|
345
|
+
})
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
const cmd30 = stringToArgs('hey --foo=hi.hello?q=p hello')
|
|
350
|
+
test(`basic string parsing (equals long-arg-with-equals) "CLI ${cmd30.join(' ')}"`, () => {
|
|
351
|
+
const result = uxParse(cmd30)
|
|
352
|
+
deepLog('result', result)
|
|
353
|
+
assert.equal(result.mergedOptions, {
|
|
354
|
+
// possibleLeadingCommands: ['hey'],
|
|
355
|
+
hey: true, // @TODO fix this do we want it?
|
|
356
|
+
foo: 'hi.hello?q=p',
|
|
357
|
+
hello: true
|
|
358
|
+
})
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
const cmd31 = stringToArgs('int=-5')
|
|
362
|
+
test(`basic int parsing "CLI ${cmd31.join(' ')}"`, () => {
|
|
363
|
+
const result = uxParse(cmd31)
|
|
364
|
+
deepLog('result', result)
|
|
365
|
+
assert.equal(result.mergedOptions, {
|
|
366
|
+
int: -5
|
|
367
|
+
})
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
test.run()
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
function splitOutsideQuotes(str) {
|
|
4
|
+
|
|
5
|
+
str = str
|
|
6
|
+
.replace(/}(?=(?:(?:[^"]*(?:")){2})*[^"]*(?:")[^"]*$)/g, '∆') // For } in double " quotes
|
|
7
|
+
.replace(/}(?=(?:(?:[^']*(?:')){2})*[^']*(?:')[^']*$)/g, '∆') // For } in single ' quotes
|
|
8
|
+
.replace(/{(?=(?:(?:[^']*(?:')){2})*[^']*(?:')[^']*$)/g, '▽') // For { in single ' quotes
|
|
9
|
+
.replace(/{(?=(?:(?:[^"]*(?:")){2})*[^"]*(?:")[^"]*$)/g, '▽') // For { in double " quotes
|
|
10
|
+
.replace(/\[(?=(?:(?:[^']*(?:')){2})*[^']*(?:')[^']*$)/g, '▸') // For [ in single ' quotes
|
|
11
|
+
.replace(/\[(?=(?:(?:[^"]*(?:")){2})*[^"]*(?:")[^"]*$)/g, '▸') // For [ in double " quotes
|
|
12
|
+
.replace(/\](?=(?:(?:[^']*(?:')){2})*[^']*(?:')[^']*$)/g, '◂') // For ] in single ' quotes
|
|
13
|
+
.replace(/\](?=(?:(?:[^"]*(?:")){2})*[^"]*(?:")[^"]*$)/g, '◂') // For ] in double " quotes
|
|
14
|
+
|
|
15
|
+
let parts = []
|
|
16
|
+
let current = ''
|
|
17
|
+
let inQuotes = false
|
|
18
|
+
let quoteChar = ''
|
|
19
|
+
let braceCount = 0
|
|
20
|
+
let bracketCount = 0
|
|
21
|
+
|
|
22
|
+
for (let char of str) {
|
|
23
|
+
if ((char === '"' || char === "'") && !inQuotes) {
|
|
24
|
+
inQuotes = true
|
|
25
|
+
quoteChar = char
|
|
26
|
+
current += char
|
|
27
|
+
} else if (char === quoteChar && inQuotes) {
|
|
28
|
+
inQuotes = false
|
|
29
|
+
quoteChar = ''
|
|
30
|
+
current += char
|
|
31
|
+
} else if (char === '{') {
|
|
32
|
+
braceCount++
|
|
33
|
+
current += char
|
|
34
|
+
} else if (char === '}') {
|
|
35
|
+
braceCount--
|
|
36
|
+
current += char
|
|
37
|
+
} else if (char === '[') {
|
|
38
|
+
bracketCount++
|
|
39
|
+
current += char
|
|
40
|
+
} else if (char === ']') {
|
|
41
|
+
bracketCount--
|
|
42
|
+
current += char
|
|
43
|
+
} else if (char === ' ' && !inQuotes && !braceCount && !bracketCount) {
|
|
44
|
+
if (current) parts.push(current)
|
|
45
|
+
current = ''
|
|
46
|
+
} else {
|
|
47
|
+
current += char
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (current) parts.push(current)
|
|
52
|
+
return parts.map((x) => {
|
|
53
|
+
return x
|
|
54
|
+
.replace(/∆/g, '}')
|
|
55
|
+
.replace(/▽/g, '{')
|
|
56
|
+
.replace(/▸/g, '[')
|
|
57
|
+
.replace(/◂/g, ']')
|
|
58
|
+
})
|
|
59
|
+
/* combineEquals */
|
|
60
|
+
.reduce((acc, item, i) => {
|
|
61
|
+
if (item.startsWith('=')) {
|
|
62
|
+
acc[acc.length - 1] += item
|
|
63
|
+
return acc
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (acc.length && acc[acc.length - 1].endsWith('=') && (acc[acc.length - 1].match(/=/g) || []).length === 1) {
|
|
67
|
+
acc[acc.length - 1] += item
|
|
68
|
+
return acc
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
acc.push(item)
|
|
72
|
+
return acc
|
|
73
|
+
}, [])
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
module.exports = {
|
|
77
|
+
splitOutsideQuotes
|
|
78
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const { test } = require('uvu')
|
|
2
|
+
const assert = require('uvu/assert')
|
|
3
|
+
const { splitOutsideQuotes } = require('./splitOutsideQuotes')
|
|
4
|
+
|
|
5
|
+
test('Exports API', () => {
|
|
6
|
+
assert.equal(typeof splitOutsideQuotes, 'function', 'undefined val')
|
|
7
|
+
})
|
|
8
|
+
|
|
9
|
+
test('splitOutsideQuotes', () => {
|
|
10
|
+
const tests = [
|
|
11
|
+
`command arg1 arg2`,
|
|
12
|
+
`command arg1 arg2 arg3 --stage prod`,
|
|
13
|
+
`command arg1 arg2 arg3 --stage prod --stage dev`,
|
|
14
|
+
`command arg1 arg2 arg3 --stage prod --stage dev stage = prod`,
|
|
15
|
+
`test key="some value" other='single quotes'`,
|
|
16
|
+
`complex obj={ test: true, nested: { wow: 1 } } simple=2`,
|
|
17
|
+
`complex obj="{ test: true, nested: { wow: 1 } }" simple=2`,
|
|
18
|
+
`complex obj='{ test: true, nested: { wow: 1, with: "sp ac es" } }' simple=2`,
|
|
19
|
+
`array=[ 1, 2, "spaces here", { a: 1 } ] end=true`,
|
|
20
|
+
`array='[ 1, 2, "spaces here", { a: 1 } ]' end=true`,
|
|
21
|
+
`array="[ 1, 2, 'spaces here', { a: 1 } ]" end=true`,
|
|
22
|
+
`mix="quoted { brackets }" obj={ unquoted: "value" }`,
|
|
23
|
+
`mix="quoted { brackets }" obj={ unquoted: "val ue" }`,
|
|
24
|
+
`mix="quoted { brackets }" obj={ unquoted: "val} foo" }`,
|
|
25
|
+
`mix="quoted [ ]" obj=[ 1, 2, 3, "cool beans" ]`,
|
|
26
|
+
`mix="quoted [ ]" obj=[ 1, 2, 3, "cool ]beans" ]`,
|
|
27
|
+
`mix="quoted [ ]" obj={ nice: [ 1, 2, 3, 'nice', 'ra}d', "cool ]beans" ]}`,
|
|
28
|
+
`nice=true word = bond ab funky= 'fresh'`,
|
|
29
|
+
`nice=true word = bond ab funky= 'fre sh'`,
|
|
30
|
+
`nice=wowow= rad`,
|
|
31
|
+
`nice=wow=ow= rad=123`,
|
|
32
|
+
`nice = wow= rad`,
|
|
33
|
+
`nice = wo=w= rad`,
|
|
34
|
+
`nice wow= rad=123`,
|
|
35
|
+
]
|
|
36
|
+
const results = [
|
|
37
|
+
['command', 'arg1', 'arg2'],
|
|
38
|
+
['command', 'arg1', 'arg2', 'arg3', '--stage', 'prod'],
|
|
39
|
+
['command', 'arg1', 'arg2', 'arg3', '--stage', 'prod', '--stage', 'dev'],
|
|
40
|
+
['command', 'arg1', 'arg2', 'arg3', '--stage', 'prod', '--stage', 'dev', 'stage=prod'],
|
|
41
|
+
['test', 'key="some value"', 'other=\'single quotes\''],
|
|
42
|
+
['complex', 'obj={ test: true, nested: { wow: 1 } }', 'simple=2'],
|
|
43
|
+
['complex', 'obj="{ test: true, nested: { wow: 1 } }"', 'simple=2'],
|
|
44
|
+
['complex', `obj='{ test: true, nested: { wow: 1, with: "sp ac es" } }'`, 'simple=2'],
|
|
45
|
+
['array=[ 1, 2, "spaces here", { a: 1 } ]', 'end=true'],
|
|
46
|
+
['array=\'[ 1, 2, "spaces here", { a: 1 } ]\'', 'end=true'],
|
|
47
|
+
['array="[ 1, 2, \'spaces here\', { a: 1 } ]"', 'end=true'],
|
|
48
|
+
['mix="quoted { brackets }"', 'obj={ unquoted: "value" }'],
|
|
49
|
+
['mix="quoted { brackets }"', 'obj={ unquoted: "val ue" }'],
|
|
50
|
+
['mix="quoted { brackets }"', 'obj={ unquoted: "val} foo" }'],
|
|
51
|
+
['mix="quoted [ ]"', 'obj=[ 1, 2, 3, "cool beans" ]'],
|
|
52
|
+
['mix="quoted [ ]"', 'obj=[ 1, 2, 3, "cool ]beans" ]'],
|
|
53
|
+
[`mix="quoted [ ]"`, `obj={ nice: [ 1, 2, 3, 'nice', 'ra}d', "cool ]beans" ]}`],
|
|
54
|
+
[
|
|
55
|
+
'nice=true',
|
|
56
|
+
'word=bond',
|
|
57
|
+
'ab',
|
|
58
|
+
`funky='fresh'`
|
|
59
|
+
],
|
|
60
|
+
[
|
|
61
|
+
'nice=true',
|
|
62
|
+
'word=bond',
|
|
63
|
+
'ab',
|
|
64
|
+
`funky='fre sh'`
|
|
65
|
+
],
|
|
66
|
+
[
|
|
67
|
+
'nice=wowow=',
|
|
68
|
+
'rad'
|
|
69
|
+
],
|
|
70
|
+
[
|
|
71
|
+
'nice=wow=ow=',
|
|
72
|
+
'rad=123'
|
|
73
|
+
],
|
|
74
|
+
[
|
|
75
|
+
'nice=wow=',
|
|
76
|
+
'rad'
|
|
77
|
+
],
|
|
78
|
+
[
|
|
79
|
+
'nice=wo=w=',
|
|
80
|
+
'rad'
|
|
81
|
+
],
|
|
82
|
+
[
|
|
83
|
+
'nice',
|
|
84
|
+
'wow=rad=123'
|
|
85
|
+
]
|
|
86
|
+
]
|
|
87
|
+
for (let i = 0; i < tests.length; i++) {
|
|
88
|
+
const test = tests[i]
|
|
89
|
+
const result = splitOutsideQuotes(test)
|
|
90
|
+
/*
|
|
91
|
+
console.log('test', test)
|
|
92
|
+
console.log('result', result)
|
|
93
|
+
console.log('───────────────────────────────')
|
|
94
|
+
// process.exit(1)
|
|
95
|
+
/** */
|
|
96
|
+
assert.equal(result, results[i], `test ${i}. \nExpected ${results[i]} \nGot..... ${result}`)
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
test.run()
|
package/lib/block-parser.js
CHANGED
|
@@ -21,8 +21,14 @@ function parseBlocks(contents, opts = {}) {
|
|
|
21
21
|
closeText: close
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
+
// console.log(patterns)
|
|
25
|
+
|
|
24
26
|
const newerRegex = patterns.blockPattern
|
|
25
|
-
|
|
27
|
+
/*
|
|
28
|
+
console.log('newerRegex', newerRegex)
|
|
29
|
+
console.log('open', patterns.openPattern)
|
|
30
|
+
console.log('close', patterns.closePattern)
|
|
31
|
+
/** */
|
|
26
32
|
|
|
27
33
|
/*
|
|
28
34
|
const regexToUse = getBlockRegex({
|
|
@@ -47,7 +53,10 @@ function parseBlocks(contents, opts = {}) {
|
|
|
47
53
|
patterns.openPattern,
|
|
48
54
|
patterns.closePattern
|
|
49
55
|
)
|
|
50
|
-
|
|
56
|
+
/*
|
|
57
|
+
console.log('isBalanced', isBalanced)
|
|
58
|
+
/** */
|
|
59
|
+
|
|
51
60
|
const balanced = (closeCount > openCount) ? true : isBalanced
|
|
52
61
|
if (!balanced) {
|
|
53
62
|
throw new Error(`[Parsing error]
|
|
@@ -68,7 +77,7 @@ Details:
|
|
|
68
77
|
let paramString = ''
|
|
69
78
|
let options = {}
|
|
70
79
|
const [ block, spaces, openTag, type, params = '', content, closeTag ] = newMatches
|
|
71
|
-
|
|
80
|
+
|
|
72
81
|
let transformType = type
|
|
73
82
|
paramString = params.trim()
|
|
74
83
|
|
|
@@ -87,6 +96,7 @@ Details:
|
|
|
87
96
|
/** */
|
|
88
97
|
const isMultiline = block.indexOf('\n') > -1
|
|
89
98
|
const indentation = spaces || ''
|
|
99
|
+
// console.log('indentation', `"${indentation}"`)
|
|
90
100
|
let context = {
|
|
91
101
|
isMultiline,
|
|
92
102
|
}
|
|
@@ -184,7 +194,9 @@ Details:
|
|
|
184
194
|
|
|
185
195
|
function verifyTagsBalanced(str, open, close) {
|
|
186
196
|
const openCount = (str.match(open) || []).length
|
|
197
|
+
// console.log('openCount', openCount)
|
|
187
198
|
const closeCount = (str.match(close) || []).length
|
|
199
|
+
// console.log('closeCount', closeCount)
|
|
188
200
|
return {
|
|
189
201
|
isBalanced: openCount === closeCount,
|
|
190
202
|
openCount,
|
|
@@ -271,9 +283,12 @@ function getBlockRegex({
|
|
|
271
283
|
const matchWord = `${boundary}${openText}${boundary}`
|
|
272
284
|
const hasOne = (allowMissingTransforms) ? '*' : '+'
|
|
273
285
|
const open = `((?:${openComment}${emojiPat}(?:\\r?|\\n?|\\s*)${matchWord})\\s*[(\\[\\{]*([A-Za-z0-9_$]${hasOne})[)\\]\\}]*\\s*((?:.|\\r?\\n)*?)${closeComment}\\n?)`
|
|
286
|
+
// const close = `(\\n?[ \\t]?${openComment}${emojiPat}(?:\\r?|\\n?|\\s*)${closeText}(?:.|\\r?\\n)*?${closeComment})`
|
|
274
287
|
const close = `(\\n?[ \\t]*${openComment}${emojiPat}(?:\\r?|\\n?|\\s*)${closeText}(?:.|\\r?\\n)*?${closeComment})`
|
|
275
288
|
// const close = `(\\n?${openComment}(?:.*|\\r?|\\n?|\\s*)${closeText}(?:.|\\r?\\n)*?${closeComment})`
|
|
276
|
-
const blockPattern = new RegExp(`([ \\t]*)${open}([\\s\\S]
|
|
289
|
+
const blockPattern = new RegExp(`([ \\t]*)${open}([\\s\\S]*?)${close}`, 'gmi')
|
|
290
|
+
// 👇 repeat error with .* on weird contents
|
|
291
|
+
// const blockPattern = new RegExp(`([ \\t]*)${open}([\\s\\S]*?.*)${close}`, 'gmi')
|
|
277
292
|
const openPattern = new RegExp(open, 'gi')
|
|
278
293
|
const closePattern = new RegExp(close, 'gi')
|
|
279
294
|
|