@diplodoc/transform 4.77.14 → 4.77.15

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.
@@ -0,0 +1,3 @@
1
+ import type { MarkdownItPluginCb } from './typings';
2
+ declare const inlineSvgMarker: MarkdownItPluginCb;
3
+ export = inlineSvgMarker;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ const MARKER = /^<!--[ \t]*diplodoc:svg[ \t][^\r\n]*?-->(?=<svg\b)/;
3
+ const TOKEN_NAME = 'inline_svg_marker';
4
+ const inlineSvgMarker = (md) => {
5
+ md.block.ruler.before('html_block', TOKEN_NAME, (state, startLine) => {
6
+ var _a;
7
+ const start = state.bMarks[startLine] + state.tShift[startLine];
8
+ const content = state.src.slice(start, state.eMarks[startLine]);
9
+ const marker = (_a = MARKER.exec(content)) === null || _a === void 0 ? void 0 : _a[0];
10
+ if (marker) {
11
+ const src = state.src.slice(0, start) +
12
+ ' '.repeat(marker.length) +
13
+ state.src.slice(start + marker.length);
14
+ state.src = src;
15
+ }
16
+ return false;
17
+ }, { alt: ['paragraph', 'reference', 'blockquote'] });
18
+ md.inline.ruler.before('html_inline', TOKEN_NAME, (state) => {
19
+ var _a;
20
+ const content = state.src.slice(state.pos);
21
+ const marker = (_a = MARKER.exec(content)) === null || _a === void 0 ? void 0 : _a[0];
22
+ if (!marker) {
23
+ return false;
24
+ }
25
+ const token = state.push(TOKEN_NAME, '', 0);
26
+ token.meta = {
27
+ start: state.pos,
28
+ end: state.pos + marker.length,
29
+ };
30
+ state.pos += marker.length;
31
+ return true;
32
+ });
33
+ md.core.ruler.after('inline', `${TOKEN_NAME}_cleanup`, (state) => {
34
+ state.tokens.forEach((token) => {
35
+ if (token.type !== 'inline' || !token.children) {
36
+ return;
37
+ }
38
+ for (let index = token.children.length - 1; index >= 0; index--) {
39
+ const marker = token.children[index];
40
+ if (marker.type !== TOKEN_NAME) {
41
+ continue;
42
+ }
43
+ const { start, end } = marker.meta;
44
+ token.content = token.content.slice(0, start) + token.content.slice(end);
45
+ token.children.splice(index, 1);
46
+ }
47
+ });
48
+ });
49
+ };
50
+ module.exports = inlineSvgMarker;
51
+ //# sourceMappingURL=inline-svg-marker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inline-svg-marker.js","sourceRoot":"","sources":["../../src/transform/plugins/inline-svg-marker.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diplodoc/transform",
3
- "version": "4.77.14",
3
+ "version": "4.77.15",
4
4
  "description": "A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML",
