markdown-magic 2.6.1 → 3.0.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 +47 -37
- package/cli.js +5 -82
- package/lib/block-parser-js.test.js +171 -0
- package/lib/block-parser.js +382 -0
- package/lib/block-parser.test.js +479 -0
- package/lib/cli.js +245 -0
- package/lib/cli.test.js +409 -0
- package/lib/defaults.js +12 -0
- package/lib/globals.d.ts +66 -0
- package/lib/index.js +353 -184
- package/lib/index.test.js +11 -0
- package/lib/process-contents.js +371 -0
- package/lib/process-file.js +37 -0
- package/lib/transforms/code.js +67 -28
- package/lib/transforms/file.js +17 -17
- package/lib/transforms/index.js +0 -114
- package/lib/transforms/remote.js +8 -6
- package/lib/transforms/sectionToc.js +18 -0
- package/lib/transforms/toc.js +12 -265
- package/lib/transforms/wordCount.js +5 -0
- package/lib/types.js +11 -0
- package/lib/utils/fs.js +342 -0
- package/lib/utils/fs.test.js +267 -0
- package/lib/utils/index.js +19 -0
- package/{cli-utils.js → lib/utils/load-config.js} +2 -6
- package/lib/utils/logs.js +94 -0
- package/lib/utils/md/filters.js +20 -0
- package/lib/utils/md/find-code-blocks.js +88 -0
- package/lib/utils/md/find-date.js +32 -0
- package/lib/utils/md/find-frontmatter.js +92 -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-md.js +27 -0
- package/lib/utils/md/find-images.js +107 -0
- package/lib/utils/md/find-links.js +220 -0
- package/lib/utils/md/find-unmatched-html-tags.js +32 -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 +153 -0
- package/lib/utils/md/md.test.js +105 -0
- package/lib/utils/md/parse.js +146 -0
- package/lib/utils/md/utils.js +19 -0
- package/lib/utils/regex-timeout.js +84 -0
- package/lib/utils/regex.js +40 -6
- package/lib/utils/remoteRequest.js +55 -0
- package/lib/utils/syntax.js +82 -0
- package/lib/utils/text.js +328 -0
- package/lib/utils/text.test.js +305 -0
- package/lib/utils/toc.js +315 -0
- package/package.json +30 -26
- package/index.js +0 -46
- package/lib/processFile.js +0 -154
- 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/new-parser.test.js +0 -324
- package/lib/utils/weird-parse.js +0 -230
- package/lib/utils/weird-parse.test.js +0 -217
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
const html = {
|
|
2
|
+
tags: [
|
|
3
|
+
'<!--',
|
|
4
|
+
'-->'
|
|
5
|
+
],
|
|
6
|
+
pattern: [
|
|
7
|
+
'<!-{2,}',
|
|
8
|
+
'-{2,}>' // '-->'
|
|
9
|
+
],
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Kramdown https://github.com/HHS/nih-oite-website/blob/480244abfd0f0d741b27d6232273dd03073e06ad/app/javascript/kramdown/parser.js#L12-L48
|
|
13
|
+
|
|
14
|
+
// JS https://regex101.com/r/XKHU18/5
|
|
15
|
+
const js = {
|
|
16
|
+
tags: ['/*', '*/'],
|
|
17
|
+
pattern: [
|
|
18
|
+
'\/\\*+',
|
|
19
|
+
// Old ^ '\/\\*{1,}[\n\\*]*', // '\/\\*+', '\/\*[\*\n\s\t]+', //
|
|
20
|
+
'\\*+/'
|
|
21
|
+
],
|
|
22
|
+
/* Match single line JS comment */
|
|
23
|
+
singleLineTag: '//',
|
|
24
|
+
singleLinePattern: '//+',
|
|
25
|
+
singleLine: '\/\/.*$'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const jsx = {
|
|
29
|
+
tags: [
|
|
30
|
+
'{/*',
|
|
31
|
+
'*/}'
|
|
32
|
+
],
|
|
33
|
+
pattern: [
|
|
34
|
+
'\{\/\\*+',
|
|
35
|
+
'\\*+/\}'
|
|
36
|
+
]
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const yaml = {
|
|
40
|
+
tags: ['##', '##'],
|
|
41
|
+
pattern: [
|
|
42
|
+
'##+',
|
|
43
|
+
'##+'
|
|
44
|
+
],
|
|
45
|
+
singleLineTag: '#',
|
|
46
|
+
singleLinePattern: '#+',
|
|
47
|
+
singleLine: '#.*$',
|
|
48
|
+
content: '[ \\t\\S]*?',
|
|
49
|
+
converter: (str) => {
|
|
50
|
+
return str.split('\n').map((line) => {
|
|
51
|
+
return line[0] === '#' ? line : `#${line}`
|
|
52
|
+
}).join()
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const syntaxMap = {
|
|
57
|
+
// <!-- x -->
|
|
58
|
+
md: html,
|
|
59
|
+
markdown: html,
|
|
60
|
+
// <!-- x -->
|
|
61
|
+
html: html,
|
|
62
|
+
// /* x */
|
|
63
|
+
js: js,
|
|
64
|
+
// {/* x */}
|
|
65
|
+
jsx: jsx,
|
|
66
|
+
mdx: jsx,
|
|
67
|
+
// ## x ##
|
|
68
|
+
yaml: yaml,
|
|
69
|
+
yml: yaml
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Additional comment syntaxes for future
|
|
73
|
+
// https://github.com/apidoc/apidoc/tree/27566b48a9e8bad2fb3920c02473940917eabe70#supported-programming-languages
|
|
74
|
+
|
|
75
|
+
function getSyntaxInfo(syntax = '') {
|
|
76
|
+
return syntaxMap[syntax.toLowerCase()] || {}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = {
|
|
80
|
+
getSyntaxInfo,
|
|
81
|
+
syntaxMap
|
|
82
|
+
}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
const { syntaxMap } = require('./syntax')
|
|
2
|
+
|
|
3
|
+
function getLines(str = '') {
|
|
4
|
+
return str.split(/\r\n|\r|\n/)
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function getLineCount(str = '') {
|
|
8
|
+
return getLines(str).length
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function getRowAndColumnFromCharPos(input, indexToFind) {
|
|
12
|
+
const preChunk = input.substr(0, indexToFind);
|
|
13
|
+
const row = preChunk.split('\n').length - 1
|
|
14
|
+
const lastIndexOfNewLine = input.lastIndexOf('\n', indexToFind);
|
|
15
|
+
const col = lastIndexOfNewLine > 0 ? indexToFind - lastIndexOfNewLine - 1 : indexToFind;
|
|
16
|
+
return { row, col }
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
function getWordCount(str = '') {
|
|
20
|
+
return str.trim().split(/\s+/).length
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function getFirstCharacter(str) {
|
|
24
|
+
return str.charAt(0)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function getLastCharacter(str) {
|
|
28
|
+
return str.substr(-1)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function getLeadingSpaces(text) {
|
|
32
|
+
const matches = text.match(/^\s*/)
|
|
33
|
+
return (matches && matches[0]) ? matches[0] : ''
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getTextBetweenChars(text, start, end) {
|
|
37
|
+
return text.slice(start, end)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get text between two words
|
|
42
|
+
* @param {string} s
|
|
43
|
+
* @param {string} prefix
|
|
44
|
+
* @param {string} suffix
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
function getTextBetweenWords(s, prefix, suffix) {
|
|
48
|
+
let i = s.indexOf(prefix)
|
|
49
|
+
if (i === -1) return ''
|
|
50
|
+
s = s.substring(i + prefix.length)
|
|
51
|
+
if (suffix) {
|
|
52
|
+
i = s.indexOf(suffix)
|
|
53
|
+
if (i === -1) return ''
|
|
54
|
+
s = s.substring(0, i)
|
|
55
|
+
}
|
|
56
|
+
return s
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function replaceTextBetweenChars(str = '', start, end, newStr) {
|
|
60
|
+
return str.substring(0, start) + newStr + str.substring(end)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function getTextBetweenLines(content, startLine, endLine) {
|
|
64
|
+
const startDefined = typeof startLine !== 'undefined'
|
|
65
|
+
const endDefined = typeof endLine !== 'undefined'
|
|
66
|
+
if (!startDefined && !endDefined) return
|
|
67
|
+
|
|
68
|
+
const lines = getLines(content)
|
|
69
|
+
if (startDefined && !endDefined) {
|
|
70
|
+
return lines.slice(startLine - 1, startLine).join('')
|
|
71
|
+
}
|
|
72
|
+
if ((startLine) && (endLine) && parseInt(startLine, 10) <= parseInt(endLine, 10)) {
|
|
73
|
+
return lines.slice(startLine - 1, endLine).join('\n')
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isUpperCase(str) {
|
|
78
|
+
return str === str.toUpperCase()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// https://github.com/jamiebuilds/min-indent/blob/master/index.js
|
|
82
|
+
function findMinIndent(string) {
|
|
83
|
+
const match = string.match(/^[ \t]*(?=\S)/gm)
|
|
84
|
+
if (!match) return 0
|
|
85
|
+
return match.reduce((r, a) => Math.min(r, a.length), Infinity)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function stripIndent(string, indentation) {
|
|
89
|
+
const indent = typeof indentation !== 'undefined' ? indentation : findMinIndent(string);
|
|
90
|
+
if (indent === 0) {
|
|
91
|
+
return string
|
|
92
|
+
}
|
|
93
|
+
const regex = new RegExp(`^[ \\t]{${indent}}`, 'gm')
|
|
94
|
+
return string.replace(regex, '')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Trim leading & trailing spaces/line breaks in code and keeps the indentation of the first non-empty line
|
|
99
|
+
* @param {string|number} str
|
|
100
|
+
* @returns string
|
|
101
|
+
*/
|
|
102
|
+
function trimString(str = '') {
|
|
103
|
+
let content = (typeof str === 'number') ? str.toString() : str
|
|
104
|
+
// console.log('content', `"${content}"`)
|
|
105
|
+
return content.replace(/^(?:[\t ]*(?:\r?\n|\r))+|\s+$/g, '')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function indentString(string, count = 1, options = {}) {
|
|
109
|
+
const {
|
|
110
|
+
indent = ' ',
|
|
111
|
+
includeEmptyLines = false
|
|
112
|
+
} = options;
|
|
113
|
+
if (count === 0) return string
|
|
114
|
+
const regex = includeEmptyLines ? /^/gm : /^(?!\s*$)/gm
|
|
115
|
+
return string.replace(regex, indent.repeat(count))
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Removes the indentation of multiline strings
|
|
120
|
+
* @link https://github.com/victornpb/tiny-dedent/
|
|
121
|
+
* @param {string} str A template literal string
|
|
122
|
+
* @return {string} A string without the indentation
|
|
123
|
+
*/
|
|
124
|
+
function dedentString(str) {
|
|
125
|
+
str = str.replace(/^[ \t]*\r?\n/, ''); // remove leading blank line
|
|
126
|
+
var indent = /^[ \t]+/m.exec(str); // detected indent
|
|
127
|
+
if (indent) str = str.replace(new RegExp('^' + indent[0], 'gm'), ''); // remove indent
|
|
128
|
+
return str.replace(/(\r?\n)[ \t]+$/, '$1'); // remove trailling blank line
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Strip out comment blocks
|
|
133
|
+
* @param {string} str
|
|
134
|
+
* @param {'md' | 'js'} syntax
|
|
135
|
+
* @returns {string} clean commentless string
|
|
136
|
+
*/
|
|
137
|
+
function stripCommentBlockOld(str, syntax = 'md') {
|
|
138
|
+
const [ openPattern, closePattern ] = syntaxMap[syntax].pattern
|
|
139
|
+
const pattern = new RegExp(`^([ \\S]*)${openPattern}(\\s?[\\s\\S]*?)?${closePattern}\n?`, 'gim')
|
|
140
|
+
// console.log('pattern', pattern)
|
|
141
|
+
let newString = str
|
|
142
|
+
let matches
|
|
143
|
+
while ((matches = pattern.exec(str)) !== null) {
|
|
144
|
+
if (matches.index === pattern.lastIndex) {
|
|
145
|
+
pattern.lastIndex++ // avoid infinite loops with zero-width matches
|
|
146
|
+
}
|
|
147
|
+
const [ _match, leadingText ] = matches
|
|
148
|
+
/*
|
|
149
|
+
console.log('_match', _match)
|
|
150
|
+
console.log('leadingText', `"${leadingText}"`)
|
|
151
|
+
console.log('───────────────────────')
|
|
152
|
+
/**/
|
|
153
|
+
/* Handle comments that start midway through line after text */
|
|
154
|
+
if (leadingText) {
|
|
155
|
+
/* Trim trailing tabs/spaces */
|
|
156
|
+
const trimmed = leadingText.replace(/([ \t]*)$/, '')
|
|
157
|
+
const replacement = _match.replace(trimmed, '')
|
|
158
|
+
// console.log('replacement', `"${replacement}"`)
|
|
159
|
+
newString = newString.replace(replacement, `\n`)
|
|
160
|
+
// console.log('new str', newString)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// const pattern = new RegExp(`([ \\t]*)${openPattern}\\s?([\\s\\S]*?)?${closePattern}\n?`, 'gi')
|
|
165
|
+
return newString.replace(pattern, '')
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Strip out comment blocks
|
|
170
|
+
* @param {string} str
|
|
171
|
+
* @param {typeof import('../types')['syntaxType']} syntax
|
|
172
|
+
* @returns {string} clean commentless string
|
|
173
|
+
*/
|
|
174
|
+
function stripComments(str, syntax = 'md') {
|
|
175
|
+
const syntaxData = syntaxMap[syntax]
|
|
176
|
+
const [ openPattern, closePattern ] = syntaxData.pattern
|
|
177
|
+
const OR = (syntaxData.singleLine) ? `|\\s?[ \\t]*${syntaxData.singleLine}` : ''
|
|
178
|
+
const CONTENT = syntaxData.content || '[\\s\\S]*?'
|
|
179
|
+
const pattern = new RegExp(`\\s?[ \\t]*${openPattern}(${CONTENT})?${closePattern}${OR}`, 'gim')
|
|
180
|
+
console.log('pattern', pattern)
|
|
181
|
+
return str.replace(pattern, '')
|
|
182
|
+
// https://regex101.com/r/XKHU18/5
|
|
183
|
+
return str.replace(/\s?[ \t]*\/\*[\s\S]*?\*\/|\s?[ \t]*\/\/.*$|\/\*{1,}[\n\*]*(\s?[\s\S]*?)?\*+\//gm, '')
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// @TODO export as util to import into CODE
|
|
187
|
+
function stripAllComments(block) {
|
|
188
|
+
// ([^\s]*)?([ \t]*)?(\/\*{1,}[\n\*]*(\s?[\s\S]*?)?\*\/)([^\s<]*)?(\n{1,2})?
|
|
189
|
+
// https://regex101.com/r/WSioZ7/1
|
|
190
|
+
const pattern = new RegExp(`([^\\s]*)?([ \\t]*)?(<!-{2,}(\\s?[\\s\\S]*?)?-{2,}>)([^\\s<]*)?(\n{1,2})?`, 'gi')
|
|
191
|
+
// ALT https://regex101.com/r/hxppia/1
|
|
192
|
+
// Alt HTML comments https://regex101.com/r/EJyioz/1
|
|
193
|
+
|
|
194
|
+
// console.log('closeTagRegex', closeTagRegex)
|
|
195
|
+
let matches
|
|
196
|
+
let remove = []
|
|
197
|
+
while ((matches = pattern.exec(block)) !== null) {
|
|
198
|
+
if (matches.index === pattern.lastIndex) {
|
|
199
|
+
pattern.lastIndex++ // avoid infinite loops with zero-width matches
|
|
200
|
+
}
|
|
201
|
+
const [ match, leadingText, leadingSpace, comment, insideComment, trailingText, trailingNewLine ] = matches
|
|
202
|
+
/*
|
|
203
|
+
console.log('match', match)
|
|
204
|
+
console.log('leadingText', leadingText)
|
|
205
|
+
console.log('leadingSpace', leadingSpace)
|
|
206
|
+
console.log('comment', comment)
|
|
207
|
+
console.log('insideComment', insideComment)
|
|
208
|
+
console.log('trailingText', trailingText)
|
|
209
|
+
console.log('trailingNewLine', trailingNewLine)
|
|
210
|
+
/** */
|
|
211
|
+
const newLineCount = (trailingNewLine || '').length
|
|
212
|
+
const trailing = (!trailingText && newLineCount > 1) ? `${trailingNewLine || ''}` : ''
|
|
213
|
+
const leading = (leadingSpace) ? leadingSpace.slice(1) : ''
|
|
214
|
+
remove.push(`${leading}${comment}${trailing}`)
|
|
215
|
+
}
|
|
216
|
+
return remove.reduce((acc, curr) => {
|
|
217
|
+
return acc.replaceAll(curr, '')
|
|
218
|
+
}, block)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function convertCommentSyntax(str, { from, to }) {
|
|
222
|
+
const syntaxData = syntaxMap[from]
|
|
223
|
+
const [ openPattern, closePattern ] = syntaxData.pattern
|
|
224
|
+
const [ openTag, closeTag ] = syntaxMap[to].tags
|
|
225
|
+
// const match = ` *?\\${openPattern}([\\s\\S]*?)?${closePattern}\\n\\n*?`
|
|
226
|
+
const UseLeadingLine = ''// || '|\\s?[ \\t]*'
|
|
227
|
+
const OR = (syntaxData.singleLine) ? `|${UseLeadingLine}${syntaxData.singleLine}` : ''
|
|
228
|
+
const CONTENT = syntaxData.content || '[\\s\\S]*?'
|
|
229
|
+
const match = `${UseLeadingLine}${openPattern}(${CONTENT})?${closePattern}${OR}`
|
|
230
|
+
// const match = `${openPattern}(.*|\\r?|\\n?|\\s*)*${closePattern}`
|
|
231
|
+
const regexToUse = new RegExp(match, 'gm')
|
|
232
|
+
// console.log('regexToUse', regexToUse)
|
|
233
|
+
const found = str.match(regexToUse)
|
|
234
|
+
// console.log('found', found)
|
|
235
|
+
if (!found) {
|
|
236
|
+
return str
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
const pattern = syntaxData.singleLinePattern ? new RegExp(syntaxData.singleLinePattern) : new RegExp(openPattern)
|
|
240
|
+
// console.log('pattern', pattern)
|
|
241
|
+
for (let index = 0; index < found.length; index++) {
|
|
242
|
+
const comment = found[index]
|
|
243
|
+
const cleanComment = comment.replace(pattern, '')
|
|
244
|
+
/*
|
|
245
|
+
console.log('comment', comment)
|
|
246
|
+
console.log('cleanComment', cleanComment)
|
|
247
|
+
/** */
|
|
248
|
+
str = str.replace(comment, `${openTag}${cleanComment} ${closeTag}`)
|
|
249
|
+
}
|
|
250
|
+
return str
|
|
251
|
+
|
|
252
|
+
const newComment = found[0].replace(regexToUse, `${openTag}$1${closeTag}`)
|
|
253
|
+
const converter = syntaxMap[to].converter
|
|
254
|
+
const newText = (converter) ? converter(newComment) : newComment
|
|
255
|
+
return str.replace(regexToUse, newText)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* capitalize first letter
|
|
260
|
+
* @param {string} str
|
|
261
|
+
* @returns
|
|
262
|
+
*/
|
|
263
|
+
function capitalizeFirstLetter(str) {
|
|
264
|
+
return capitalize(str.charAt(0)) + str.slice(1)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* capitalize string
|
|
269
|
+
* @param {string} str
|
|
270
|
+
* @returns
|
|
271
|
+
*/
|
|
272
|
+
function capitalize(str = '') {
|
|
273
|
+
return str.toUpperCase()
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function camelCase(str = '') {
|
|
277
|
+
return str.replace(/[-_ ](\w)/g, (_, c) => c.toUpperCase())
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function kebabCase(str = '') {
|
|
281
|
+
return str.replace(/\B([A-Z])/g, '-$1').toLowerCase()
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
const smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
|
|
285
|
+
|
|
286
|
+
function toTitleCase(str = '') {
|
|
287
|
+
return str.replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, (match, index, title) => {
|
|
288
|
+
if (index > 0
|
|
289
|
+
&& index + match.length !== title.length
|
|
290
|
+
&& match.search(smallWords) > -1
|
|
291
|
+
&& title.charAt(index - 2) !== ':'
|
|
292
|
+
&& (title.charAt(index + match.length) !== '-' || title.charAt(index - 1) === '-')
|
|
293
|
+
&& title.charAt(index - 1).search(/[^\s-]/) < 0) {
|
|
294
|
+
return match.toLowerCase();
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (match.substr(1).search(/[A-Z]|\../) > -1) {
|
|
298
|
+
return match;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
return match.charAt(0).toUpperCase() + match.substr(1);
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
module.exports = {
|
|
306
|
+
toTitleCase,
|
|
307
|
+
getLines,
|
|
308
|
+
getLineCount,
|
|
309
|
+
getWordCount,
|
|
310
|
+
getLeadingSpaces,
|
|
311
|
+
getFirstCharacter,
|
|
312
|
+
getLastCharacter,
|
|
313
|
+
getRowAndColumnFromCharPos,
|
|
314
|
+
getTextBetweenChars,
|
|
315
|
+
getTextBetweenWords,
|
|
316
|
+
getTextBetweenLines,
|
|
317
|
+
replaceTextBetweenChars,
|
|
318
|
+
stripIndent,
|
|
319
|
+
indentString,
|
|
320
|
+
dedentString,
|
|
321
|
+
stripComments,
|
|
322
|
+
convertCommentSyntax,
|
|
323
|
+
// stripCommentBlockJS,
|
|
324
|
+
trimString,
|
|
325
|
+
// future https://github.com/junfengliang/autowrap
|
|
326
|
+
findMinIndent,
|
|
327
|
+
isUpperCase
|
|
328
|
+
}
|
|
@@ -0,0 +1,305 @@
|
|
|
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, 'md')
|
|
92
|
+
/*
|
|
93
|
+
console.log('parsedValue')
|
|
94
|
+
logOutput(parsedValue)
|
|
95
|
+
/** */
|
|
96
|
+
assert.equal(typeof parsedValue, 'string')
|
|
97
|
+
assert.equal(parsedValue.match(/-->/), null)
|
|
98
|
+
assert.equal(parsedValue.match(/<!--/), null)
|
|
99
|
+
assert.equal(parsedValue.split('\n'), [
|
|
100
|
+
'<h1 id="jdjdj">Netlify + FaunaDB ',
|
|
101
|
+
' <a href="https://app.netlify.com/start/deploy?repository=https://github.com/netlify/netlify-faunadb-example&stack=fauna">',
|
|
102
|
+
' <img src="https://www.netlify.com/img/deploy/button.svg">',
|
|
103
|
+
' </a>',
|
|
104
|
+
'</h1>',
|
|
105
|
+
'',
|
|
106
|
+
'foo o',
|
|
107
|
+
'',
|
|
108
|
+
'nice',
|
|
109
|
+
'',
|
|
110
|
+
'wooooooo',
|
|
111
|
+
'',
|
|
112
|
+
'cool',
|
|
113
|
+
'',
|
|
114
|
+
'rad',
|
|
115
|
+
'',
|
|
116
|
+
'',
|
|
117
|
+
'nice',
|
|
118
|
+
'',
|
|
119
|
+
'',
|
|
120
|
+
'lol',
|
|
121
|
+
'',
|
|
122
|
+
'',
|
|
123
|
+
'nice',
|
|
124
|
+
'',
|
|
125
|
+
'',
|
|
126
|
+
'',
|
|
127
|
+
'actual content',
|
|
128
|
+
'',
|
|
129
|
+
'',
|
|
130
|
+
'',
|
|
131
|
+
'<img src="https://www.netlify.com/img/deploy/button.svg"/>',
|
|
132
|
+
'',
|
|
133
|
+
'',
|
|
134
|
+
'<img src="https://www.hehhehehehe.com/img/deploy/button.svg" />',
|
|
135
|
+
'',
|
|
136
|
+
'',
|
|
137
|
+
'wowow',
|
|
138
|
+
'whatever we want ',
|
|
139
|
+
'',
|
|
140
|
+
'',
|
|
141
|
+
'xyz',
|
|
142
|
+
'',
|
|
143
|
+
'',
|
|
144
|
+
'nice',
|
|
145
|
+
'',
|
|
146
|
+
''
|
|
147
|
+
])
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
test('Remove Javascript comments', () => {
|
|
151
|
+
const parsedValue = stripComments(`
|
|
152
|
+
/*
|
|
153
|
+
Fooo bar
|
|
154
|
+
*/
|
|
155
|
+
console.log('cool')
|
|
156
|
+
console.log('multiline')/*
|
|
157
|
+
weird one
|
|
158
|
+
*/
|
|
159
|
+
console.log('inline') /* inline klsjlkajdsalkjd *****/
|
|
160
|
+
|
|
161
|
+
/* inline */
|
|
162
|
+
console.log('nice')
|
|
163
|
+
`, 'js')
|
|
164
|
+
/*
|
|
165
|
+
console.log('parsedValue')
|
|
166
|
+
logOutput(parsedValue)
|
|
167
|
+
/** */
|
|
168
|
+
assert.equal(typeof parsedValue, 'string')
|
|
169
|
+
assert.equal(parsedValue.match(/\/\*/), null)
|
|
170
|
+
assert.equal(parsedValue.match(/\*\//), null)
|
|
171
|
+
assert.equal(parsedValue.split('\n'), [
|
|
172
|
+
'',
|
|
173
|
+
"console.log('cool')",
|
|
174
|
+
"console.log('multiline')",
|
|
175
|
+
"console.log('inline')",
|
|
176
|
+
'',
|
|
177
|
+
"console.log('nice')",
|
|
178
|
+
''
|
|
179
|
+
])
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
test('Remove YAML comments', () => {
|
|
183
|
+
const parsedValue = stripComments(`
|
|
184
|
+
bob: cool
|
|
185
|
+
# Remove this
|
|
186
|
+
# And this Remove this
|
|
187
|
+
joe: cool
|
|
188
|
+
bill: "cool"
|
|
189
|
+
## Remove this
|
|
190
|
+
## And this
|
|
191
|
+
steve: 'cool' # inline comment
|
|
192
|
+
foo:
|
|
193
|
+
bar: lol
|
|
194
|
+
`, 'yml')
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
console.log('yml', dedentString(parsedValue))
|
|
198
|
+
console.log('parsedValue')
|
|
199
|
+
// deepLog(parsedValue)
|
|
200
|
+
logOutput(parsedValue)
|
|
201
|
+
/** */
|
|
202
|
+
assert.equal(typeof parsedValue, 'string')
|
|
203
|
+
assert.equal(parsedValue.match(/#/), null)
|
|
204
|
+
assert.equal(parsedValue.split('\n'), [
|
|
205
|
+
'',
|
|
206
|
+
' bob: cool',
|
|
207
|
+
' joe: cool',
|
|
208
|
+
' bill: "cool"',
|
|
209
|
+
" steve: 'cool'",
|
|
210
|
+
' foo:',
|
|
211
|
+
' bar: lol',
|
|
212
|
+
''
|
|
213
|
+
])
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('Convert comment syntax', () => {
|
|
217
|
+
const yml = `
|
|
218
|
+
bob: cool
|
|
219
|
+
# Remove this
|
|
220
|
+
# And this Remove this
|
|
221
|
+
joe: cool
|
|
222
|
+
bill: "cool"
|
|
223
|
+
## Remove this
|
|
224
|
+
## And this
|
|
225
|
+
steve: 'cool' # inline comment
|
|
226
|
+
foo:
|
|
227
|
+
bar: lol
|
|
228
|
+
`
|
|
229
|
+
const jsx = convertCommentSyntax(yml, {
|
|
230
|
+
from: 'yml',
|
|
231
|
+
to: 'jsx'
|
|
232
|
+
})
|
|
233
|
+
// logOutput(jsx)
|
|
234
|
+
|
|
235
|
+
assert.equal(jsx.split('\n'), [
|
|
236
|
+
'',
|
|
237
|
+
' bob: cool',
|
|
238
|
+
' {/* Remove this */}',
|
|
239
|
+
' {/* And this Remove this */}',
|
|
240
|
+
' joe: cool',
|
|
241
|
+
' bill: "cool"',
|
|
242
|
+
' {/* Remove this */}',
|
|
243
|
+
' {/* And this */}',
|
|
244
|
+
" steve: 'cool' {/* inline comment */}",
|
|
245
|
+
' foo:',
|
|
246
|
+
' bar: lol',
|
|
247
|
+
''
|
|
248
|
+
])
|
|
249
|
+
|
|
250
|
+
const js = convertCommentSyntax(yml, {
|
|
251
|
+
from: 'yml',
|
|
252
|
+
to: 'js'
|
|
253
|
+
})
|
|
254
|
+
// logOutput(js)
|
|
255
|
+
|
|
256
|
+
assert.equal(js.split('\n'), [
|
|
257
|
+
'',
|
|
258
|
+
' bob: cool',
|
|
259
|
+
' /* Remove this */',
|
|
260
|
+
' /* And this Remove this */',
|
|
261
|
+
' joe: cool',
|
|
262
|
+
' bill: "cool"',
|
|
263
|
+
' /* Remove this */',
|
|
264
|
+
' /* And this */',
|
|
265
|
+
" steve: 'cool' /* inline comment */",
|
|
266
|
+
' foo:',
|
|
267
|
+
' bar: lol',
|
|
268
|
+
''
|
|
269
|
+
])
|
|
270
|
+
|
|
271
|
+
const html = convertCommentSyntax(yml, {
|
|
272
|
+
from: 'yml',
|
|
273
|
+
to: 'html'
|
|
274
|
+
})
|
|
275
|
+
// logOutput(html)
|
|
276
|
+
|
|
277
|
+
assert.equal(html.split('\n'), [
|
|
278
|
+
'',
|
|
279
|
+
' bob: cool',
|
|
280
|
+
' <!-- Remove this -->',
|
|
281
|
+
' <!-- And this Remove this -->',
|
|
282
|
+
' joe: cool',
|
|
283
|
+
' bill: "cool"',
|
|
284
|
+
' <!-- Remove this -->',
|
|
285
|
+
' <!-- And this -->',
|
|
286
|
+
" steve: 'cool' <!-- inline comment -->",
|
|
287
|
+
' foo:',
|
|
288
|
+
' bar: lol',
|
|
289
|
+
''
|
|
290
|
+
])
|
|
291
|
+
|
|
292
|
+
// //*
|
|
293
|
+
// console.log('parsedValue')
|
|
294
|
+
// // deepLog(parsedValue)
|
|
295
|
+
// logOutput(parsedValue)
|
|
296
|
+
// /** */
|
|
297
|
+
// assert.equal(typeof parsedValue, 'string')
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
function logOutput(value) {
|
|
302
|
+
console.log(value.split('\n'))
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
test.run()
|