@diplodoc/transform 4.29.0 → 4.30.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.
Files changed (147) hide show
  1. package/dist/css/print.css.map +1 -1
  2. package/dist/css/yfm.css +0 -1
  3. package/dist/css/yfm.css.map +2 -2
  4. package/dist/css/yfm.min.css +1 -1
  5. package/dist/css/yfm.min.css.map +2 -2
  6. package/dist/js/yfm.js.map +2 -2
  7. package/dist/js/yfm.min.js.map +2 -2
  8. package/lib/headings.js.map +1 -1
  9. package/lib/highlight.js.map +1 -1
  10. package/lib/index.js.map +1 -1
  11. package/lib/liquid/conditions.js +1 -1
  12. package/lib/liquid/conditions.js.map +1 -1
  13. package/lib/liquid/cycles.js +1 -1
  14. package/lib/liquid/cycles.js.map +1 -1
  15. package/lib/liquid/evaluation.js +1 -1
  16. package/lib/liquid/evaluation.js.map +1 -1
  17. package/lib/liquid/index.d.ts +1 -1
  18. package/lib/liquid/index.js.map +1 -1
  19. package/lib/liquid/substitutions.js +2 -2
  20. package/lib/liquid/substitutions.js.map +1 -1
  21. package/lib/md.js +30 -9
  22. package/lib/md.js.map +1 -1
  23. package/lib/plugins/anchors/collect.js +1 -1
  24. package/lib/plugins/anchors/collect.js.map +1 -1
  25. package/lib/plugins/anchors/index.js +4 -4
  26. package/lib/plugins/anchors/index.js.map +1 -1
  27. package/lib/plugins/block-anchor/index.js.map +1 -1
  28. package/lib/plugins/changelog/collect.d.ts +1 -1
  29. package/lib/plugins/changelog/collect.js +1 -1
  30. package/lib/plugins/changelog/collect.js.map +1 -1
  31. package/lib/plugins/changelog/index.js.map +1 -1
  32. package/lib/plugins/checkbox/index.js.map +1 -1
  33. package/lib/plugins/deflist.js.map +1 -1
  34. package/lib/plugins/file/index.js.map +1 -1
  35. package/lib/plugins/images/index.js +1 -1
  36. package/lib/plugins/images/index.js.map +1 -1
  37. package/lib/plugins/imsize/index.js.map +1 -1
  38. package/lib/plugins/imsize/plugin.js.map +1 -1
  39. package/lib/plugins/includes/collect.d.ts +4 -2
  40. package/lib/plugins/includes/collect.js +20 -3
  41. package/lib/plugins/includes/collect.js.map +1 -1
  42. package/lib/plugins/includes/index.js +8 -5
  43. package/lib/plugins/includes/index.js.map +1 -1
  44. package/lib/plugins/includes/types.d.ts +6 -0
  45. package/lib/plugins/includes/types.js +3 -0
  46. package/lib/plugins/includes/types.js.map +1 -0
  47. package/lib/plugins/links/collect.js.map +1 -1
  48. package/lib/plugins/links/index.js +1 -1
  49. package/lib/plugins/links/index.js.map +1 -1
  50. package/lib/plugins/meta.js.map +1 -1
  51. package/lib/plugins/monospace.js +0 -1
  52. package/lib/plugins/monospace.js.map +1 -1
  53. package/lib/plugins/notes/index.js +0 -2
  54. package/lib/plugins/notes/index.js.map +1 -1
  55. package/lib/plugins/sup.js.map +1 -1
  56. package/lib/plugins/table/index.js.map +1 -1
  57. package/lib/plugins/term/index.js.map +1 -1
  58. package/lib/plugins/term/termDefinitions.js.map +1 -1
  59. package/lib/plugins/typings.d.ts +1 -14
  60. package/lib/plugins/typings.js +15 -0
  61. package/lib/plugins/typings.js.map +1 -1
  62. package/lib/plugins/utils.d.ts +1 -1
  63. package/lib/plugins/utils.js.map +1 -1
  64. package/lib/plugins/video/const.d.ts +3 -1
  65. package/lib/plugins/video/const.js +4 -0
  66. package/lib/plugins/video/const.js.map +1 -1
  67. package/lib/plugins/video/index.js +7 -9
  68. package/lib/plugins/video/index.js.map +1 -1
  69. package/lib/plugins/video/parsers.d.ts +2 -0
  70. package/lib/plugins/video/parsers.js +19 -1
  71. package/lib/plugins/video/parsers.js.map +1 -1
  72. package/lib/plugins/video/types.d.ts +8 -0
  73. package/lib/plugins/video/utils.js +9 -6
  74. package/lib/plugins/video/utils.js.map +1 -1
  75. package/lib/preprocessors/included/index.d.ts +5 -0
  76. package/lib/preprocessors/included/index.js +71 -0
  77. package/lib/preprocessors/included/index.js.map +1 -0
  78. package/lib/preprocessors.d.ts +3 -0
  79. package/lib/preprocessors.js +8 -0
  80. package/lib/preprocessors.js.map +1 -0
  81. package/lib/sanitize.js +1 -1
  82. package/lib/sanitize.js.map +1 -1
  83. package/lib/typings.d.ts +22 -2
  84. package/lib/utilsFS.d.ts +2 -0
  85. package/lib/utilsFS.js +18 -8
  86. package/lib/utilsFS.js.map +1 -1
  87. package/lib/yfmlint/index.d.ts +2 -2
  88. package/lib/yfmlint/index.js +6 -1
  89. package/lib/yfmlint/index.js.map +1 -1
  90. package/lib/yfmlint/markdownlint-custom-rule/yfm001.js.map +1 -1
  91. package/lib/yfmlint/typings.d.ts +2 -0
  92. package/lib/yfmlint/utils.d.ts +2 -2
  93. package/lib/yfmlint/utils.js.map +1 -1
  94. package/lib/yfmlint/yfmlint.js.map +1 -1
  95. package/package.json +12 -10
  96. package/src/.eslintrc.js +1 -23
  97. package/src/js/index.ts +0 -1
  98. package/src/js/term/index.ts +1 -0
  99. package/src/transform/headings.ts +1 -0
  100. package/src/transform/highlight.ts +1 -0
  101. package/src/transform/index.ts +2 -0
  102. package/src/transform/liquid/conditions.ts +3 -1
  103. package/src/transform/liquid/cycles.ts +3 -1
  104. package/src/transform/liquid/evaluation.ts +2 -1
  105. package/src/transform/liquid/index.ts +2 -3
  106. package/src/transform/liquid/substitutions.ts +3 -2
  107. package/src/transform/md.ts +55 -14
  108. package/src/transform/plugins/anchors/collect.ts +2 -1
  109. package/src/transform/plugins/anchors/index.ts +4 -3
  110. package/src/transform/plugins/block-anchor/index.ts +1 -0
  111. package/src/transform/plugins/changelog/collect.ts +5 -2
  112. package/src/transform/plugins/changelog/index.ts +2 -1
  113. package/src/transform/plugins/checkbox/index.ts +1 -0
  114. package/src/transform/plugins/deflist.ts +1 -0
  115. package/src/transform/plugins/file/index.ts +1 -0
  116. package/src/transform/plugins/images/index.ts +2 -2
  117. package/src/transform/plugins/imsize/index.ts +1 -0
  118. package/src/transform/plugins/imsize/plugin.ts +1 -0
  119. package/src/transform/plugins/includes/collect.ts +45 -5
  120. package/src/transform/plugins/includes/index.ts +23 -7
  121. package/src/transform/plugins/includes/types.ts +7 -0
  122. package/src/transform/plugins/links/collect.ts +2 -0
  123. package/src/transform/plugins/links/index.ts +5 -3
  124. package/src/transform/plugins/meta.ts +1 -0
  125. package/src/transform/plugins/monospace.ts +1 -1
  126. package/src/transform/plugins/notes/index.ts +2 -2
  127. package/src/transform/plugins/sup.ts +1 -0
  128. package/src/transform/plugins/table/index.ts +3 -1
  129. package/src/transform/plugins/term/index.ts +1 -0
  130. package/src/transform/plugins/term/termDefinitions.ts +2 -0
  131. package/src/transform/plugins/typings.ts +1 -16
  132. package/src/transform/plugins/utils.ts +2 -1
  133. package/src/transform/plugins/video/const.ts +5 -0
  134. package/src/transform/plugins/video/index.ts +8 -10
  135. package/src/transform/plugins/video/parsers.ts +18 -0
  136. package/src/transform/plugins/video/types.ts +2 -0
  137. package/src/transform/plugins/video/utils.ts +9 -6
  138. package/src/transform/preprocessors/included/index.ts +101 -0
  139. package/src/transform/preprocessors.ts +7 -0
  140. package/src/transform/sanitize.ts +2 -2
  141. package/src/transform/typings.ts +27 -2
  142. package/src/transform/utilsFS.ts +19 -7
  143. package/src/transform/yfmlint/index.ts +18 -5
  144. package/src/transform/yfmlint/markdownlint-custom-rule/yfm001.ts +0 -1
  145. package/src/transform/yfmlint/typings.ts +5 -0
  146. package/src/transform/yfmlint/utils.ts +4 -2
  147. 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): void;
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 {root, path, destPath = '', log, copyFile, singlePage} = options;
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 null;
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 {GetFileTokensOpts, getFileTokens, getFullIncludePath, isFileExists} from '../../utilsFS';
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
- import {StateCore} from 'src/transform/typings';
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, options);
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
 
