@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.
- package/dist/css/_yfm-only.css.map +1 -1
- package/dist/css/_yfm-only.min.css.map +1 -1
- package/dist/css/base.css.map +1 -1
- package/dist/css/base.min.css.map +1 -1
- package/dist/css/print.css.map +1 -1
- package/dist/css/yfm.css.map +1 -1
- package/dist/css/yfm.min.css.map +1 -1
- package/lib/md.js +2 -0
- package/lib/md.js.map +1 -1
- package/lib/plugins/images/index.js +38 -19
- package/lib/plugins/images/index.js.map +1 -1
- package/lib/plugins/inline-svg-marker.d.ts +3 -0
- package/lib/plugins/inline-svg-marker.js +51 -0
- package/lib/plugins/inline-svg-marker.js.map +1 -0
- package/package.json +1 -1
- package/src/transform/md.ts +2 -0
- package/src/transform/plugins/images/index.ts +47 -21
- package/src/transform/plugins/inline-svg-marker.ts +75 -0
|
@@ -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
package/src/transform/md.ts
CHANGED
|
@@ -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)
|
|
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'))
|
|
232
|
+
if (image.attrGet('yfm_patched')) {
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
231
235
|
|
|
232
236
|
const imgSrc = getSrcTokenAttr(image);
|
|
233
|
-
if (isExternalHref(imgSrc))
|
|
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)
|
|
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)
|
|
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
|
-
|
|
322
|
-
|
|
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;
|