@diplodoc/transform 4.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/CHANGELOG.diplodoc.md +38 -0
- package/CHANGELOG.md +404 -0
- package/LICENSE +21 -0
- package/README.md +41 -0
- package/README.ru.md +36 -0
- package/dist/css/yfm.css +736 -0
- package/dist/css/yfm.css.map +7 -0
- package/dist/css/yfm.min.css +2 -0
- package/dist/css/yfm.min.css.map +7 -0
- package/dist/js/code.d.ts +1 -0
- package/dist/js/cut.d.ts +1 -0
- package/dist/js/index.d.ts +5 -0
- package/dist/js/polyfill.d.ts +1 -0
- package/dist/js/tabs.d.ts +1 -0
- package/dist/js/term/index.d.ts +1 -0
- package/dist/js/term/utils.d.ts +10 -0
- package/dist/js/utils.d.ts +2 -0
- package/dist/js/yfm.js +432 -0
- package/dist/js/yfm.js.map +7 -0
- package/dist/js/yfm.min.js +2 -0
- package/dist/js/yfm.min.js.map +7 -0
- package/lib/getObject.d.ts +2 -0
- package/lib/getObject.js +11 -0
- package/lib/getObject.js.map +1 -0
- package/lib/headings.d.ts +4 -0
- package/lib/headings.js +73 -0
- package/lib/headings.js.map +1 -0
- package/lib/highlight.d.ts +3 -0
- package/lib/highlight.js +29 -0
- package/lib/highlight.js.map +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +35 -0
- package/lib/index.js.map +1 -0
- package/lib/liquid/conditions.d.ts +4 -0
- package/lib/liquid/conditions.js +181 -0
- package/lib/liquid/conditions.js.map +1 -0
- package/lib/liquid/cycles.d.ts +4 -0
- package/lib/liquid/cycles.js +160 -0
- package/lib/liquid/cycles.js.map +1 -0
- package/lib/liquid/errors.d.ts +3 -0
- package/lib/liquid/errors.js +13 -0
- package/lib/liquid/errors.js.map +1 -0
- package/lib/liquid/evaluation.d.ts +3 -0
- package/lib/liquid/evaluation.js +138 -0
- package/lib/liquid/evaluation.js.map +1 -0
- package/lib/liquid/filters.d.ts +9 -0
- package/lib/liquid/filters.js +22 -0
- package/lib/liquid/filters.js.map +1 -0
- package/lib/liquid/index.d.ts +9 -0
- package/lib/liquid/index.js +87 -0
- package/lib/liquid/index.js.map +1 -0
- package/lib/liquid/lexical.d.ts +14 -0
- package/lib/liquid/lexical.js +79 -0
- package/lib/liquid/lexical.js.map +1 -0
- package/lib/liquid/services/argv.d.ts +15 -0
- package/lib/liquid/services/argv.js +17 -0
- package/lib/liquid/services/argv.js.map +1 -0
- package/lib/liquid/sourceMap.d.ts +24 -0
- package/lib/liquid/sourceMap.js +56 -0
- package/lib/liquid/sourceMap.js.map +1 -0
- package/lib/liquid/substitutions.d.ts +2 -0
- package/lib/liquid/substitutions.js +36 -0
- package/lib/liquid/substitutions.js.map +1 -0
- package/lib/liquid/utils.d.ts +8 -0
- package/lib/liquid/utils.js +24 -0
- package/lib/liquid/utils.js.map +1 -0
- package/lib/log.d.ts +18 -0
- package/lib/log.js +54 -0
- package/lib/log.js.map +1 -0
- package/lib/md.d.ts +14 -0
- package/lib/md.js +96 -0
- package/lib/md.js.map +1 -0
- package/lib/plugins/anchors/collect.d.ts +5 -0
- package/lib/plugins/anchors/collect.js +81 -0
- package/lib/plugins/anchors/collect.js.map +1 -0
- package/lib/plugins/anchors/constants.d.ts +2 -0
- package/lib/plugins/anchors/constants.js +6 -0
- package/lib/plugins/anchors/constants.js.map +1 -0
- package/lib/plugins/anchors/index.d.ts +7 -0
- package/lib/plugins/anchors/index.js +134 -0
- package/lib/plugins/anchors/index.js.map +1 -0
- package/lib/plugins/changelog/collect.d.ts +8 -0
- package/lib/plugins/changelog/collect.js +50 -0
- package/lib/plugins/changelog/collect.js.map +1 -0
- package/lib/plugins/changelog/index.d.ts +6 -0
- package/lib/plugins/changelog/index.js +131 -0
- package/lib/plugins/changelog/index.js.map +1 -0
- package/lib/plugins/changelog/types.d.ts +10 -0
- package/lib/plugins/changelog/types.js +3 -0
- package/lib/plugins/changelog/types.js.map +1 -0
- package/lib/plugins/checkbox/checkbox.d.ts +7 -0
- package/lib/plugins/checkbox/checkbox.js +91 -0
- package/lib/plugins/checkbox/checkbox.js.map +1 -0
- package/lib/plugins/checkbox/index.d.ts +8 -0
- package/lib/plugins/checkbox/index.js +12 -0
- package/lib/plugins/checkbox/index.js.map +1 -0
- package/lib/plugins/code.d.ts +3 -0
- package/lib/plugins/code.js +61 -0
- package/lib/plugins/code.js.map +1 -0
- package/lib/plugins/cut.d.ts +3 -0
- package/lib/plugins/cut.js +70 -0
- package/lib/plugins/cut.js.map +1 -0
- package/lib/plugins/deflist.d.ts +3 -0
- package/lib/plugins/deflist.js +8 -0
- package/lib/plugins/deflist.js.map +1 -0
- package/lib/plugins/file/const.d.ts +27 -0
- package/lib/plugins/file/const.js +47 -0
- package/lib/plugins/file/const.js.map +1 -0
- package/lib/plugins/file/file.d.ts +8 -0
- package/lib/plugins/file/file.js +63 -0
- package/lib/plugins/file/file.js.map +1 -0
- package/lib/plugins/file/index.d.ts +4 -0
- package/lib/plugins/file/index.js +9 -0
- package/lib/plugins/file/index.js.map +1 -0
- package/lib/plugins/images/collect.d.ts +8 -0
- package/lib/plugins/images/collect.js +43 -0
- package/lib/plugins/images/collect.js.map +1 -0
- package/lib/plugins/images/index.d.ts +10 -0
- package/lib/plugins/images/index.js +81 -0
- package/lib/plugins/images/index.js.map +1 -0
- package/lib/plugins/imsize/const.d.ts +7 -0
- package/lib/plugins/imsize/const.js +12 -0
- package/lib/plugins/imsize/const.js.map +1 -0
- package/lib/plugins/imsize/helpers.d.ts +6 -0
- package/lib/plugins/imsize/helpers.js +64 -0
- package/lib/plugins/imsize/helpers.js.map +1 -0
- package/lib/plugins/imsize/index.d.ts +8 -0
- package/lib/plugins/imsize/index.js +12 -0
- package/lib/plugins/imsize/index.js.map +1 -0
- package/lib/plugins/imsize/plugin.d.ts +3 -0
- package/lib/plugins/imsize/plugin.js +188 -0
- package/lib/plugins/imsize/plugin.js.map +1 -0
- package/lib/plugins/includes/collect.d.ts +8 -0
- package/lib/plugins/includes/collect.js +49 -0
- package/lib/plugins/includes/collect.js.map +1 -0
- package/lib/plugins/includes/index.d.ts +8 -0
- package/lib/plugins/includes/index.js +98 -0
- package/lib/plugins/includes/index.js.map +1 -0
- package/lib/plugins/links/collect.d.ts +7 -0
- package/lib/plugins/links/collect.js +74 -0
- package/lib/plugins/links/collect.js.map +1 -0
- package/lib/plugins/links/constants.d.ts +1 -0
- package/lib/plugins/links/constants.js +5 -0
- package/lib/plugins/links/constants.js.map +1 -0
- package/lib/plugins/links/index.d.ts +24 -0
- package/lib/plugins/links/index.js +178 -0
- package/lib/plugins/links/index.js.map +1 -0
- package/lib/plugins/meta.d.ts +3 -0
- package/lib/plugins/meta.js +8 -0
- package/lib/plugins/meta.js.map +1 -0
- package/lib/plugins/monospace.d.ts +3 -0
- package/lib/plugins/monospace.js +109 -0
- package/lib/plugins/monospace.js.map +1 -0
- package/lib/plugins/notes.d.ts +3 -0
- package/lib/plugins/notes.js +103 -0
- package/lib/plugins/notes.js.map +1 -0
- package/lib/plugins/sup.d.ts +3 -0
- package/lib/plugins/sup.js +8 -0
- package/lib/plugins/sup.js.map +1 -0
- package/lib/plugins/table/index.d.ts +3 -0
- package/lib/plugins/table/index.js +215 -0
- package/lib/plugins/table/index.js.map +1 -0
- package/lib/plugins/tabs.d.ts +4 -0
- package/lib/plugins/tabs.js +4 -0
- package/lib/plugins/tabs.js.map +1 -0
- package/lib/plugins/term/constants.d.ts +1 -0
- package/lib/plugins/term/constants.js +5 -0
- package/lib/plugins/term/constants.js.map +1 -0
- package/lib/plugins/term/index.d.ts +3 -0
- package/lib/plugins/term/index.js +108 -0
- package/lib/plugins/term/index.js.map +1 -0
- package/lib/plugins/term/termDefinitions.d.ts +4 -0
- package/lib/plugins/term/termDefinitions.js +125 -0
- package/lib/plugins/term/termDefinitions.js.map +1 -0
- package/lib/plugins/typings.d.ts +12 -0
- package/lib/plugins/typings.js +3 -0
- package/lib/plugins/typings.js.map +1 -0
- package/lib/plugins/utils.d.ts +6 -0
- package/lib/plugins/utils.js +30 -0
- package/lib/plugins/utils.js.map +1 -0
- package/lib/plugins/video/const.d.ts +10 -0
- package/lib/plugins/video/const.js +22 -0
- package/lib/plugins/video/const.js.map +1 -0
- package/lib/plugins/video/index.d.ts +8 -0
- package/lib/plugins/video/index.js +104 -0
- package/lib/plugins/video/index.js.map +1 -0
- package/lib/plugins/video/parsers.d.ts +6 -0
- package/lib/plugins/video/parsers.js +64 -0
- package/lib/plugins/video/parsers.js.map +1 -0
- package/lib/plugins/video/types.d.ts +34 -0
- package/lib/plugins/video/types.js +3 -0
- package/lib/plugins/video/types.js.map +1 -0
- package/lib/plugins/video/utils.d.ts +2 -0
- package/lib/plugins/video/utils.js +25 -0
- package/lib/plugins/video/utils.js.map +1 -0
- package/lib/plugins.d.ts +3 -0
- package/lib/plugins.js +36 -0
- package/lib/plugins.js.map +1 -0
- package/lib/sanitize.d.ts +12 -0
- package/lib/sanitize.js +572 -0
- package/lib/sanitize.js.map +1 -0
- package/lib/title.d.ts +7 -0
- package/lib/title.js +18 -0
- package/lib/title.js.map +1 -0
- package/lib/typings.d.ts +57 -0
- package/lib/typings.js +3 -0
- package/lib/typings.js.map +1 -0
- package/lib/utils.d.ts +13 -0
- package/lib/utils.js +79 -0
- package/lib/utils.js.map +1 -0
- package/lib/utilsFS.d.ts +27 -0
- package/lib/utilsFS.js +89 -0
- package/lib/utilsFS.js.map +1 -0
- package/lib/yfmlint/index.d.ts +26 -0
- package/lib/yfmlint/index.js +72 -0
- package/lib/yfmlint/index.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/index.d.ts +9 -0
- package/lib/yfmlint/markdownlint-custom-rule/index.js +22 -0
- package/lib/yfmlint/markdownlint-custom-rule/index.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm001.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm001.js +28 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm001.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm002.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm002.js +33 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm002.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm003.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm003.js +33 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm003.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm004.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm004.js +28 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm004.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm005.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm005.js +28 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm005.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm006.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm006.js +28 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm006.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm007.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm007.js +29 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm007.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm008.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm008.js +28 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm008.js.map +1 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm009.d.ts +2 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm009.js +47 -0
- package/lib/yfmlint/markdownlint-custom-rule/yfm009.js.map +1 -0
- package/lib/yfmlint/typings.d.ts +12 -0
- package/lib/yfmlint/typings.js +3 -0
- package/lib/yfmlint/typings.js.map +1 -0
- package/lib/yfmlint/utils.d.ts +9 -0
- package/lib/yfmlint/utils.js +22 -0
- package/lib/yfmlint/utils.js.map +1 -0
- package/lib/yfmlint/yfmlint.d.ts +3 -0
- package/lib/yfmlint/yfmlint.js +69 -0
- package/lib/yfmlint/yfmlint.js.map +1 -0
- package/package.json +106 -0
- package/src/.eslintrc +10 -0
- package/src/js/code.ts +65 -0
- package/src/js/cut.ts +57 -0
- package/src/js/index.ts +6 -0
- package/src/js/polyfill.js +27 -0
- package/src/js/term/index.ts +79 -0
- package/src/js/term/utils.ts +151 -0
- package/src/js/utils.ts +9 -0
- package/src/scss/_anchor.scss +33 -0
- package/src/scss/_code.scss +23 -0
- package/src/scss/_common.scss +407 -0
- package/src/scss/_cut.scss +42 -0
- package/src/scss/_file.scss +35 -0
- package/src/scss/_highlight.scss +96 -0
- package/src/scss/_note.scss +73 -0
- package/src/scss/_print.scss +20 -0
- package/src/scss/_term.scss +79 -0
- package/src/scss/_variables.scss +16 -0
- package/src/scss/yfm.scss +11 -0
- package/src/transform/getObject.ts +10 -0
- package/src/transform/headings.ts +88 -0
- package/src/transform/highlight.ts +33 -0
- package/src/transform/index.ts +50 -0
- package/src/transform/liquid/conditions.ts +259 -0
- package/src/transform/liquid/cycles.ts +244 -0
- package/src/transform/liquid/errors.ts +10 -0
- package/src/transform/liquid/evaluation.ts +145 -0
- package/src/transform/liquid/filters.ts +19 -0
- package/src/transform/liquid/index.ts +141 -0
- package/src/transform/liquid/lexical.ts +86 -0
- package/src/transform/liquid/services/argv.ts +23 -0
- package/src/transform/liquid/sourceMap.ts +72 -0
- package/src/transform/liquid/substitutions.ts +40 -0
- package/src/transform/liquid/utils.ts +30 -0
- package/src/transform/log.ts +60 -0
- package/src/transform/md.ts +123 -0
- package/src/transform/plugins/anchors/collect.ts +101 -0
- package/src/transform/plugins/anchors/constants.ts +2 -0
- package/src/transform/plugins/anchors/index.ts +166 -0
- package/src/transform/plugins/changelog/collect.ts +66 -0
- package/src/transform/plugins/changelog/index.ts +164 -0
- package/src/transform/plugins/changelog/types.ts +10 -0
- package/src/transform/plugins/checkbox/checkbox.ts +107 -0
- package/src/transform/plugins/checkbox/index.ts +15 -0
- package/src/transform/plugins/code.ts +79 -0
- package/src/transform/plugins/cut.ts +98 -0
- package/src/transform/plugins/deflist.ts +5 -0
- package/src/transform/plugins/file/README.md +34 -0
- package/src/transform/plugins/file/const.ts +46 -0
- package/src/transform/plugins/file/file.ts +82 -0
- package/src/transform/plugins/file/index.ts +10 -0
- package/src/transform/plugins/images/collect.ts +60 -0
- package/src/transform/plugins/images/index.ts +119 -0
- package/src/transform/plugins/imsize/const.ts +7 -0
- package/src/transform/plugins/imsize/helpers.ts +75 -0
- package/src/transform/plugins/imsize/index.ts +14 -0
- package/src/transform/plugins/imsize/plugin.ts +214 -0
- package/src/transform/plugins/includes/collect.ts +73 -0
- package/src/transform/plugins/includes/index.ts +127 -0
- package/src/transform/plugins/links/collect.ts +92 -0
- package/src/transform/plugins/links/constants.ts +1 -0
- package/src/transform/plugins/links/index.ts +218 -0
- package/src/transform/plugins/meta.ts +5 -0
- package/src/transform/plugins/monospace.ts +141 -0
- package/src/transform/plugins/notes.ts +134 -0
- package/src/transform/plugins/sup.ts +5 -0
- package/src/transform/plugins/table/index.ts +290 -0
- package/src/transform/plugins/tabs.ts +3 -0
- package/src/transform/plugins/term/constants.ts +1 -0
- package/src/transform/plugins/term/index.ts +139 -0
- package/src/transform/plugins/term/termDefinitions.ts +177 -0
- package/src/transform/plugins/typings.ts +14 -0
- package/src/transform/plugins/utils.ts +38 -0
- package/src/transform/plugins/video/const.ts +20 -0
- package/src/transform/plugins/video/index.ts +134 -0
- package/src/transform/plugins/video/parsers.ts +65 -0
- package/src/transform/plugins/video/types.ts +27 -0
- package/src/transform/plugins/video/utils.ts +24 -0
- package/src/transform/plugins.ts +35 -0
- package/src/transform/sanitize.ts +596 -0
- package/src/transform/title.ts +22 -0
- package/src/transform/typings.ts +64 -0
- package/src/transform/utils.ts +91 -0
- package/src/transform/utilsFS.ts +128 -0
- package/src/transform/yfmlint/README.md +48 -0
- package/src/transform/yfmlint/index.ts +124 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/index.ts +9 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm001.ts +36 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm002.ts +33 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm003.ts +33 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm004.ts +27 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm005.ts +27 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm006.ts +26 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm007.ts +28 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm008.ts +26 -0
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm009.ts +54 -0
- package/src/transform/yfmlint/typings.ts +13 -0
- package/src/transform/yfmlint/utils.ts +31 -0
- package/src/transform/yfmlint/yfmlint.ts +73 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import applySubstitutions from './substitutions';
|
|
2
|
+
import {prepareSourceMap} from './sourceMap';
|
|
3
|
+
|
|
4
|
+
import applyCycles from './cycles';
|
|
5
|
+
import applyConditions from './conditions';
|
|
6
|
+
|
|
7
|
+
import ArgvService, {ArgvSettings} from './services/argv';
|
|
8
|
+
import {Dictionary} from 'lodash';
|
|
9
|
+
|
|
10
|
+
const fence = '```';
|
|
11
|
+
|
|
12
|
+
const find = (open: string, close: string, string: string, index: number) => {
|
|
13
|
+
const start = string.indexOf(open, index);
|
|
14
|
+
const end = start > -1 ? string.indexOf(close, start + open.length) : -1;
|
|
15
|
+
|
|
16
|
+
return [start, end];
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const replace = (
|
|
20
|
+
open: string,
|
|
21
|
+
close: string,
|
|
22
|
+
value: (string: string) => string,
|
|
23
|
+
string: string,
|
|
24
|
+
) => {
|
|
25
|
+
let result = '';
|
|
26
|
+
let carriage = 0;
|
|
27
|
+
let [start, end] = find(open, close, string, carriage);
|
|
28
|
+
|
|
29
|
+
while (start > -1 && end > -1) {
|
|
30
|
+
const fragment = string.slice(start + open.length, end);
|
|
31
|
+
|
|
32
|
+
result += string.slice(carriage, start) + open + value(fragment) + close;
|
|
33
|
+
carriage = end + close.length;
|
|
34
|
+
[start, end] = find(open, close, string, carriage);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
result += string.slice(carriage);
|
|
38
|
+
|
|
39
|
+
return result;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function saveCode(
|
|
43
|
+
str: string,
|
|
44
|
+
vars: Record<string, unknown>,
|
|
45
|
+
codes: string[],
|
|
46
|
+
path?: string,
|
|
47
|
+
substitutions?: boolean,
|
|
48
|
+
) {
|
|
49
|
+
return replace(
|
|
50
|
+
fence,
|
|
51
|
+
fence,
|
|
52
|
+
(code) => {
|
|
53
|
+
const codeWithVars = substitutions ? applySubstitutions(code, vars, path) : code;
|
|
54
|
+
const index = codes.push(codeWithVars) - 1;
|
|
55
|
+
|
|
56
|
+
/* Keep the same count of lines to avoid transformation of the source map */
|
|
57
|
+
const codeLines = codeWithVars.split('\n');
|
|
58
|
+
const emptyLines = codeLines.length > 1 ? '\n'.repeat(codeLines.length) : '';
|
|
59
|
+
|
|
60
|
+
return `${index}${emptyLines}`;
|
|
61
|
+
},
|
|
62
|
+
str,
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function repairCode(str: string, codes: string[]) {
|
|
67
|
+
return replace(fence, fence, (code) => codes[Number(code)], str);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function liquid<
|
|
71
|
+
B extends boolean = false,
|
|
72
|
+
C = B extends false ? string : {output: string; sourceMap: Dictionary<string>},
|
|
73
|
+
>(
|
|
74
|
+
originInput: string,
|
|
75
|
+
vars: Record<string, unknown>,
|
|
76
|
+
path?: string,
|
|
77
|
+
settings?: ArgvSettings & {withSourceMap?: B},
|
|
78
|
+
): C {
|
|
79
|
+
const {
|
|
80
|
+
cycles = true,
|
|
81
|
+
conditions = true,
|
|
82
|
+
substitutions = true,
|
|
83
|
+
conditionsInCode = false,
|
|
84
|
+
keepNotVar = false,
|
|
85
|
+
withSourceMap,
|
|
86
|
+
} = settings || {};
|
|
87
|
+
|
|
88
|
+
ArgvService.init({
|
|
89
|
+
cycles,
|
|
90
|
+
conditions,
|
|
91
|
+
substitutions,
|
|
92
|
+
conditionsInCode,
|
|
93
|
+
keepNotVar,
|
|
94
|
+
withSourceMap,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const codes: string[] = [];
|
|
98
|
+
|
|
99
|
+
let output = conditionsInCode
|
|
100
|
+
? originInput
|
|
101
|
+
: saveCode(originInput, vars, codes, path, substitutions);
|
|
102
|
+
|
|
103
|
+
let sourceMap: Record<number, number> = {};
|
|
104
|
+
|
|
105
|
+
if (withSourceMap) {
|
|
106
|
+
const lines = output.split('\n');
|
|
107
|
+
sourceMap = lines.reduce((acc: Record<number, number>, _cur, index) => {
|
|
108
|
+
acc[index + 1] = index + 1;
|
|
109
|
+
|
|
110
|
+
return acc;
|
|
111
|
+
}, {});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (cycles) {
|
|
115
|
+
output = applyCycles(output, vars, path, {sourceMap});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (conditions) {
|
|
119
|
+
output = applyConditions(output, vars, path, {sourceMap});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (substitutions) {
|
|
123
|
+
output = applySubstitutions(output, vars, path);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
output = conditionsInCode ? output : repairCode(output, codes);
|
|
127
|
+
codes.length = 0;
|
|
128
|
+
|
|
129
|
+
if (withSourceMap) {
|
|
130
|
+
return {
|
|
131
|
+
output,
|
|
132
|
+
sourceMap: prepareSourceMap(sourceMap),
|
|
133
|
+
} as unknown as C;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return output as unknown as C;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// 'export default' instead of 'export = ' because of circular dependency with './cycles.ts'.
|
|
140
|
+
// somehow it breaks import in './cycles.ts' and imports nothing
|
|
141
|
+
export default liquid;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// quote related
|
|
2
|
+
const singleQuoted = /'[^']*'/;
|
|
3
|
+
const doubleQuoted = /"[^"]*"/;
|
|
4
|
+
|
|
5
|
+
const quoted = new RegExp(`${singleQuoted.source}|${doubleQuoted.source}`);
|
|
6
|
+
export const quoteBalanced = new RegExp(`(?:${quoted.source}|[^'"])*`);
|
|
7
|
+
|
|
8
|
+
export const vars = /((not_var)?({{2}([. \w-|(),]+)}{2}))/gm;
|
|
9
|
+
|
|
10
|
+
// basic types
|
|
11
|
+
const number = /-?\d+\.?\d*|\.?\d+/;
|
|
12
|
+
const bool = /true|false/;
|
|
13
|
+
|
|
14
|
+
// property access
|
|
15
|
+
const identifier = /[\w-|]+[?]?/;
|
|
16
|
+
const subscript = new RegExp(`\\[(?:${quoted.source}|[\\w-\\.]+)\\]`);
|
|
17
|
+
const literal = new RegExp(`(?:${quoted.source}|${bool.source}|${number.source})`);
|
|
18
|
+
export const variable = new RegExp(
|
|
19
|
+
`${identifier.source}(?:\\.${identifier.source}|${subscript.source})*`,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
// range related
|
|
23
|
+
const rangeLimit = new RegExp(`(?:${variable.source}|${number.source})`);
|
|
24
|
+
const rangeCapture = new RegExp(`\\((${rangeLimit.source})\\.\\.(${rangeLimit.source})\\)`);
|
|
25
|
+
|
|
26
|
+
// full match
|
|
27
|
+
export const tagLine = new RegExp(`^\\s*(${identifier.source})\\s*([\\s\\S]*)\\s*$`);
|
|
28
|
+
const literalLine = new RegExp(`^${literal.source}$`, 'i');
|
|
29
|
+
const variableLine = new RegExp(`^${variable.source}$`);
|
|
30
|
+
const numberLine = new RegExp(`^${number.source}$`);
|
|
31
|
+
const boolLine = new RegExp(`^${bool.source}$`, 'i');
|
|
32
|
+
const quotedLine = new RegExp(`^${quoted.source}$`);
|
|
33
|
+
export const rangeLine = new RegExp(`^${rangeCapture.source}$`);
|
|
34
|
+
|
|
35
|
+
export const operators = [
|
|
36
|
+
/\s+or\s+/,
|
|
37
|
+
/\s+and\s+/,
|
|
38
|
+
/[=]=|!=|<=|>=|<|>|\s+contains\s+/,
|
|
39
|
+
/\s+\|\s+/, // myVar | filterName
|
|
40
|
+
/\s+\|/, // myVar |filterName
|
|
41
|
+
/\|\s+/, // myVar| filterName
|
|
42
|
+
/\./,
|
|
43
|
+
];
|
|
44
|
+
|
|
45
|
+
const prepareArgsForMethods = {
|
|
46
|
+
slice: (args: string[]) => args.map((arg) => Number(arg)),
|
|
47
|
+
};
|
|
48
|
+
const supportedMethods = Object.keys(prepareArgsForMethods);
|
|
49
|
+
const supportedMethodsRE = new RegExp(`^(${supportedMethods.join('\\|')})\\(([^)]*)\\)$`);
|
|
50
|
+
export const isSupportedMethod = (exp: string) => {
|
|
51
|
+
return supportedMethodsRE.test(exp);
|
|
52
|
+
};
|
|
53
|
+
export const getParsedMethod = (exp: String) => {
|
|
54
|
+
const match = exp.match(supportedMethodsRE);
|
|
55
|
+
|
|
56
|
+
if (!match) return null;
|
|
57
|
+
|
|
58
|
+
const name = match[1];
|
|
59
|
+
const args = match[2].split(/[\s,]+/);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
name,
|
|
63
|
+
args,
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export const isLiteral = (str: string) => literalLine.test(str);
|
|
68
|
+
export const isVariable = (str: string) => variableLine.test(str);
|
|
69
|
+
|
|
70
|
+
export function parseLiteral(str: string) {
|
|
71
|
+
let res = str.match(numberLine);
|
|
72
|
+
|
|
73
|
+
if (res) {
|
|
74
|
+
return Number(str);
|
|
75
|
+
}
|
|
76
|
+
res = str.match(boolLine);
|
|
77
|
+
if (res) {
|
|
78
|
+
return str.toLowerCase() === 'true';
|
|
79
|
+
}
|
|
80
|
+
res = str.match(quotedLine);
|
|
81
|
+
if (res) {
|
|
82
|
+
return str.slice(1, -1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
throw new TypeError(`cannot parse '${str}' as literal`);
|
|
86
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type ArgvSettings = {
|
|
2
|
+
conditions?: boolean;
|
|
3
|
+
conditionsInCode?: boolean;
|
|
4
|
+
cycles?: boolean;
|
|
5
|
+
substitutions?: boolean;
|
|
6
|
+
keepNotVar?: boolean;
|
|
7
|
+
withSourceMap?: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
let _argv: ArgvSettings;
|
|
11
|
+
|
|
12
|
+
export function getConfig() {
|
|
13
|
+
return _argv || {};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function init(argv: ArgvSettings) {
|
|
17
|
+
_argv = {...argv};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default {
|
|
21
|
+
init,
|
|
22
|
+
getConfig,
|
|
23
|
+
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import invert from 'lodash/invert';
|
|
2
|
+
|
|
3
|
+
const DELETED_LINE = Number.MIN_SAFE_INTEGER;
|
|
4
|
+
|
|
5
|
+
export function getLineNumber(input: string, index: number) {
|
|
6
|
+
return input.substring(0, index).split('\n').length;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function prepareSourceMap(sourceMap: object) {
|
|
10
|
+
const newToOldMap = invert(sourceMap);
|
|
11
|
+
delete newToOldMap[DELETED_LINE];
|
|
12
|
+
|
|
13
|
+
return newToOldMap;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type Options = {
|
|
17
|
+
firstLineNumber: number;
|
|
18
|
+
lastLineNumber: number;
|
|
19
|
+
sourceMap: Record<number, number>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
type MoveLinesOptions = {
|
|
23
|
+
start: number;
|
|
24
|
+
end: number;
|
|
25
|
+
offset: number;
|
|
26
|
+
withReplace?: boolean;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export function createSourceMapApi({firstLineNumber, lastLineNumber, sourceMap}: Options) {
|
|
30
|
+
const isInlineTag = firstLineNumber === lastLineNumber;
|
|
31
|
+
const newToOldIndexes = invert(sourceMap);
|
|
32
|
+
|
|
33
|
+
const getOriginIndex = (i: number) => Number(newToOldIndexes[i]);
|
|
34
|
+
|
|
35
|
+
const setSourceMapValue = (i: number, value: number) => {
|
|
36
|
+
sourceMap[getOriginIndex(i)] = value;
|
|
37
|
+
};
|
|
38
|
+
const getSourceMapValue = (i: number) => sourceMap[getOriginIndex(i)];
|
|
39
|
+
|
|
40
|
+
const moveLines = ({start, end, offset, withReplace = false}: MoveLinesOptions) => {
|
|
41
|
+
if (isInlineTag) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
for (let i = start; i <= end; i++) {
|
|
46
|
+
const newLineNumber = i + offset;
|
|
47
|
+
setSourceMapValue(i, newLineNumber);
|
|
48
|
+
|
|
49
|
+
if (withReplace) {
|
|
50
|
+
setSourceMapValue(newLineNumber, DELETED_LINE);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const removeLine = (i: number) => {
|
|
56
|
+
setSourceMapValue(i, DELETED_LINE);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const removeLines = ({start, end}: {start: number; end: number}) => {
|
|
60
|
+
for (let i = start; i <= end; i++) {
|
|
61
|
+
removeLine(i);
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
isInlineTag,
|
|
67
|
+
getSourceMapValue,
|
|
68
|
+
moveLines,
|
|
69
|
+
removeLines,
|
|
70
|
+
removeLine,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import {bold} from 'chalk';
|
|
2
|
+
|
|
3
|
+
import ArgvService from './services/argv';
|
|
4
|
+
import getObject from '../getObject';
|
|
5
|
+
import {evalExp} from './evaluation';
|
|
6
|
+
import {log} from '../log';
|
|
7
|
+
import {vars as varsRe, isVariable} from './lexical';
|
|
8
|
+
|
|
9
|
+
const substitutions = (str: string, builtVars: Record<string, unknown>, path?: string) => {
|
|
10
|
+
const {keepNotVar} = ArgvService.getConfig();
|
|
11
|
+
|
|
12
|
+
return str.replace(varsRe, (match, _groupNotVar, flag, groupVar, groupVarValue) => {
|
|
13
|
+
if (flag) {
|
|
14
|
+
return keepNotVar ? _groupNotVar : groupVar;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const trimVarPath = groupVarValue.trim();
|
|
18
|
+
|
|
19
|
+
if (trimVarPath.startsWith('.')) {
|
|
20
|
+
return groupVar;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let value;
|
|
24
|
+
if (isVariable(trimVarPath)) {
|
|
25
|
+
value = getObject(trimVarPath, builtVars);
|
|
26
|
+
} else {
|
|
27
|
+
value = evalExp(trimVarPath, builtVars);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (value === undefined) {
|
|
31
|
+
value = match;
|
|
32
|
+
|
|
33
|
+
log.warn(`Variable ${bold(trimVarPath)} not found${path ? ` in ${bold(path)}` : ''}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return value;
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export = substitutions;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export function removeIndentBlock(str: string) {
|
|
2
|
+
let i = str.length - 1;
|
|
3
|
+
let curChar = str[i];
|
|
4
|
+
|
|
5
|
+
while (curChar === ' ') {
|
|
6
|
+
curChar = str[--i];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
if (curChar === '\n') {
|
|
10
|
+
return str.substring(0, i + 1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return str;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
type Opts = {
|
|
17
|
+
content: string;
|
|
18
|
+
tagStartPos: number;
|
|
19
|
+
tagContent: string;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export function getPreparedLeftContent({content, tagStartPos, tagContent}: Opts) {
|
|
23
|
+
const preparedLeftContent = content.substring(0, tagStartPos);
|
|
24
|
+
|
|
25
|
+
if (tagContent === '') {
|
|
26
|
+
return removeIndentBlock(preparedLeftContent);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return preparedLeftContent;
|
|
30
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {green, yellow, red} from 'chalk';
|
|
2
|
+
|
|
3
|
+
export enum LogLevels {
|
|
4
|
+
INFO = 'info',
|
|
5
|
+
WARN = 'warn',
|
|
6
|
+
ERROR = 'error',
|
|
7
|
+
DISABLED = 'disabled',
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const problems: Record<LogLevels, string[]> = {
|
|
11
|
+
[LogLevels.INFO]: [],
|
|
12
|
+
[LogLevels.WARN]: [],
|
|
13
|
+
[LogLevels.ERROR]: [],
|
|
14
|
+
[LogLevels.DISABLED]: [],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
function createLogger(type: LogLevels) {
|
|
18
|
+
const formatter: Record<string, (v: string) => string> = {
|
|
19
|
+
[LogLevels.INFO]: (msg) => `${green('INFO')} ${msg}`,
|
|
20
|
+
[LogLevels.WARN]: (msg) => `${yellow('WARN')} ${msg}`,
|
|
21
|
+
[LogLevels.ERROR]: (msg) => `${red('ERR')} ${msg}`,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return function log(msg: string) {
|
|
25
|
+
const problem = formatter[type](msg);
|
|
26
|
+
|
|
27
|
+
if (!problems[type].includes(problem)) {
|
|
28
|
+
problems[type].push(problem);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export const log = {
|
|
34
|
+
[LogLevels.INFO]: createLogger(LogLevels.INFO),
|
|
35
|
+
[LogLevels.WARN]: createLogger(LogLevels.WARN),
|
|
36
|
+
[LogLevels.ERROR]: createLogger(LogLevels.ERROR),
|
|
37
|
+
LogLevels,
|
|
38
|
+
get: () => problems,
|
|
39
|
+
add: (logs: Record<LogLevels, string[]>) => {
|
|
40
|
+
problems[LogLevels.INFO] = problems[LogLevels.INFO].concat(logs[LogLevels.INFO]);
|
|
41
|
+
problems[LogLevels.WARN] = problems[LogLevels.WARN].concat(logs[LogLevels.WARN]);
|
|
42
|
+
problems[LogLevels.ERROR] = problems[LogLevels.ERROR].concat(logs[LogLevels.ERROR]);
|
|
43
|
+
},
|
|
44
|
+
clear: () => {
|
|
45
|
+
problems[LogLevels.INFO] = [];
|
|
46
|
+
problems[LogLevels.WARN] = [];
|
|
47
|
+
problems[LogLevels.ERROR] = [];
|
|
48
|
+
},
|
|
49
|
+
isEmpty: () => {
|
|
50
|
+
return !(
|
|
51
|
+
problems[LogLevels.INFO].length ||
|
|
52
|
+
problems[LogLevels.WARN].length ||
|
|
53
|
+
problems[LogLevels.ERROR].length
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type Logger = typeof log;
|
|
59
|
+
|
|
60
|
+
export default log;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type {MarkdownIt, OptionsType, EnvType} from './typings';
|
|
2
|
+
import type Token from 'markdown-it/lib/token';
|
|
3
|
+
|
|
4
|
+
import DefaultMarkdownIt from 'markdown-it';
|
|
5
|
+
import DefaultPlugins from './plugins';
|
|
6
|
+
import {log} from './log';
|
|
7
|
+
import makeHighlight from './highlight';
|
|
8
|
+
import attrs from 'markdown-it-attrs';
|
|
9
|
+
import extractTitle from './title';
|
|
10
|
+
import getHeadings from './headings';
|
|
11
|
+
import sanitizeHtml from './sanitize';
|
|
12
|
+
|
|
13
|
+
function initMarkdownit(options: OptionsType) {
|
|
14
|
+
const {allowHTML = false, linkify = false, breaks = true, highlightLangs = {}} = options;
|
|
15
|
+
|
|
16
|
+
const highlight = makeHighlight(highlightLangs);
|
|
17
|
+
const md = new DefaultMarkdownIt({html: allowHTML, linkify, highlight, breaks}) as MarkdownIt;
|
|
18
|
+
const env = {
|
|
19
|
+
// TODO: move md.meta directly to env
|
|
20
|
+
get meta() {
|
|
21
|
+
return md.meta;
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
set meta(value) {
|
|
25
|
+
md.meta = value;
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
// TODO: move md.assets directly to env
|
|
29
|
+
get assets() {
|
|
30
|
+
return md.assets;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
set assets(value) {
|
|
34
|
+
md.assets = value;
|
|
35
|
+
},
|
|
36
|
+
|
|
37
|
+
headings: [],
|
|
38
|
+
title: '',
|
|
39
|
+
} as EnvType;
|
|
40
|
+
|
|
41
|
+
initPlugins(md, options);
|
|
42
|
+
|
|
43
|
+
const parse = initParser(md, options, env);
|
|
44
|
+
const compile = initCompiler(md, options, env);
|
|
45
|
+
|
|
46
|
+
return {parse, compile, env};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function initPlugins(md: MarkdownIt, options: OptionsType) {
|
|
50
|
+
const {
|
|
51
|
+
vars = {},
|
|
52
|
+
path,
|
|
53
|
+
extractTitle,
|
|
54
|
+
conditionsInCode = false,
|
|
55
|
+
disableLiquid = false,
|
|
56
|
+
linkify = false,
|
|
57
|
+
linkifyTlds,
|
|
58
|
+
leftDelimiter = '{',
|
|
59
|
+
rightDelimiter = '}',
|
|
60
|
+
plugins = DefaultPlugins,
|
|
61
|
+
...customOptions
|
|
62
|
+
} = options;
|
|
63
|
+
|
|
64
|
+
const pluginOptions = {
|
|
65
|
+
...customOptions,
|
|
66
|
+
conditionsInCode,
|
|
67
|
+
vars,
|
|
68
|
+
path,
|
|
69
|
+
extractTitle,
|
|
70
|
+
disableLiquid,
|
|
71
|
+
log,
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// Need for ids of headers
|
|
75
|
+
md.use(attrs, {leftDelimiter, rightDelimiter});
|
|
76
|
+
|
|
77
|
+
plugins.forEach((plugin) => md.use(plugin, pluginOptions));
|
|
78
|
+
|
|
79
|
+
if (linkify && linkifyTlds) {
|
|
80
|
+
md.linkify.tlds(linkifyTlds, true);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function initParser(md: MarkdownIt, options: OptionsType, env: EnvType) {
|
|
85
|
+
return (input: string) => {
|
|
86
|
+
const {extractTitle: extractTitleOption, needTitle, needFlatListHeadings = false} = options;
|
|
87
|
+
|
|
88
|
+
let tokens = md.parse(input, env);
|
|
89
|
+
|
|
90
|
+
if (extractTitleOption) {
|
|
91
|
+
const {title, tokens: slicedTokens, titleTokens} = extractTitle(tokens);
|
|
92
|
+
|
|
93
|
+
tokens = slicedTokens;
|
|
94
|
+
|
|
95
|
+
// title tokens include other tokens that need to be transformed
|
|
96
|
+
if (titleTokens.length > 1) {
|
|
97
|
+
env.title = md.renderer.render(titleTokens, md.options, env);
|
|
98
|
+
} else {
|
|
99
|
+
env.title = title;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (needTitle) {
|
|
104
|
+
env.title = extractTitle(tokens).title;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
env.headings = getHeadings(tokens, needFlatListHeadings);
|
|
108
|
+
|
|
109
|
+
return tokens;
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function initCompiler(md: MarkdownIt, options: OptionsType, env: EnvType) {
|
|
114
|
+
const {needToSanitizeHtml = true, sanitizeOptions} = options;
|
|
115
|
+
|
|
116
|
+
return (tokens: Token[]) => {
|
|
117
|
+
const html = md.renderer.render(tokens, md.options, env);
|
|
118
|
+
|
|
119
|
+
return needToSanitizeHtml ? sanitizeHtml(html, sanitizeOptions) : html;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export = initMarkdownit;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import _ from 'lodash';
|
|
2
|
+
import {sep} from 'path';
|
|
3
|
+
|
|
4
|
+
import {getSinglePageAnchorId, resolveRelativePath} from '../../utilsFS';
|
|
5
|
+
import {transformLinkToOriginalArticle} from '../../utils';
|
|
6
|
+
import {CUSTOM_ID_REGEXP, CUSTOM_ID_EXCEPTION} from './constants';
|
|
7
|
+
import {сarriage} from '../utils';
|
|
8
|
+
import {MarkdownItPluginOpts} from '../typings';
|
|
9
|
+
|
|
10
|
+
const slugify: (str: string, opts: {}) => string = require('slugify');
|
|
11
|
+
|
|
12
|
+
/* eslint-disable max-len */
|
|
13
|
+
/* If the singlePage option is passed in the options:
|
|
14
|
+
* - replace the default anchor and custom anchors with anchors with file at the beginning
|
|
15
|
+
* - increase the level of headers,
|
|
16
|
+
* - add page anchor to the first matched header
|
|
17
|
+
* Example for file index.md:
|
|
18
|
+
* Before: # Title {#CustomAnchor} {#custom-anchor}
|
|
19
|
+
* ## Subtitle
|
|
20
|
+
* After: ## Title {data-original-article=/index} {#_index} {#_index_title} {#_index_CustomAnchor} {#_index_custom-anchor}
|
|
21
|
+
* ## Subtitle {#_index_subtitle}
|
|
22
|
+
* */
|
|
23
|
+
const collect = (input: string, options: MarkdownItPluginOpts & {singlePage: boolean}) => {
|
|
24
|
+
const {root, path, singlePage} = options;
|
|
25
|
+
|
|
26
|
+
if (!singlePage || path.includes(`_includes${sep}`)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const currentPath = resolveRelativePath(root, path);
|
|
31
|
+
const pageId = getSinglePageAnchorId({root, currentPath});
|
|
32
|
+
let needToSetPageId = true;
|
|
33
|
+
let needToSetOriginalPathAttr = true;
|
|
34
|
+
const lines = input.split(сarriage);
|
|
35
|
+
let i = 0;
|
|
36
|
+
const HEADER_LINK_REGEXP = /^(?<headerLevel>#+)\s(?<headerContent>.+)$/i;
|
|
37
|
+
|
|
38
|
+
while (i < lines.length) {
|
|
39
|
+
const line = lines[i];
|
|
40
|
+
const headerMatch = line.match(HEADER_LINK_REGEXP);
|
|
41
|
+
|
|
42
|
+
if (!headerMatch) {
|
|
43
|
+
i++;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const {headerLevel, headerContent} = headerMatch.groups as {
|
|
48
|
+
headerLevel: string;
|
|
49
|
+
headerContent: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
let newHeaderContent = headerContent;
|
|
53
|
+
const newCustomHeaders = [];
|
|
54
|
+
|
|
55
|
+
while (CUSTOM_ID_REGEXP.test(newHeaderContent)) {
|
|
56
|
+
newHeaderContent = newHeaderContent.replace(CUSTOM_ID_REGEXP, (match, customId) => {
|
|
57
|
+
if (match === CUSTOM_ID_EXCEPTION) {
|
|
58
|
+
return match;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
newCustomHeaders.push(`${pageId}_${customId}`);
|
|
62
|
+
return '';
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
newHeaderContent = newHeaderContent.trim();
|
|
66
|
+
|
|
67
|
+
const slugifiedTitle = slugify(newHeaderContent, {lower: true});
|
|
68
|
+
newCustomHeaders.push(`${pageId}_${slugifiedTitle}`);
|
|
69
|
+
if (needToSetPageId) {
|
|
70
|
+
newCustomHeaders.push(pageId);
|
|
71
|
+
needToSetPageId = false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const newCustomHeadersStr = _.chain(newCustomHeaders)
|
|
75
|
+
.uniq()
|
|
76
|
+
.map((id) => {
|
|
77
|
+
return `{${id}}`;
|
|
78
|
+
})
|
|
79
|
+
.value()
|
|
80
|
+
.join(' ');
|
|
81
|
+
|
|
82
|
+
const baseHeaderSyntax = `${headerLevel}# ${newHeaderContent}`;
|
|
83
|
+
lines[i] = `${baseHeaderSyntax} ${newCustomHeadersStr}`;
|
|
84
|
+
|
|
85
|
+
if (needToSetOriginalPathAttr) {
|
|
86
|
+
const originalArticleHref = transformLinkToOriginalArticle({root, currentPath});
|
|
87
|
+
lines[
|
|
88
|
+
i
|
|
89
|
+
] = `${baseHeaderSyntax} {data-original-article=${originalArticleHref}} ${newCustomHeadersStr}`;
|
|
90
|
+
|
|
91
|
+
needToSetOriginalPathAttr = false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
i++;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// eslint-disable-next-line consistent-return
|
|
98
|
+
return lines.join(сarriage);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export = collect;
|