markdown-magic 2.6.0 → 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.
Files changed (61) hide show
  1. package/README.md +6 -10
  2. package/cli.js +5 -82
  3. package/lib/block-parser-js.test.js +179 -0
  4. package/lib/block-parser.js +389 -0
  5. package/lib/{utils/new-parser.test.js → block-parser.test.js} +168 -50
  6. package/lib/cli.js +234 -0
  7. package/lib/cli.test.js +409 -0
  8. package/lib/defaults.js +12 -0
  9. package/lib/index.js +319 -184
  10. package/lib/index.test.js +11 -0
  11. package/lib/options-parser.js +498 -0
  12. package/lib/options-parser.test.js +1237 -0
  13. package/lib/process-contents.js +330 -0
  14. package/lib/process-file.js +34 -0
  15. package/lib/transforms/code.js +67 -22
  16. package/lib/transforms/file.js +13 -10
  17. package/lib/transforms/remote.js +9 -6
  18. package/lib/transforms/toc.js +136 -64
  19. package/lib/transforms/wordCount.js +5 -0
  20. package/lib/utils/fs.js +340 -0
  21. package/lib/utils/fs.test.js +268 -0
  22. package/lib/utils/html-to-json/compat.js +42 -0
  23. package/lib/utils/html-to-json/format.js +64 -0
  24. package/lib/utils/html-to-json/index.js +37 -0
  25. package/lib/utils/html-to-json/lexer.js +345 -0
  26. package/lib/utils/html-to-json/parser.js +146 -0
  27. package/lib/utils/html-to-json/stringify.js +37 -0
  28. package/lib/utils/html-to-json/tags.js +171 -0
  29. package/lib/utils/index.js +19 -0
  30. package/{cli-utils.js → lib/utils/load-config.js} +2 -6
  31. package/lib/utils/logs.js +89 -0
  32. package/lib/utils/md/filters.js +20 -0
  33. package/lib/utils/md/find-code-blocks.js +80 -0
  34. package/lib/utils/md/find-date.js +32 -0
  35. package/lib/utils/md/find-frontmatter.js +94 -0
  36. package/lib/utils/md/find-frontmatter.test.js +17 -0
  37. package/lib/utils/md/find-html-tags.js +105 -0
  38. package/lib/utils/md/find-images.js +102 -0
  39. package/lib/utils/md/find-links.js +202 -0
  40. package/lib/utils/md/find-unmatched-html-tags.js +33 -0
  41. package/lib/utils/md/fixtures/2022-01-22-date-in-filename.md +14 -0
  42. package/lib/utils/md/fixtures/file-with-frontmatter.md +32 -0
  43. package/lib/utils/md/fixtures/file-with-links.md +143 -0
  44. package/lib/utils/md/md.test.js +37 -0
  45. package/lib/utils/md/parse.js +122 -0
  46. package/lib/utils/md/utils.js +19 -0
  47. package/lib/utils/regex-timeout.js +83 -0
  48. package/lib/utils/regex.js +38 -5
  49. package/lib/utils/remoteRequest.js +54 -0
  50. package/lib/utils/syntax.js +79 -0
  51. package/lib/utils/text.js +260 -0
  52. package/lib/utils/text.test.js +311 -0
  53. package/package.json +26 -26
  54. package/index.js +0 -46
  55. package/lib/processFile.js +0 -154
  56. package/lib/transforms/index.js +0 -114
  57. package/lib/updateContents.js +0 -125
  58. package/lib/utils/_md.test.js +0 -63
  59. package/lib/utils/new-parser.js +0 -412
  60. package/lib/utils/weird-parse.js +0 -230
  61. 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 &nbsp;&nbsp;&nbsp;
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 &nbsp;&nbsp;&nbsp; ',
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": "2.6.0",
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
- "index.js",
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
- "uvu": "uvu lib '.test.([mc]js|[jt]sx?)$'",
21
- "test": "ava --verbose",
22
- "test:watch": "ava --verbose --watch",
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",
@@ -35,30 +42,23 @@
35
42
  "url": "https://github.com/DavidWells/markdown-magic"
36
43
  },
37
44
  "dependencies": {
38
- "@technote-space/doctoc": "^2.4.7",
39
- "commander": "^7.2.0",
40
- "deepmerge": "^4.2.2",
41
- "find-up": "^5.0.0",
42
- "globby": "^10.0.2",
45
+ "@technote-space/doctoc": "2.4.7",
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
- "mkdirp": "^1.0.4",
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
- "safe-chalk": "^1.0.0"
57
- },
58
- "ava": {
59
- "files": [
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
@@ -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
- }