@@ -0,0 +1,7 @@
1
+ import {MarkdownIt} from '../../typings';
2
+
3
+ export interface MarkdownItIncluded extends MarkdownIt {
4
+ included?: {
5
+ [key: string]: string;
6
+ };
7
+ }
@@ -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,5 +1,6 @@
1
1
  // @ts-expect-error
2
2
  import meta from 'markdown-it-meta';
3
+
3
4
  import {MarkdownItPluginCb} from './typings';
4
5
 
5
6
  export = meta as MarkdownItPluginCb;
@@ -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,5 +1,6 @@
1
1
  // @ts-expect-error
2
2
  import sup from 'markdown-it-sup';
3
+
3
4
  import {MarkdownItPluginCb} from './typings';
4
5
 
5
6
  export = sup as MarkdownItPluginCb;
@@ -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';
@@ -3,6 +3,7 @@ import Token from 'markdown-it/lib/token';
3
3
 
4
4
  import {MarkdownItPluginCb} from '../typings';
5
5
  import {generateID} from '../utils';
6
+
6
7
  import {termDefinitions} from './termDefinitions';
7
8
  import {BASIC_TERM_REGEXP} from './constants';
8
9
 
@@ -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
- import type {Logger} from '../log';
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,8 +1,9 @@
1
1
  import {bold} from 'chalk';
