@adobe/helix-markdown-support 6.2.1 → 6.3.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.
@@ -2,7 +2,7 @@ version: 2.1
2
2
  executors:
3
3
  node18:
4
4
  docker:
5
- - image: cimg/node:18.16
5
+ - image: cimg/node:18.17
6
6
 
7
7
  orbs:
8
8
  codecov: codecov/codecov@3.2.5
package/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [6.3.1](https://github.com/adobe/helix-markdown-support/compare/v6.3.0...v6.3.1) (2023-08-24)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * properly handle whitespace after sort ([#211](https://github.com/adobe/helix-markdown-support/issues/211)) ([03bf02a](https://github.com/adobe/helix-markdown-support/commit/03bf02a249f594e03c5d523d876e0b6522ad6ed5))
7
+
8
+ # [6.3.0](https://github.com/adobe/helix-markdown-support/compare/v6.2.1...v6.3.0) (2023-07-27)
9
+
10
+
11
+ ### Features
12
+
13
+ * sort formats ([#206](https://github.com/adobe/helix-markdown-support/issues/206)) ([b734a35](https://github.com/adobe/helix-markdown-support/commit/b734a359e764ac4630b7b2418c0e71e342ad52b6))
14
+
1
15
  ## [6.2.1](https://github.com/adobe/helix-markdown-support/compare/v6.2.0...v6.2.1) (2023-07-18)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-markdown-support",
3
- "version": "6.2.1",
3
+ "version": "6.3.1",
4
4
  "description": "Helix Markdown Support",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -58,20 +58,20 @@
58
58
  "node": ">=14"
59
59
  },
60
60
  "devDependencies": {
61
- "@adobe/eslint-config-helix": "2.0.2",
61
+ "@adobe/eslint-config-helix": "2.0.3",
62
62
  "@adobe/remark-gridtables": "1.0.4",
63
63
  "@semantic-release/changelog": "6.0.3",
64
64
  "@semantic-release/git": "10.0.1",
65
- "c8": "8.0.0",
66
- "eslint": "8.45.0",
65
+ "c8": "8.0.1",
66
+ "eslint": "8.47.0",
67
67
  "husky": "8.0.3",
68
68
  "junit-report-builder": "3.0.1",
69
- "lint-staged": "13.2.3",
69
+ "lint-staged": "13.3.0",
70
70
  "mdast-builder": "1.1.1",
71
71
  "mocha": "10.2.0",
72
72
  "mocha-multi-reporters": "1.5.1",
73
73
  "rehype-format": "4.0.1",
74
- "rehype-stringify": "9.0.3",
74
+ "rehype-stringify": "9.0.4",
75
75
  "remark-gfm": "3.0.1",
76
76
  "remark-parse": "10.0.2",
77
77
  "remark-rehype": "10.1.0",
@@ -25,22 +25,56 @@ function isSnug(type) {
25
25
  return type === 'superscript' || type === 'subscript';
26
26
  }
27
27
 
28
- /**
29
- * Sanitizes text:
30
- * - collapses consecutive formats
31
- * - collapses consecutive text blocks
32
- * - trims ends of texts before break
33
- * - trims ends of texts at the end
34
- * - moves leading and trailing whitespaces out of formats
35
- * - ensures spaces after formats
36
- * - removes trailing breaks in containers
37
- * see https://github.com/micromark/micromark/issues/118#issuecomment-1238225086
38
- * - removes empty text blocks, formats, paragraphs
39
- *
40
- * @param {object} tree
41
- * @returns {object} The modified (original) tree.
42
- */
43
- export default function sanitizeTextAndFormats(tree) {
28
+ const FLOW_SORT_ORDER = [
29
+ 'delete',
30
+ 'strong',
31
+ 'emphasis',
32
+ 'link',
33
+ 'underline',
34
+ 'subscript',
35
+ 'superscript',
36
+ ];
37
+
38
+ export function sort(tree) {
39
+ if (!tree.children) {
40
+ return;
41
+ }
42
+ for (let i = 0; i < tree.children.length; i += 1) {
43
+ let node = tree.children[i];
44
+ let key = FLOW_SORT_ORDER.indexOf(node.type);
45
+ if (key >= 0) {
46
+ // find the longest chain of formats
47
+ const chain = [];
48
+ while (key >= 0) {
49
+ chain.push({ node, key });
50
+ node = node.children?.length === 1 ? node.children[0] : null;
51
+ key = node ? FLOW_SORT_ORDER.indexOf(node?.type) : -1;
52
+ }
53
+ if (chain.length > 1) {
54
+ // remember children of last node in chain
55
+ const lastChildren = chain[chain.length - 1].node.children;
56
+
57
+ // sort chain
58
+ chain.sort((n0, n1) => (n0.key - n1.key));
59
+
60
+ // relink chain
61
+ for (let j = 0; j < chain.length - 1; j += 1) {
62
+ chain[j].node.children = [chain[j + 1].node];
63
+ }
64
+ chain[chain.length - 1].node.children = lastChildren;
65
+
66
+ // eslint-disable-next-line no-param-reassign
67
+ tree.children[i] = chain[0].node;
68
+ }
69
+ // continue on last node
70
+ sort(chain[chain.length - 1].node);
71
+ } else {
72
+ sort(node);
73
+ }
74
+ }
75
+ }
76
+
77
+ function collapse(tree) {
44
78
  visit(tree, (node, index, parent) => {
45
79
  const { children: siblings = [] } = parent || {};
46
80
  const { children = [] } = node;
@@ -56,7 +90,17 @@ export default function sanitizeTextAndFormats(tree) {
56
90
  siblings.splice(index, 1);
57
91
  return index - 1;
58
92
  }
93
+ }
94
+ return CONTINUE;
95
+ });
96
+ }
59
97
 
98
+ function whitespace(tree) {
99
+ visit(tree, (node, index, parent) => {
100
+ const { children: siblings = [] } = parent || {};
101
+ const { children = [] } = node;
102
+
103
+ if (isFormat(node.type)) {
60
104
  // check if last text block has trailing whitespace
61
105
  const last = children[children.length - 1];
62
106
  if (last?.type === 'text') {
@@ -127,7 +171,9 @@ export default function sanitizeTextAndFormats(tree) {
127
171
  }
128
172
  return CONTINUE;
129
173
  });
174
+ }
130
175
 
176
+ function cleanup(tree) {
131
177
  visit(tree, (node, index, parent) => {
132
178
  const { children: siblings = [] } = parent || {};
133
179
 
@@ -177,28 +223,56 @@ export default function sanitizeTextAndFormats(tree) {
177
223
 
178
224
  return CONTINUE;
179
225
  });
226
+ }
180
227
 
181
- // remove text, formats and paragraphs
182
- function prune(node) {
183
- const { children, type } = node;
184
- if (type === 'text') {
185
- return !node.value;
186
- }
187
- if (!children) {
188
- return false;
189
- }
190
- for (let i = 0; i < children.length; i += 1) {
191
- if (prune(children[i])) {
192
- children.splice(i, 1);
193
- i -= 1;
194
- }
195
- }
196
- if (type === 'paragraph' || isFormat(type)) {
197
- return children.length === 0;
198
- }
228
+ /**
229
+ * remove empty text, formats, paragraphs
230
+ * @param node
231
+ * @return {boolean}
232
+ */
233
+ function prune(node) {
234
+ const { children, type } = node;
235
+ if (type === 'text') {
236
+ return !node.value;
237
+ }
238
+ if (!children) {
199
239
  return false;
200
240
  }
201
- prune(tree);
241
+ for (let i = 0; i < children.length; i += 1) {
242
+ if (prune(children[i])) {
243
+ children.splice(i, 1);
244
+ i -= 1;
245
+ }
246
+ }
247
+ if (type === 'paragraph' || isFormat(type)) {
248
+ return children.length === 0;
249
+ }
250
+ return false;
251
+ }
202
252
 
253
+ /**
254
+ * Sanitizes text:
255
+ * - collapses consecutive formats
256
+ * - collapses consecutive text blocks
257
+ * - trims ends of texts before break
258
+ * - trims ends of texts at the end
259
+ * - moves leading and trailing whitespaces out of formats
260
+ * - ensures spaces after formats
261
+ * - removes trailing breaks in containers
262
+ * see https://github.com/micromark/micromark/issues/118#issuecomment-1238225086
263
+ * - removes empty text blocks, formats, paragraphs
264
+ *
265
+ * @param {object} tree
266
+ * @returns {object} The modified (original) tree.
267
+ */
268
+ export default function sanitizeTextAndFormats(tree) {
269
+ collapse(tree);
270
+ prune(tree);
271
+ sort(tree);
272
+ // collapse again, because sorting the nodes might have produce new collapsable siblings
273
+ collapse(tree);
274
+ whitespace(tree);
275
+ cleanup(tree);
276
+ prune(tree);
203
277
  return tree;
204
278
  }