@diplodoc/transform 4.20.0 → 4.21.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.
@@ -1,15 +1,48 @@
1
1
  "use strict";
2
- /**
3
- * Parse the markdown-attrs format to retrieve a class name
4
- * Putting all the requirements in regex was more complicated than parsing a string char by char.
5
- *
6
- * @param {string} inputString - The string to parse.
7
- * @returns {string|null} - The extracted class or null if there is none
8
- */
9
2
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.parseAttrsClass = void 0;
11
- function parseAttrsClass(inputString) {
12
- const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ .=-_';
3
+ exports.parseAttrs = void 0;
4
+ const wrapToData = (key) => {
5
+ if (key.startsWith('data-')) {
6
+ return key;
7
+ }
8
+ return `data-${key}`;
9
+ };
10
+ const selectors = {
11
+ class(value) {
12
+ if (value.startsWith('.')) {
13
+ return {
14
+ key: 'class',
15
+ value: value.slice(1),
16
+ };
17
+ }
18
+ return null;
19
+ },
20
+ id(value) {
21
+ if (value.startsWith('#')) {
22
+ return {
23
+ key: 'id',
24
+ value: value.slice(1),
25
+ };
26
+ }
27
+ return null;
28
+ },
29
+ attr(value) {
30
+ const parts = value.split('=');
31
+ if (parts.length === 2) {
32
+ return {
33
+ key: wrapToData(parts[0]),
34
+ value: parts[1],
35
+ };
36
+ }
37
+ return {
38
+ key: wrapToData(value),
39
+ value: 'true',
40
+ };
41
+ },
42
+ };
43
+ const handlers = Object.values(selectors);
44
+ function parseAttrs(inputString) {
45
+ const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ .=-_#';
13
46
  if (!inputString.startsWith('{')) {
14
47
  return null;
15
48
  }
@@ -20,15 +53,24 @@ function parseAttrsClass(inputString) {
20
53
  if (!contentInside) {
21
54
  return null;
22
55
  }
23
- const parts = contentInside.split('.');
24
- if (parts.length !== 2 || !parts[1]) {
25
- return null;
26
- }
27
- //There should be a preceding whitespace
28
- if (!parts[0].endsWith(' ') && parts[0] !== '') {
29
- return null;
30
- }
31
- return parts[1];
56
+ const parts = contentInside.split(' ');
57
+ const attrs = {
58
+ class: [],
59
+ id: [],
60
+ };
61
+ parts.forEach((part) => {
62
+ const matched = handlers.find((test) => test(part));
63
+ if (!matched) {
64
+ return;
65
+ }
66
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
67
+ const { key, value } = matched(part);
68
+ if (!attrs[key]) {
69
+ attrs[key] = [];
70
+ }
71
+ attrs[key].push(value);
72
+ });
73
+ return attrs;
32
74
  }
33
75
  if (!validChars.includes(char)) {
34
76
  return null;
@@ -36,5 +78,5 @@ function parseAttrsClass(inputString) {
36
78
  }
37
79
  return null;
38
80
  }
39
- exports.parseAttrsClass = parseAttrsClass;
81
+ exports.parseAttrs = parseAttrs;
40
82
  //# sourceMappingURL=utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/transform/plugins/table/utils.ts"],"names":[],"mappings":";AAAA;;;;;;GAMG;;;AAEH,SAAgB,eAAe,CAAC,WAAmB;IAC/C,MAAM,UAAU,GAAG,2DAA2D,CAAC;IAE/E,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;QAC9B,OAAO,IAAI,CAAC;KACf;IAED,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;QACzC,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAE5B,IAAI,IAAI,KAAK,GAAG,EAAE;YACd,MAAM,aAAa,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,4BAA4B;YAElF,IAAI,CAAC,aAAa,EAAE;gBAChB,OAAO,IAAI,CAAC;aACf;YAED,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBACjC,OAAO,IAAI,CAAC;aACf;YACD,wCAAwC;YACxC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC5C,OAAO,IAAI,CAAC;aACf;YAED,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;SACnB;QAED,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;YAC5B,OAAO,IAAI,CAAC;SACf;KACJ;IAED,OAAO,IAAI,CAAC;AAChB,CAAC;AAnCD,0CAmCC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/transform/plugins/table/utils.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.20.0",
3
+ "version": "4.21.0",
4
4
  "description": "A simple transformer of text in YFM (Yandex Flavored Markdown) to HTML",
5
5
  "keywords": [
6
6
  "markdown",
@@ -16,7 +16,7 @@
16
16
 
17
17
  &_dfn {
18
18
  position: absolute;
19
- z-index: 1000;
19
+ z-index: 100;
20
20
 
21
21
  width: fit-content;
22
22
  max-width: 450px;
@@ -124,7 +124,7 @@ const index: MarkdownItPluginCb<Options> = (md, options) => {
124
124
  } else {
125
125
  id = slugify(title, {
126
126
  lower: true,
127
- remove: /[*+~.()'"!:@`ь]/g,
127
+ remove: /[*+~.()'"!:@`ь?]/g,
128
128
  });
129
129
  ghId = slugger.slug(title);
130
130
  }
@@ -1,7 +1,7 @@
1
1
  import StateBlock from 'markdown-it/lib/rules_block/state_block';
2
2
  import {MarkdownItPluginCb} from '../typings';
3
3
  import Token from 'markdown-it/lib/token';
4
- import {parseAttrsClass} from './utils';
4
+ import {parseAttrs} from './utils';
5
5
 
6
6
  const pluginName = 'yfm_table';
7
7
  const pipeChar = 0x7c; // |
@@ -96,6 +96,7 @@ class StateIterator {
96
96
  interface RowPositions {
97
97
  rows: [number, number, [Stats, Stats][]][];
98
98
  endOfTable: number | null;
99
+ pos: number;
99
100
  }
100
101
 
101
102
  function getTableRowPositions(
@@ -214,7 +215,17 @@ function getTableRowPositions(
214
215
 
215
216
  iter.next();
216
217
  }
217
- return {rows, endOfTable};
218
+
219
+ const {pos} = iter;
220
+
221
+ return {rows, endOfTable, pos};
222
+ }
223
+
224
+ function extractAttributes(state: StateBlock, pos: number): Record<string, string[]> {
225
+ const attrsStringStart = state.skipSpaces(pos);
226
+ const attrsString = state.src.slice(attrsStringStart);
227
+
228
+ return parseAttrs(attrsString) ?? {};
218
229
  }
219
230
 
220
231
  /**
@@ -232,7 +243,7 @@ function extractAndApplyClassFromToken(contentToken: Token, tdOpenToken: Token):
232
243
  if (!allAttrs) {
233
244
  return;
234
245
  }
235
- const attrsClass = parseAttrsClass(allAttrs[0].trim());
246
+ const attrsClass = parseAttrs(allAttrs[0].trim())?.class.join(' ');
236
247
  if (attrsClass) {
237
248
  tdOpenToken.attrSet('class', attrsClass);
238
249
  // remove the class from the token so that it's not propagated to tr or table level
@@ -363,13 +374,15 @@ const yfmTable: MarkdownItPluginCb = (md) => {
363
374
  return true;
364
375
  }
365
376
 
366
- const {rows, endOfTable} = getTableRowPositions(
377
+ const {rows, endOfTable, pos} = getTableRowPositions(
367
378
  state,
368
379
  startPosition,
369
380
  endPosition,
370
381
  startLine,
371
382
  );
372
383
 
384
+ const attrs = extractAttributes(state, pos);
385
+
373
386
  if (!endOfTable) {
374
387
  token = state.push('__yfm_lint', '', 0);
375
388
  token.hidden = true;
@@ -385,6 +398,11 @@ const yfmTable: MarkdownItPluginCb = (md) => {
385
398
 
386
399
  const tableStart = state.tokens.length;
387
400
  token = state.push('yfm_table_open', 'table', 1);
401
+
402
+ for (const [property, values] of Object.entries(attrs)) {
403
+ token.attrJoin(property, values.join(' '));
404
+ }
405
+
388
406
  token.map = [startLine, endOfTable];
389
407
 
390
408
  token = state.push('yfm_tbody_open', 'tbody', 1);
@@ -1,13 +1,61 @@
1
- /**
2
- * Parse the markdown-attrs format to retrieve a class name
3
- * Putting all the requirements in regex was more complicated than parsing a string char by char.
4
- *
5
- * @param {string} inputString - The string to parse.
6
- * @returns {string|null} - The extracted class or null if there is none
7
- */
1
+ type DatasetKey = `data-${string}`;
2
+ type Attrs = 'class' | 'id' | DatasetKey;
8
3
 
9
- export function parseAttrsClass(inputString: string): string | null {
10
- const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ .=-_';
4
+ type Selector = (value: string) => {
5
+ key: Attrs;
6
+ value: string;
7
+ } | null;
8
+
9
+ const wrapToData = (key: string): DatasetKey => {
10
+ if (key.startsWith('data-')) {
11
+ return key as DatasetKey;
12
+ }
13
+
14
+ return `data-${key}`;
15
+ };
16
+
17
+ const selectors = {
18
+ class(value: string) {
19
+ if (value.startsWith('.')) {
20
+ return {
21
+ key: 'class',
22
+ value: value.slice(1),
23
+ };
24
+ }
25
+
26
+ return null;
27
+ },
28
+ id(value: string) {
29
+ if (value.startsWith('#')) {
30
+ return {
31
+ key: 'id',
32
+ value: value.slice(1),
33
+ };
34
+ }
35
+
36
+ return null;
37
+ },
38
+ attr(value: string) {
39
+ const parts = value.split('=');
40
+
41
+ if (parts.length === 2) {
42
+ return {
43
+ key: wrapToData(parts[0]) as DatasetKey,
44
+ value: parts[1],
45
+ };
46
+ }
47
+
48
+ return {
49
+ key: wrapToData(value) as DatasetKey,
50
+ value: 'true',
51
+ };
52
+ },
53
+ };
54
+
55
+ const handlers = Object.values(selectors) as Selector[];
56
+
57
+ export function parseAttrs(inputString: string) {
58
+ const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ .=-_#';
11
59
 
12
60
  if (!inputString.startsWith('{')) {
13
61
  return null;
@@ -23,16 +71,31 @@ export function parseAttrsClass(inputString: string): string | null {
23
71
  return null;
24
72
  }
25
73
 
26
- const parts = contentInside.split('.');
27
- if (parts.length !== 2 || !parts[1]) {
28
- return null;
29
- }
30
- //There should be a preceding whitespace
31
- if (!parts[0].endsWith(' ') && parts[0] !== '') {
32
- return null;
33
- }
74
+ const parts = contentInside.split(' ');
75
+
76
+ const attrs: Record<string, string[]> = {
77
+ class: [],
78
+ id: [],
79
+ };
80
+
81
+ parts.forEach((part) => {
82
+ const matched = handlers.find((test) => test(part));
83
+
84
+ if (!matched) {
85
+ return;
86
+ }
87
+
88
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
89
+ const {key, value} = matched(part)!;
90
+
91
+ if (!attrs[key]) {
92
+ attrs[key] = [];
93
+ }
94
+
95
+ attrs[key].push(value);
96
+ });
34
97
 
35
- return parts[1];
98
+ return attrs;
36
99
  }
37
100
 
38
101
  if (!validChars.includes(char)) {