2
- import {Logger} from '../log';
3
2
  import {platform} from 'process';
4
3
  import Token from 'markdown-it/lib/token';
5
4
 
5
+ import {Logger} from '../log';
6
+
6
7
  export type MatchTokenFunction = (
7
8
  tokens: Token[],
8
9
  idx: number,
@@ -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
- : '<div class="embed-responsive embed-responsive-16by9"><iframe class="embed-responsive-item ' +
73
- service +
74
- '-player" type="text/html" width="' +
75
- width +
76
- '" height="' +
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 'https://www.youtube.com/embed/' + videoID;
6
+ return `https://www.youtube.com/embed/${videoID}`;
7
7
  case 'vimeo':
8
- return 'https://player.vimeo.com/video/' + videoID;
8
+ return `https://player.vimeo.com/video/${videoID}`;
9
9
  case 'vine':
10
- return 'https://vine.co/v/' + videoID + '/embed/' + options.vine.embed;
10
+ return `https://vine.co/v/${videoID}/embed/${options.vine.embed}`;
11
11
  case 'prezi':
12
12
  return (
13
- 'https://prezi.com/embed/' +
14
- videoID +
13
+ `https://prezi.com/embed/${videoID}` +
15
14
  '/?bgcolor=ffffff&amp;lock_to_path=0&amp;autoplay=0&amp;autohide_ctrls=0&amp;' +
16
15
  'landing_data=bHVZZmNaNDBIWnNjdEVENDRhZDFNZGNIUE43MHdLNWpsdFJLb2ZHanI5N1lQVHkxSHFxazZ0UUNCRHloSXZROHh3PT0&amp;' +
17
16
  'landing_sign=1kD6c0N6aYpMUS0wxnQjxzSqZlEB8qNFdxtdjYhwSuI'
18
17
  );
19
18
  case 'osf':
20
- return 'https://mfr.osf.io/render?url=https://osf.io/' + videoID + '/?action=download';
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;
@@ -0,0 +1,7 @@
1
+ import type {MarkdownItPreprocessorCb} from './plugins/typings';
2
+
3
+ import included from './preprocessors/included';
4
+
5
+ const defaultPreprocessors = [included] as MarkdownItPreprocessorCb[];
6
+
7
+ export = defaultPreprocessors;
@@ -485,7 +485,7 @@ const defaultCssWhitelist = {
485
485
  '--method': true,
486
486
  };
487
487
 
488
- const yfmHtmlAttrs = ['note-type', 'yfm2xliff-explicit', 'term-key'];
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: number, element: cheerio.Element) => {
521
+ styleTags.each((_index, element) => {
522
522
  const styleText = dom(element).text();
523
523
 
524
524
  try {
@@ -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 {MarkdownItPluginCb} from './plugins/typings';
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
+ };