@diplodoc/transform 4.29.0 → 4.30.2
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/dist/css/print.css.map +1 -1
- package/dist/css/yfm.css +0 -1
- package/dist/css/yfm.css.map +2 -2
- package/dist/css/yfm.min.css +1 -1
- package/dist/css/yfm.min.css.map +2 -2
- package/dist/js/yfm.js.map +2 -2
- package/dist/js/yfm.min.js.map +2 -2
- package/lib/headings.js.map +1 -1
- package/lib/highlight.js.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/liquid/conditions.js +1 -1
- package/lib/liquid/conditions.js.map +1 -1
- package/lib/liquid/cycles.js +1 -1
- package/lib/liquid/cycles.js.map +1 -1
- package/lib/liquid/evaluation.js +1 -1
- package/lib/liquid/evaluation.js.map +1 -1
- package/lib/liquid/index.d.ts +1 -1
- package/lib/liquid/index.js.map +1 -1
- package/lib/liquid/substitutions.js +2 -2
- package/lib/liquid/substitutions.js.map +1 -1
- package/lib/md.js +30 -9
- package/lib/md.js.map +1 -1
- package/lib/plugins/anchors/collect.js +1 -1
- package/lib/plugins/anchors/collect.js.map +1 -1
- package/lib/plugins/anchors/index.js +4 -4
- package/lib/plugins/anchors/index.js.map +1 -1
- package/lib/plugins/block-anchor/index.js.map +1 -1
- package/lib/plugins/changelog/collect.d.ts +1 -1
- package/lib/plugins/changelog/collect.js +1 -1
- package/lib/plugins/changelog/collect.js.map +1 -1
- package/lib/plugins/changelog/index.js.map +1 -1
- package/lib/plugins/checkbox/index.js.map +1 -1
- package/lib/plugins/deflist.js.map +1 -1
- package/lib/plugins/file/index.js.map +1 -1
- package/lib/plugins/images/index.js +1 -1
- package/lib/plugins/images/index.js.map +1 -1
- package/lib/plugins/imsize/index.js.map +1 -1
- package/lib/plugins/imsize/plugin.js.map +1 -1
- package/lib/plugins/includes/collect.d.ts +4 -2
- package/lib/plugins/includes/collect.js +20 -3
- package/lib/plugins/includes/collect.js.map +1 -1
- package/lib/plugins/includes/index.js +8 -5
- package/lib/plugins/includes/index.js.map +1 -1
- package/lib/plugins/includes/types.d.ts +6 -0
- package/lib/plugins/includes/types.js +3 -0
- package/lib/plugins/includes/types.js.map +1 -0
- package/lib/plugins/links/collect.js.map +1 -1
- package/lib/plugins/links/index.js +1 -1
- package/lib/plugins/links/index.js.map +1 -1
- package/lib/plugins/meta.js.map +1 -1
- package/lib/plugins/monospace.js +0 -1
- package/lib/plugins/monospace.js.map +1 -1
- package/lib/plugins/notes/index.js +0 -2
- package/lib/plugins/notes/index.js.map +1 -1
- package/lib/plugins/sup.js.map +1 -1
- package/lib/plugins/table/index.js.map +1 -1
- package/lib/plugins/term/index.js.map +1 -1
- package/lib/plugins/term/termDefinitions.js.map +1 -1
- package/lib/plugins/typings.d.ts +1 -14
- package/lib/plugins/typings.js +15 -0
- package/lib/plugins/typings.js.map +1 -1
- package/lib/plugins/utils.d.ts +1 -1
- package/lib/plugins/utils.js.map +1 -1
- package/lib/plugins/video/const.d.ts +3 -1
- package/lib/plugins/video/const.js +4 -0
- package/lib/plugins/video/const.js.map +1 -1
- package/lib/plugins/video/index.js +7 -9
- package/lib/plugins/video/index.js.map +1 -1
- package/lib/plugins/video/parsers.d.ts +2 -0
- package/lib/plugins/video/parsers.js +19 -1
- package/lib/plugins/video/parsers.js.map +1 -1
- package/lib/plugins/video/types.d.ts +8 -0
- package/lib/plugins/video/utils.js +9 -6
- package/lib/plugins/video/utils.js.map +1 -1
- package/lib/preprocessors/included/index.d.ts +5 -0
- package/lib/preprocessors/included/index.js +71 -0
- package/lib/preprocessors/included/index.js.map +1 -0
- package/lib/preprocessors.d.ts +3 -0
- package/lib/preprocessors.js +8 -0
- package/lib/preprocessors.js.map +1 -0
- package/lib/sanitize.js +1 -1
- package/lib/sanitize.js.map +1 -1
- package/lib/typings.d.ts +22 -2
- package/lib/utilsFS.d.ts +2 -0
- package/lib/utilsFS.js +18 -8
- package/lib/utilsFS.js.map +1 -1
- package/lib/yfmlint/index.d.ts +2 -2
- package/lib/yfmlint/index.js +6 -1
- package/lib/yfmlint/index.js.map +1 -1
- package/lib/yfmlint/markdownlint-custom-rule/yfm001.js.map +1 -1
- package/lib/yfmlint/typings.d.ts +2 -0
- package/lib/yfmlint/utils.d.ts +2 -2
- package/lib/yfmlint/utils.js.map +1 -1
- package/lib/yfmlint/yfmlint.js.map +1 -1
- package/package.json +13 -11
- package/src/.eslintrc.js +1 -23
- package/src/js/index.ts +0 -1
- package/src/js/term/index.ts +1 -0
- package/src/transform/headings.ts +1 -0
- package/src/transform/highlight.ts +1 -0
- package/src/transform/index.ts +2 -0
- package/src/transform/liquid/conditions.ts +3 -1
- package/src/transform/liquid/cycles.ts +3 -1
- package/src/transform/liquid/evaluation.ts +2 -1
- package/src/transform/liquid/index.ts +2 -3
- package/src/transform/liquid/substitutions.ts +3 -2
- package/src/transform/md.ts +55 -14
- package/src/transform/plugins/anchors/collect.ts +2 -1
- package/src/transform/plugins/anchors/index.ts +4 -3
- package/src/transform/plugins/block-anchor/index.ts +1 -0
- package/src/transform/plugins/changelog/collect.ts +5 -2
- package/src/transform/plugins/changelog/index.ts +2 -1
- package/src/transform/plugins/checkbox/index.ts +1 -0
- package/src/transform/plugins/deflist.ts +1 -0
- package/src/transform/plugins/file/index.ts +1 -0
- package/src/transform/plugins/images/index.ts +2 -2
- package/src/transform/plugins/imsize/index.ts +1 -0
- package/src/transform/plugins/imsize/plugin.ts +1 -0
- package/src/transform/plugins/includes/collect.ts +45 -5
- package/src/transform/plugins/includes/index.ts +23 -7
- package/src/transform/plugins/includes/types.ts +7 -0
- package/src/transform/plugins/links/collect.ts +2 -0
- package/src/transform/plugins/links/index.ts +5 -3
- package/src/transform/plugins/meta.ts +1 -0
- package/src/transform/plugins/monospace.ts +1 -1
- package/src/transform/plugins/notes/index.ts +2 -2
- package/src/transform/plugins/sup.ts +1 -0
- package/src/transform/plugins/table/index.ts +3 -1
- package/src/transform/plugins/term/index.ts +1 -0
- package/src/transform/plugins/term/termDefinitions.ts +2 -0
- package/src/transform/plugins/typings.ts +1 -16
- package/src/transform/plugins/utils.ts +2 -1
- package/src/transform/plugins/video/const.ts +5 -0
- package/src/transform/plugins/video/index.ts +8 -10
- package/src/transform/plugins/video/parsers.ts +18 -0
- package/src/transform/plugins/video/types.ts +2 -0
- package/src/transform/plugins/video/utils.ts +9 -6
- package/src/transform/preprocessors/included/index.ts +101 -0
- package/src/transform/preprocessors.ts +7 -0
- package/src/transform/sanitize.ts +2 -2
- package/src/transform/typings.ts +27 -2
- package/src/transform/utilsFS.ts +19 -7
- package/src/transform/yfmlint/index.ts +18 -5
- package/src/transform/yfmlint/markdownlint-custom-rule/yfm001.ts +0 -1
- package/src/transform/yfmlint/typings.ts +5 -0
- package/src/transform/yfmlint/utils.ts +4 -2
- package/src/transform/yfmlint/yfmlint.ts +2 -1
|
@@ -1,24 +1,39 @@
|
|
|
1
1
|
import {relative} from 'path';
|
|
2
2
|
import {bold} from 'chalk';
|
|
3
3
|
|
|
4
|
-
import {isFileExists, resolveRelativePath} from '../../utilsFS';
|
|
4
|
+
import {getRelativePath, isFileExists, resolveRelativePath} from '../../utilsFS';
|
|
5
5
|
import {MarkdownItPluginOpts} from '../typings';
|
|
6
6
|
|
|
7
7
|
const includesPaths: string[] = [];
|
|
8
8
|
|
|
9
9
|
type Opts = MarkdownItPluginOpts & {
|
|
10
10
|
destPath: string;
|
|
11
|
-
copyFile(path: string, dest: string, opts: Opts):
|
|
11
|
+
copyFile(path: string, dest: string, opts: Opts): string | null | undefined;
|
|
12
12
|
singlePage: Boolean;
|
|
13
|
+
included: Boolean;
|
|
14
|
+
includedParentPath?: string;
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
const collect = (input: string, options: Opts) => {
|
|
16
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
root,
|
|
20
|
+
path,
|
|
21
|
+
destPath = '',
|
|
22
|
+
log,
|
|
23
|
+
copyFile,
|
|
24
|
+
singlePage,
|
|
25
|
+
includedParentPath: includedParentPathNullable,
|
|
26
|
+
included,
|
|
27
|
+
} = options;
|
|
28
|
+
const includedParentPath = includedParentPathNullable || path;
|
|
29
|
+
|
|
17
30
|
const INCLUDE_REGEXP = /{%\s*include\s*(notitle)?\s*\[(.+?)]\((.+?)\)\s*%}/g;
|
|
18
31
|
|
|
19
32
|
let match,
|
|
20
33
|
result = input;
|
|
21
34
|
|
|
35
|
+
const appendix: Map<string, string> = new Map();
|
|
36
|
+
|
|
22
37
|
while ((match = INCLUDE_REGEXP.exec(result)) !== null) {
|
|
23
38
|
let [, , , relativePath] = match;
|
|
24
39
|
const [matchedInclude] = match;
|
|
@@ -55,7 +70,27 @@ const collect = (input: string, options: Opts) => {
|
|
|
55
70
|
};
|
|
56
71
|
|
|
57
72
|
try {
|
|
58
|
-
copyFile(includePath, targetDestPath, includeOptions);
|
|
73
|
+
const content = copyFile(includePath, targetDestPath, includeOptions);
|
|
74
|
+
|
|
75
|
+
// To reduce file reading we can include the file content into the generated content
|
|
76
|
+
if (included && content) {
|
|
77
|
+
const includedRelativePath = getRelativePath(includedParentPath, includePath);
|
|
78
|
+
|
|
79
|
+
// The appendix is the map that protects from multiple include files
|
|
80
|
+
if (!appendix.has(includedRelativePath)) {
|
|
81
|
+
// Recursive function to include the depth structure
|
|
82
|
+
const includeContent = collect(content, {
|
|
83
|
+
...options,
|
|
84
|
+
path: includePath,
|
|
85
|
+
includedParentPath,
|
|
86
|
+
});
|
|
87
|
+
// Add to appendix set structure
|
|
88
|
+
appendix.set(
|
|
89
|
+
includedRelativePath,
|
|
90
|
+
`{% included (${includedRelativePath}) %}\n${includeContent}\n{% endincluded %}`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
59
94
|
} catch (e) {
|
|
60
95
|
log.error(`No such file or has no access to ${bold(includePath)} in ${bold(path)}`);
|
|
61
96
|
} finally {
|
|
@@ -63,11 +98,16 @@ const collect = (input: string, options: Opts) => {
|
|
|
63
98
|
}
|
|
64
99
|
}
|
|
65
100
|
|
|
101
|
+
// Appendix should be appended to the end of the file (it supports depth structure, so the included files will have included as well)
|
|
102
|
+
if (appendix.size > 0) {
|
|
103
|
+
result += '\n' + [...appendix.values()].join('\n');
|
|
104
|
+
}
|
|
105
|
+
|
|
66
106
|
if (singlePage) {
|
|
67
107
|
return result;
|
|
68
108
|
}
|
|
69
109
|
|
|
70
|
-
return
|
|
110
|
+
return result;
|
|
71
111
|
};
|
|
72
112
|
|
|
73
113
|
export = collect;
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import {bold} from 'chalk';
|
|
2
|
+
import Token from 'markdown-it/lib/token';
|
|
2
3
|
|
|
3
|
-
import {
|
|
4
|
+
import {StateCore} from '../../typings';
|
|
5
|
+
import {
|
|
6
|
+
GetFileTokensOpts,
|
|
7
|
+
getFileTokens,
|
|
8
|
+
getFullIncludePath,
|
|
9
|
+
isFileExists,
|
|
10
|
+
resolveRelativePath,
|
|
11
|
+
} from '../../utilsFS';
|
|
4
12
|
import {findBlockTokens} from '../../utils';
|
|
5
|
-
import Token from 'markdown-it/lib/token';
|
|
6
13
|
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';
|
|
7
|
-
|
|
14
|
+
|
|
15
|
+
import {MarkdownItIncluded} from './types';
|
|
8
16
|
|
|
9
17
|
const INCLUDE_REGEXP = /^{%\s*include\s*(notitle)?\s*\[(.+?)]\((.+?)\)\s*%}$/;
|
|
10
18
|
|
|
@@ -20,7 +28,7 @@ type Options = MarkdownItPluginOpts &
|
|
|
20
28
|
noReplaceInclude: boolean;
|
|
21
29
|
};
|
|
22
30
|
|
|
23
|
-
function unfoldIncludes(state: StateCore, path: string, options: Options) {
|
|
31
|
+
function unfoldIncludes(md: MarkdownItIncluded, state: StateCore, path: string, options: Options) {
|
|
24
32
|
const {root, notFoundCb, log, noReplaceInclude = false} = options;
|
|
25
33
|
const {tokens} = state;
|
|
26
34
|
let i = 0;
|
|
@@ -41,6 +49,11 @@ function unfoldIncludes(state: StateCore, path: string, options: Options) {
|
|
|
41
49
|
const [, keyword /* description */, , includePath] = match;
|
|
42
50
|
|
|
43
51
|
const fullIncludePath = getFullIncludePath(includePath, root, path);
|
|
52
|
+
const relativeIncludePath = resolveRelativePath(path, includePath);
|
|
53
|
+
|
|
54
|
+
// Check the existed included store and extract it
|
|
55
|
+
const included = md.included?.[relativeIncludePath];
|
|
56
|
+
|
|
44
57
|
let pathname = fullIncludePath;
|
|
45
58
|
let hash = '';
|
|
46
59
|
const hashIndex = fullIncludePath.lastIndexOf('#');
|
|
@@ -55,7 +68,10 @@ function unfoldIncludes(state: StateCore, path: string, options: Options) {
|
|
|
55
68
|
continue;
|
|
56
69
|
}
|
|
57
70
|
|
|
58
|
-
const fileTokens = getFileTokens(pathname, state,
|
|
71
|
+
const fileTokens = getFileTokens(pathname, state, {
|
|
72
|
+
...options,
|
|
73
|
+
content: included, // The content forces the function to use it instead of reading from the disk
|
|
74
|
+
});
|
|
59
75
|
|
|
60
76
|
let includedTokens;
|
|
61
77
|
if (hash) {
|
|
@@ -92,7 +108,7 @@ function unfoldIncludes(state: StateCore, path: string, options: Options) {
|
|
|
92
108
|
}
|
|
93
109
|
}
|
|
94
110
|
|
|
95
|
-
const index: MarkdownItPluginCb<Options> = (md, options) => {
|
|
111
|
+
const index: MarkdownItPluginCb<Options> = (md: MarkdownItIncluded, options) => {
|
|
96
112
|
const {path: optPath, log} = options;
|
|
97
113
|
|
|
98
114
|
const plugin = (state: StateCore) => {
|
|
@@ -113,7 +129,7 @@ const index: MarkdownItPluginCb<Options> = (md, options) => {
|
|
|
113
129
|
}
|
|
114
130
|
|
|
115
131
|
env.includes.push(path);
|
|
116
|
-
unfoldIncludes(state, path, options);
|
|
132
|
+
unfoldIncludes(md, state, path, options);
|
|
117
133
|
env.includes.pop();
|
|
118
134
|
};
|
|
119
135
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import MarkdownIt from 'markdown-it';
|
|
2
2
|
import {sep} from 'path';
|
|
3
3
|
import url from 'url';
|
|
4
|
+
|
|
4
5
|
import {PAGE_LINK_REGEXP, getHrefTokenAttr, isLocalUrl} from '../../utils';
|
|
5
6
|
import {getSinglePageAnchorId, resolveRelativePath} from '../../utilsFS';
|
|
7
|
+
|
|
6
8
|
import index from './index';
|
|
7
9
|
|
|
8
10
|
const replaceLinkHref = (input: string, href: string, newHref: string) => {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import url from 'url';
|
|
2
2
|
import {bold} from 'chalk';
|
|
3
|
+
import Token from 'markdown-it/lib/token';
|
|
4
|
+
import path, {isAbsolute, parse, relative, resolve} from 'path';
|
|
5
|
+
|
|
6
|
+
import {Logger} from 'src/transform/log';
|
|
7
|
+
|
|
3
8
|
import {
|
|
4
9
|
PAGE_LINK_REGEXP,
|
|
5
10
|
defaultTransformLink,
|
|
@@ -9,11 +14,8 @@ import {
|
|
|
9
14
|
isLocalUrl,
|
|
10
15
|
} from '../../utils';
|
|
11
16
|
import {getFileTokens, isFileExists} from '../../utilsFS';
|
|
12
|
-
import Token from 'markdown-it/lib/token';
|
|
13
|
-
import {Logger} from 'src/transform/log';
|
|
14
17
|
import {CacheContext, StateCore} from '../../typings';
|
|
15
18
|
import {MarkdownItPluginCb, MarkdownItPluginOpts} from '../typings';
|
|
16
|
-
import path, {isAbsolute, parse, relative, resolve} from 'path';
|
|
17
19
|
|
|
18
20
|
function getTitleFromTokens(tokens: Token[]) {
|
|
19
21
|
let title = '';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import StateInline, {Delimiter} from 'markdown-it/lib/rules_inline/state_inline';
|
|
2
|
+
|
|
2
3
|
import {MarkdownItPluginCb} from './typings';
|
|
3
4
|
|
|
4
5
|
const monospace: MarkdownItPluginCb = (md) => {
|
|
@@ -108,7 +109,6 @@ const monospace: MarkdownItPluginCb = (md) => {
|
|
|
108
109
|
state.delimiters.push({
|
|
109
110
|
marker: marker,
|
|
110
111
|
length: 0, // disable "rule of 3" length checks meant for emphasis
|
|
111
|
-
jump: i / 2, // 1 delimiter = 2 characters
|
|
112
112
|
token: state.tokens.length - 1,
|
|
113
113
|
end: -1,
|
|
114
114
|
open: scanned.can_open,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {bold} from 'chalk';
|
|
2
2
|
import StateCore from 'markdown-it/lib/rules_core/state_core';
|
|
3
3
|
import Token from 'markdown-it/lib/token';
|
|
4
|
-
import {MarkdownItPluginCb} from '../typings';
|
|
5
4
|
|
|
5
|
+
import {MarkdownItPluginCb} from '../typings';
|
|
6
6
|
import {MatchTokenFunction, nestedCloseTokenIdxFactory as closeTokenFactory} from '../utils';
|
|
7
|
+
|
|
7
8
|
import {TITLES} from './constants';
|
|
8
9
|
|
|
9
10
|
const ALERT_RE = /^{% note (alert|info|tip|warning)\s*(?:"(.*?)")? %}$/;
|
|
@@ -84,7 +85,6 @@ const index: MarkdownItPluginCb = (md, {lang, notesAutotitle, path: optPath, log
|
|
|
84
85
|
const titleInline = new state.Token('inline', '', 0);
|
|
85
86
|
const titleClose = new state.Token('yfm_note_title_close', 'p', -1);
|
|
86
87
|
|
|
87
|
-
if (match[2]) titleOpen.attrSet('yfm2xliff-explicit', 'true');
|
|
88
88
|
titleOpen.block = true;
|
|
89
89
|
titleClose.block = true;
|
|
90
90
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import StateBlock from 'markdown-it/lib/rules_block/state_block';
|
|
2
|
-
import {MarkdownItPluginCb} from '../typings';
|
|
3
2
|
import Token from 'markdown-it/lib/token';
|
|
3
|
+
|
|
4
|
+
import {MarkdownItPluginCb} from '../typings';
|
|
5
|
+
|
|
4
6
|
import {AttrsParser} from './attrs';
|
|
5
7
|
|
|
6
8
|
const pluginName = 'yfm_table';
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import StateBlock from 'markdown-it/lib/rules_block/state_block';
|
|
2
|
+
|
|
2
3
|
import {MarkdownIt} from '../../typings';
|
|
3
4
|
import {MarkdownItPluginOpts} from '../typings';
|
|
5
|
+
|
|
4
6
|
import {BASIC_TERM_REGEXP} from './constants';
|
|
5
7
|
|
|
6
8
|
export function termDefinitions(md: MarkdownIt, options: MarkdownItPluginOpts) {
|
|
@@ -1,16 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import type {CacheContext, MarkdownIt} from '../typings';
|
|
3
|
-
|
|
4
|
-
export interface MarkdownItPluginOpts {
|
|
5
|
-
path: string;
|
|
6
|
-
log: Logger;
|
|
7
|
-
lang: 'ru' | 'en' | 'es' | 'fr' | 'cs' | 'ar' | 'he';
|
|
8
|
-
root: string;
|
|
9
|
-
rootPublicPath: string;
|
|
10
|
-
isLintRun: boolean;
|
|
11
|
-
cache?: CacheContext;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export type MarkdownItPluginCb<T extends {} = {}> = {
|
|
15
|
-
(md: MarkdownIt, opts: T & MarkdownItPluginOpts): void;
|
|
16
|
-
};
|
|
1
|
+
export * from '../typings'; // TODO: Remove in major release
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {VideoFullOptions} from './types';
|
|
2
|
+
|
|
2
3
|
import {videoUrl} from './utils';
|
|
3
4
|
|
|
4
5
|
/** Supported services */
|
|
@@ -8,6 +9,8 @@ export enum VideoService {
|
|
|
8
9
|
Vine = 'vine',
|
|
9
10
|
Prezi = 'prezi',
|
|
10
11
|
Osf = 'osf',
|
|
12
|
+
Yandex = 'yandex',
|
|
13
|
+
Vk = 'vk',
|
|
11
14
|
}
|
|
12
15
|
|
|
13
16
|
export const defaults: VideoFullOptions = {
|
|
@@ -17,4 +20,6 @@ export const defaults: VideoFullOptions = {
|
|
|
17
20
|
vine: {width: 600, height: 600, embed: 'simple'},
|
|
18
21
|
prezi: {width: 550, height: 400},
|
|
19
22
|
osf: {width: '100%', height: '100%'},
|
|
23
|
+
yandex: {width: 640, height: 390},
|
|
24
|
+
vk: {width: 640, height: 390},
|
|
20
25
|
};
|
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
// Process @[vine](vineVideoID)
|
|
4
4
|
// Process @[prezi](preziID)
|
|
5
5
|
// Process @[osf](guid)
|
|
6
|
+
// Process @[yandex](videoID)
|
|
7
|
+
// Process @[vk](videoID)
|
|
6
8
|
|
|
7
9
|
import type MarkdownIt from 'markdown-it';
|
|
8
10
|
// eslint-disable-next-line no-duplicate-imports
|
|
9
11
|
import type {PluginWithOptions} from 'markdown-it';
|
|
10
12
|
import type ParserInline from 'markdown-it/lib/parser_inline';
|
|
11
13
|
import type Renderer from 'markdown-it/lib/renderer';
|
|
12
|
-
|
|
13
14
|
import type {VideoFullOptions, VideoPluginOptions, VideoToken} from './types';
|
|
15
|
+
|
|
14
16
|
import {parseVideoUrl} from './parsers';
|
|
15
17
|
import {VideoService, defaults} from './const';
|
|
16
18
|
|
|
@@ -69,15 +71,11 @@ function tokenizeVideo(md: MarkdownIt, options: VideoFullOptions): Renderer.Rend
|
|
|
69
71
|
|
|
70
72
|
return videoID === ''
|
|
71
73
|
? ''
|
|
72
|
-
:
|
|
73
|
-
service +
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
height +
|
|
78
|
-
'" src="' +
|
|
79
|
-
options.url(service, videoID, options) +
|
|
80
|
-
'" frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>';
|
|
74
|
+
: `<div class="embed-responsive embed-responsive-16by9"><iframe` +
|
|
75
|
+
` class="embed-responsive-item ${service}-player"` +
|
|
76
|
+
` type="text/html" width="${width}" height="${height}"` +
|
|
77
|
+
` src="${options.url(service, videoID, options)}"` +
|
|
78
|
+
` frameborder="0" webkitallowfullscreen mozallowfullscreen allowfullscreen></iframe></div>`;
|
|
81
79
|
};
|
|
82
80
|
}
|
|
83
81
|
|
|
@@ -33,6 +33,18 @@ export function mfrParser(url: string) {
|
|
|
33
33
|
return match ? match[1] : url;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
+
const yandexRegex = /^https:\/\/runtime.video.cloud.yandex.net\/player\/video\/([a-zA-Z0-9]+)/;
|
|
37
|
+
export function yandexParser(url: string) {
|
|
38
|
+
const match = url.match(yandexRegex);
|
|
39
|
+
return match ? match[1] : url;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const vkRegex = /^https:\/\/vk.com\/video_ext\.php?(oid=[-\d]+&id=[-\d]+)/;
|
|
43
|
+
export function vkParser(url: string) {
|
|
44
|
+
const match = url.match(vkRegex);
|
|
45
|
+
return match ? match[1] : url;
|
|
46
|
+
}
|
|
47
|
+
|
|
36
48
|
export function parseVideoUrl(service: string, url: string): string | false {
|
|
37
49
|
let videoID = '';
|
|
38
50
|
|
|
@@ -52,6 +64,12 @@ export function parseVideoUrl(service: string, url: string): string | false {
|
|
|
52
64
|
case VideoService.Osf:
|
|
53
65
|
videoID = mfrParser(url);
|
|
54
66
|
break;
|
|
67
|
+
case VideoService.Yandex:
|
|
68
|
+
videoID = yandexParser(url);
|
|
69
|
+
break;
|
|
70
|
+
case VideoService.Vk:
|
|
71
|
+
videoID = vkParser(url);
|
|
72
|
+
break;
|
|
55
73
|
default:
|
|
56
74
|
return false;
|
|
57
75
|
}
|
|
@@ -12,6 +12,8 @@ export type VideoServicesOptions = {
|
|
|
12
12
|
[VideoService.Vine]: {width: number; height: number; embed: 'simple' | string};
|
|
13
13
|
[VideoService.Prezi]: {width: number; height: number};
|
|
14
14
|
[VideoService.Osf]: {width: string; height: string};
|
|
15
|
+
[VideoService.Yandex]: {width: number; height: number};
|
|
16
|
+
[VideoService.Vk]: {width: number; height: number};
|
|
15
17
|
};
|
|
16
18
|
|
|
17
19
|
export type VideoFullOptions = VideoServicesOptions & {
|
|
@@ -3,21 +3,24 @@ import type {VideoUrlFn} from './types';
|
|
|
3
3
|
export const videoUrl: VideoUrlFn = (service, videoID, options) => {
|
|
4
4
|
switch (service) {
|
|
5
5
|
case 'youtube':
|
|
6
|
-
return
|
|
6
|
+
return `https://www.youtube.com/embed/${videoID}`;
|
|
7
7
|
case 'vimeo':
|
|
8
|
-
return
|
|
8
|
+
return `https://player.vimeo.com/video/${videoID}`;
|
|
9
9
|
case 'vine':
|
|
10
|
-
return
|
|
10
|
+
return `https://vine.co/v/${videoID}/embed/${options.vine.embed}`;
|
|
11
11
|
case 'prezi':
|
|
12
12
|
return (
|
|
13
|
-
|
|
14
|
-
videoID +
|
|
13
|
+
`https://prezi.com/embed/${videoID}` +
|
|
15
14
|
'/?bgcolor=ffffff&lock_to_path=0&autoplay=0&autohide_ctrls=0&' +
|
|
16
15
|
'landing_data=bHVZZmNaNDBIWnNjdEVENDRhZDFNZGNIUE43MHdLNWpsdFJLb2ZHanI5N1lQVHkxSHFxazZ0UUNCRHloSXZROHh3PT0&' +
|
|
17
16
|
'landing_sign=1kD6c0N6aYpMUS0wxnQjxzSqZlEB8qNFdxtdjYhwSuI'
|
|
18
17
|
);
|
|
19
18
|
case 'osf':
|
|
20
|
-
return
|
|
19
|
+
return `https://mfr.osf.io/render?url=https://osf.io/${videoID}/?action=download`;
|
|
20
|
+
case 'yandex':
|
|
21
|
+
return `https://runtime.video.cloud.yandex.net/player/${videoID}`;
|
|
22
|
+
case 'vk':
|
|
23
|
+
return `https://vk.com/video_ext.php?${videoID}`;
|
|
21
24
|
default:
|
|
22
25
|
return service;
|
|
23
26
|
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import {getFullIncludePath} from '../../utilsFS';
|
|
2
|
+
import {MarkdownItPreprocessorCb} from '../../typings';
|
|
3
|
+
import {MarkdownItIncluded} from '../../plugins/includes/types';
|
|
4
|
+
|
|
5
|
+
const INCLUDE_REGEXP = /^\s*{%\s*included\s*\((.+?)\)\s*%}\s*$/;
|
|
6
|
+
const INCLUDE_END_REGEXP = /^\s*{% endincluded %}\s*$/;
|
|
7
|
+
|
|
8
|
+
const preprocessLine = (
|
|
9
|
+
lines: string[],
|
|
10
|
+
start: number,
|
|
11
|
+
{
|
|
12
|
+
root,
|
|
13
|
+
path,
|
|
14
|
+
}: {
|
|
15
|
+
root?: string;
|
|
16
|
+
path?: string;
|
|
17
|
+
},
|
|
18
|
+
md?: MarkdownItIncluded,
|
|
19
|
+
) => {
|
|
20
|
+
const hasIncludedCache = md && root && path;
|
|
21
|
+
const str = lines[start];
|
|
22
|
+
const match = str?.match(INCLUDE_REGEXP);
|
|
23
|
+
|
|
24
|
+
// Protect from unmatched results
|
|
25
|
+
if (!match) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const includePathRelative = match[1];
|
|
30
|
+
|
|
31
|
+
// Protect from empty path
|
|
32
|
+
if (!includePathRelative) {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Read all content from top to bottom(!) char of the included block
|
|
37
|
+
const data = [];
|
|
38
|
+
let line = start;
|
|
39
|
+
while (line < lines.length) {
|
|
40
|
+
line++;
|
|
41
|
+
const str = lines[line];
|
|
42
|
+
if (str === null) {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
if (str?.match(INCLUDE_END_REGEXP)) {
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
data.push(str);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// No included cache for lint mode
|
|
52
|
+
if (hasIncludedCache) {
|
|
53
|
+
if (!md.included) {
|
|
54
|
+
md.included = {};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Normalize the path to absolute
|
|
58
|
+
const includePath = getFullIncludePath(includePathRelative, root, path);
|
|
59
|
+
|
|
60
|
+
// Store the included content
|
|
61
|
+
md.included[includePath] = data.join('\n');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Remove the content of the included file
|
|
65
|
+
lines.splice(start, data.length + 2);
|
|
66
|
+
|
|
67
|
+
return true;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const index: MarkdownItPreprocessorCb<{
|
|
71
|
+
included?: boolean;
|
|
72
|
+
}> = (input, options, md?: MarkdownItIncluded) => {
|
|
73
|
+
const {included, path, root} = options;
|
|
74
|
+
|
|
75
|
+
// To reduce file reading we can include the file content into the generated content
|
|
76
|
+
if (included) {
|
|
77
|
+
const lines = input.split('\n') || [];
|
|
78
|
+
|
|
79
|
+
// The finction reads the files from bottom to top(!). It stops the loop if it does not have anything to swap.
|
|
80
|
+
// If the function finds something to process then it restarts the loop because the position of the last element has been moved.
|
|
81
|
+
// eslint-disable-next-line no-unmodified-loop-condition
|
|
82
|
+
while (input?.length) {
|
|
83
|
+
let hasChars = false;
|
|
84
|
+
for (let line = lines.length - 1; line >= 0; line--) {
|
|
85
|
+
hasChars = preprocessLine(lines, line, {path, root}, md);
|
|
86
|
+
if (hasChars) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (!hasChars) {
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
input = lines.join('\n');
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return input;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
export = index;
|
|
@@ -485,7 +485,7 @@ const defaultCssWhitelist = {
|
|
|
485
485
|
'--method': true,
|
|
486
486
|
};
|
|
487
487
|
|
|
488
|
-
const yfmHtmlAttrs = ['note-type', '
|
|
488
|
+
const yfmHtmlAttrs = ['note-type', 'term-key'];
|
|
489
489
|
|
|
490
490
|
const allowedTags = Array.from(
|
|
491
491
|
new Set([...htmlTags, ...svgTags, ...sanitizeHtml.defaults.allowedTags]),
|
|
@@ -518,7 +518,7 @@ export const defaultOptions: SanitizeOptions = {
|
|
|
518
518
|
function sanitizeStyleTags(dom: cheerio.CheerioAPI, cssWhiteList: CssWhiteList) {
|
|
519
519
|
const styleTags = dom('style');
|
|
520
520
|
|
|
521
|
-
styleTags.each((_index
|
|
521
|
+
styleTags.each((_index, element) => {
|
|
522
522
|
const styleText = dom(element).text();
|
|
523
523
|
|
|
524
524
|
try {
|
package/src/transform/typings.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {LanguageFn} from 'highlight.js';
|
|
2
2
|
import DefaultMarkdownIt from 'markdown-it';
|
|
3
3
|
import DefaultStateCore from 'markdown-it/lib/rules_core/state_core';
|
|
4
|
+
|
|
4
5
|
import {SanitizeOptions} from './sanitize';
|
|
5
|
-
import {
|
|
6
|
-
import {LogLevels} from './log';
|
|
6
|
+
import {LogLevels, Logger} from './log';
|
|
7
7
|
import {ChangelogItem} from './plugins/changelog/types';
|
|
8
8
|
|
|
9
9
|
export interface MarkdownIt extends DefaultMarkdownIt {
|
|
@@ -48,7 +48,9 @@ export interface OptionsType {
|
|
|
48
48
|
needFlatListHeadings?: boolean;
|
|
49
49
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
50
|
plugins?: MarkdownItPluginCb<any>[];
|
|
51
|
+
preprocessors?: MarkdownItPreprocessorCb[]; // Preprocessors should modify the input before passing it to MD
|
|
51
52
|
highlightLangs?: HighlightLangMap;
|
|
53
|
+
disableRules?: string[];
|
|
52
54
|
extractChangelogs?: boolean;
|
|
53
55
|
root?: string;
|
|
54
56
|
rootPublicPath?: string;
|
|
@@ -73,3 +75,26 @@ export type EnvType<Extras extends {} = {}> = {
|
|
|
73
75
|
meta?: object;
|
|
74
76
|
changelogs?: ChangelogItem[];
|
|
75
77
|
} & Extras;
|
|
78
|
+
|
|
79
|
+
export interface MarkdownItPluginOpts {
|
|
80
|
+
path: string;
|
|
81
|
+
log: Logger;
|
|
82
|
+
lang: 'ru' | 'en' | 'es' | 'fr' | 'cs' | 'ar' | 'he';
|
|
83
|
+
root: string;
|
|
84
|
+
rootPublicPath: string;
|
|
85
|
+
isLintRun: boolean;
|
|
86
|
+
cache?: CacheContext;
|
|
87
|
+
conditionsInCode?: boolean;
|
|
88
|
+
vars?: Record<string, string>;
|
|
89
|
+
extractTitle?: boolean;
|
|
90
|
+
disableLiquid?: boolean;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export type MarkdownItPluginCb<T extends {} = {}> = {
|
|
94
|
+
// TODO: use "T extends unknown = {}"
|
|
95
|
+
(md: MarkdownIt, opts: T & MarkdownItPluginOpts): void;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
export type MarkdownItPreprocessorCb<T extends unknown = {}> = {
|
|
99
|
+
(input: string, opts: T & Partial<MarkdownItPluginOpts>, md?: MarkdownIt): string;
|
|
100
|
+
};
|