5
5
  "keywords": [
6
6
  "markdown",
@@ -13,6 +13,7 @@ import getHeadings from './headings';
13
13
  import sanitizeHtml, {defaultOptions, sanitizeStyles} from './sanitize';
14
14
  import {olAttrConversion} from './plugins/ol-attr-conversion';
15
15
  import linkifyStrikethrough from './plugins/linkify-strikethrough';
16
+ import inlineSvgMarker from './plugins/inline-svg-marker';
16
17
  import {DEFAULT_LANG} from './constants';
17
18
  import {createIDGeneratorByStrategy} from './plugins/utils';
18
19
 
@@ -117,6 +118,7 @@ function initPlugins(md: MarkdownIt, options: OptionsType, pluginOptions: Markdo
117
118
  }
118
119
 
119
120
  md.use(olAttrConversion);
121
+ md.use(inlineSvgMarker);
120
122
 
121
123
  md.use(linkifyStrikethrough);
122
124
  plugins.forEach((plugin) => md.use(plugin, pluginOptions));
@@ -5,7 +5,7 @@ import type {IDGenerator} from '../utils';
5
5
 
6
6
  import {join, sep} from 'path';
7
7
  import {bold} from 'chalk';
8
- import {optimize} from 'svgo';
8
+ import {type PluginConfig, optimize} from 'svgo';
9
9
  import {readFileSync} from 'fs';
10
10
 
11
11
  import {isFileExists, resolveRelativePath} from '../../utilsFS';
@@ -147,7 +147,9 @@ function collectDataAttrs(
147
147
  opts: ImageOpts,
148
148
  ): Record<string, string> {
149
149
  const result: Record<string, string> = {};
150
- if (!image.attrs) return result;
150
+ if (!image.attrs) {
151
+ return result;
152
+ }
151
153
 
152
154
  for (const [key, value] of image.attrs) {
153
155
  if (key === 'gallery' && isGalleryValid(value)) {
@@ -227,10 +229,14 @@ const index: MarkdownItPluginCb<Opts> = (md, opts) => {
227
229
  childrenTokens: Token[],
228
230
  state: StateCore,
229
231
  ): void {
230
- if (image.attrGet('yfm_patched')) return;
232
+ if (image.attrGet('yfm_patched')) {
233
+ return;
234
+ }
231
235
 
232
236
  const imgSrc = getSrcTokenAttr(image);
233
- if (isExternalHref(imgSrc)) return;
237
+ if (isExternalHref(imgSrc)) {
238
+ return;
239
+ }
234
240
 
235
241
  const from = state.env.path || opts.path;
236
242
  const dataAttrs = collectDataAttrs(image, state, from, calcPath, replaceImage, opts);
@@ -274,10 +280,14 @@ const index: MarkdownItPluginCb<Opts> = (md, opts) => {
274
280
 
275
281
  const plugin = (state: StateCore) => {
276
282
  filterTokens(state.tokens, 'inline', (inline, {commented}) => {
277
- if (commented || !inline.children) return;
283
+ if (commented || !inline.children) {
284
+ return;
285
+ }
278
286
  const childrenTokens = inline.children;
279
287
  filterTokens(childrenTokens, 'image', (image, {commented, index}) => {
280
- if (!commented) processImageToken(image, index, childrenTokens, state);
288
+ if (!commented) {
289
+ processImageToken(image, index, childrenTokens, state);
290
+ }
281
291
  });
282
292
  });
283
293
  };
@@ -307,6 +317,21 @@ function applyDataAttrs(svgRoot: string, dataAttrs: Record<string, string>): str
307
317
  return result;
308
318
  }
309
319
 
320
+ const removeProcessingInstructions: PluginConfig = {
321
+ name: 'removeProcessingInstructions',
322
+ fn: () => {
323
+ return {
324
+ instruction: {
325
+ enter: (node, parent) => {
326
+ const start = parent.children.indexOf(node);
327
+
328
+ parent.children.splice(start, 1);
329
+ },
330
+ },
331
+ };
332
+ },
333
+ };
334
+
310
335
  function replaceSvgContent(
311
336
  content: string | null,
312
337
  options: ImageOptions,
@@ -318,8 +343,22 @@ function replaceSvgContent(
318
343
  // monoline
319
344
  content = content.replace(/>\r?\n</g, '><').replace(/\r?\n/g, ' ');
320
345
 
321
- // remove XML processing instructions (<?xml?>, <?plantuml?>, etc.) — invalid in HTML
322
- content = content.replace(/<\?[^?]*\?>/g, '');
346
+ const optimized = optimize(content, {
347
+ plugins: [
348
+ 'removeDoctype',
349
+ {name: 'removeComments', params: {preservePatterns: []}},
350
+ removeProcessingInstructions,
351
+ {
352
+ name: 'prefixIds',
353
+ params: {
354
+ prefix: generateID('svg'),
355
+ prefixClassNames: false,
356
+ },
357
+ },
358
+ ],
359
+ });
360
+
361
+ content = optimized.data;
323
362
 
324
363
  // width, height
325
364
  let svgRoot = content.replace(/.*?<svg([^>]*)>.*/g, '$1');
@@ -356,19 +395,6 @@ function replaceSvgContent(
356
395
  content = content.replace(/(<svg[^>]*>)/, `$1<title>${options.title}</title>`);
357
396
  }
358
397
 
359
- // randomize ids
360
- content = optimize(content, {
361
- plugins: [
362
- {
363
- name: 'prefixIds',
364
- params: {
365
- prefix: generateID('svg'),
366
- prefixClassNames: false,
367
- },
368
- },
369
- ],
370
- }).data;
371
-
372
398
  return escapeMarkdownCharsInSvgTextNodes(content);
373
399
  }
374
400
 
@@ -0,0 +1,75 @@
1
+ import type StateBlock from 'markdown-it/lib/rules_block/state_block';
2
+ import type StateCore from 'markdown-it/lib/rules_core/state_core';
3
+ import type StateInline from 'markdown-it/lib/rules_inline/state_inline';
4
+ import type {MarkdownItPluginCb} from './typings';
5
+
6
+ const MARKER = /^<!--[ \t]*diplodoc:svg[ \t][^\r\n]*?-->(?=<svg\b)/;
7
+ const TOKEN_NAME = 'inline_svg_marker';
8
+
9
+ type MarkerRange = {start: number; end: number};
10
+
11
+ const inlineSvgMarker: MarkdownItPluginCb = (md) => {
12
+ md.block.ruler.before(
13
+ 'html_block',
14
+ TOKEN_NAME,
15
+ (state: StateBlock, startLine: number) => {
16
+ const start = state.bMarks[startLine] + state.tShift[startLine];
17
+ const content = state.src.slice(start, state.eMarks[startLine]);
18
+ const marker = MARKER.exec(content)?.[0];
19
+
20
+ if (marker) {
21
+ const src =
22
+ state.src.slice(0, start) +
23
+ ' '.repeat(marker.length) +
24
+ state.src.slice(start + marker.length);
25
+
26
+ state.src = src;
27
+ }
28
+
29
+ return false;
30
+ },
31
+ {alt: ['paragraph', 'reference', 'blockquote']},
32
+ );
33
+
34
+ md.inline.ruler.before('html_inline', TOKEN_NAME, (state: StateInline) => {
35
+ const content = state.src.slice(state.pos);
36
+ const marker = MARKER.exec(content)?.[0];
37
+
38
+ if (!marker) {
39
+ return false;
40
+ }
41
+
42
+ const token = state.push(TOKEN_NAME, '', 0);
43
+
44
+ token.meta = {
45
+ start: state.pos,
46
+ end: state.pos + marker.length,
47
+ } satisfies MarkerRange;
48
+ state.pos += marker.length;
49
+
50
+ return true;
51
+ });
52
+
53
+ md.core.ruler.after('inline', `${TOKEN_NAME}_cleanup`, (state: StateCore) => {
54
+ state.tokens.forEach((token) => {
55
+ if (token.type !== 'inline' || !token.children) {
56
+ return;
57
+ }
58
+
59
+ for (let index = token.children.length - 1; index >= 0; index--) {
60
+ const marker = token.children[index];
61
+
62
+ if (marker.type !== TOKEN_NAME) {
63
+ continue;
64
+ }
65
+
66
+ const {start, end} = marker.meta as MarkerRange;
67
+
68
+ token.content = token.content.slice(0, start) + token.content.slice(end);
69
+ token.children.splice(index, 1);
70
+ }
71
+ });
72
+ });
73
+ };
74
+
75
+ export = inlineSvgMarker;