@adobe/helix-markdown-support 5.0.10 → 6.0.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,119 +0,0 @@
1
- /*
2
- * Copyright 2022 Adobe. All rights reserved.
3
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License. You may obtain a copy
5
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- *
7
- * Unless required by applicable law or agreed to in writing, software distributed under
8
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- * OF ANY KIND, either express or implied. See the License for the specific language
10
- * governing permissions and limitations under the License.
11
- */
12
- import { all } from 'mdast-util-to-hast';
13
- import { CONTINUE, SKIP, visit } from 'unist-util-visit';
14
- import {
15
- TYPE_BODY, TYPE_CELL, TYPE_FOOTER, TYPE_HEADER, TYPE_ROW,
16
- } from './types.js';
17
-
18
- /**
19
- * @typedef GridTableHandlerOptions
20
- * @property {boolean} noHeader if true, <thead> and <tbody> elements are suppressed.
21
- */
22
-
23
- /**
24
- * Handles a row (i.e. the `gtRow` node)
25
- * @return {HastNode} the 'tr' node
26
- */
27
- function handleRow(h, node, cellElementName) {
28
- const cells = [];
29
- for (const child of node.children) {
30
- if (child.type === TYPE_CELL) {
31
- const props = {};
32
- for (const p of ['colSpan', 'rowSpan', 'align', 'valign']) {
33
- if (p in child) {
34
- props[p] = child[p];
35
- }
36
- }
37
- // if cell contains only 1 single paragraph, unwrap it
38
- if (child.children?.length === 1 && child.children[0].type === 'paragraph') {
39
- child.children = child.children[0].children;
40
- }
41
- const cell = h(child, cellElementName, props, all(h, child));
42
- cells.push(cell);
43
-
44
- // clean text elements
45
- visit(cell, (n) => {
46
- if (n.tagName === 'code') {
47
- return SKIP;
48
- }
49
- if (n.type === 'text') {
50
- // eslint-disable-next-line no-param-reassign
51
- n.value = n.value.replace(/\r?\n/mg, ' ');
52
- }
53
- return CONTINUE;
54
- });
55
- }
56
- }
57
-
58
- return h(node, 'tr', cells);
59
- }
60
-
61
- /**
62
- * Handles a group (array) of rows. eg the children of a `gtBody`.
63
- * @return {HastNode[]} the array of rows
64
- */
65
- function createRows(h, node, cellElementName) {
66
- const rows = [];
67
- for (const child of node.children) {
68
- if (child.type === TYPE_ROW) {
69
- rows.push(handleRow(h, child, cellElementName));
70
- }
71
- }
72
- return rows;
73
- }
74
-
75
- /**
76
- * Transforms the gridTable to a hast table
77
- *
78
- * @param {GridTableHandlerOptions} opts
79
- * @return {function} A mdast-to-hast handler.
80
- */
81
- export default function gridTableHandler(opts = {}) {
82
- const { noHeader } = opts;
83
-
84
- return function handleTable(h, node) {
85
- let headerRows = [];
86
- let bodyRows = [];
87
- let footerRows = [];
88
-
89
- for (const child of node.children) {
90
- if (child.type === TYPE_HEADER) {
91
- headerRows = createRows(h, child, 'th');
92
- } else if (child.type === TYPE_BODY) {
93
- bodyRows = createRows(h, child, 'td');
94
- } else if (child.type === TYPE_FOOTER) {
95
- footerRows = createRows(h, child, 'td');
96
- } else if (child.type === TYPE_ROW) {
97
- bodyRows.push(handleRow(h, child, 'td'));
98
- }
99
- }
100
-
101
- let inner;
102
- if (noHeader && footerRows.length === 0) {
103
- inner = [...headerRows, ...bodyRows];
104
- } else {
105
- inner = [];
106
- if (headerRows.length) {
107
- inner.push(h(null, 'thead', headerRows));
108
- }
109
- if (bodyRows.length) {
110
- inner.push(h(null, 'tbody', bodyRows));
111
- }
112
- if (footerRows.length) {
113
- inner.push(h(null, 'tfoot', footerRows));
114
- }
115
- }
116
-
117
- return h(node, 'table', inner);
118
- };
119
- }
@@ -1,36 +0,0 @@
1
- /*
2
- * Copyright 2022 Adobe. All rights reserved.
3
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License. You may obtain a copy
5
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- *
7
- * Unless required by applicable law or agreed to in writing, software distributed under
8
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- * OF ANY KIND, either express or implied. See the License for the specific language
10
- * governing permissions and limitations under the License.
11
- */
12
- import fromMarkdown from './from-markdown.js';
13
- import toMarkdown from './to-markdown.js';
14
- import syntax from './syntax.js';
15
-
16
- export default function remarkPlugin(options = {}) {
17
- const data = this.data();
18
-
19
- function add(field, value) {
20
- /* c8 ignore next 2 */
21
- if (data[field]) {
22
- data[field].push(value);
23
- } else {
24
- data[field] = [value];
25
- }
26
- }
27
-
28
- const opts = {
29
- processor: this,
30
- ...options,
31
- };
32
-
33
- add('micromarkExtensions', syntax(options));
34
- add('fromMarkdownExtensions', fromMarkdown(opts));
35
- add('toMarkdownExtensions', toMarkdown(options));
36
- }
@@ -1,352 +0,0 @@
1
- /*
2
- * Copyright 2022 Adobe. All rights reserved.
3
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- * you may not use this file except in compliance with the License. You may obtain a copy
5
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- *
7
- * Unless required by applicable law or agreed to in writing, software distributed under
8
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- * OF ANY KIND, either express or implied. See the License for the specific language
10
- * governing permissions and limitations under the License.
11
- */
12
- /* eslint-disable no-use-before-define,no-underscore-dangle,no-param-reassign */
13
- import { codes } from 'micromark-util-symbol/codes.js';
14
- import { types } from 'micromark-util-symbol/types.js';
15
- import {
16
- markdownLineEnding,
17
- markdownSpace,
18
- } from 'micromark-util-character';
19
- import {
20
- TYPE_BODY, TYPE_CELL, TYPE_HEADER, TYPE_FOOTER, TYPE_TABLE,
21
- } from './types.js';
22
-
23
- // the cell divider: | or +
24
- const TYPE_CELL_DIVIDER = 'cellDivider';
25
-
26
- // a line within a row. can have cells or dividers or both, in case of row spans
27
- const TYPE_ROW_LINE = 'rowLine';
28
-
29
- // the grid divider: - / =
30
- const TYPE_GRID_DIVIDER = 'gridDivider';
31
-
32
- const V_ALIGN_CODES = {
33
- [codes.lowercaseV]: 'bottom',
34
- [codes.lowercaseX]: 'middle',
35
- [codes.caret]: 'top',
36
- };
37
-
38
- function parse() {
39
- return {
40
- tokenize: tokenizeTable,
41
- resolve: resolveTable,
42
- resolveAll: resolveAllTable,
43
- concrete: true,
44
- };
45
-
46
- function tokenizeTable(effects, ok, nok) {
47
- // positions of columns
48
- const cols = [0];
49
- let numRows = 0;
50
- let numCols = 0;
51
- let colPos = 0;
52
- let rowLine = null;
53
- let align = '';
54
- let valign = '';
55
- return start;
56
-
57
- function start(code) {
58
- effects.enter(TYPE_TABLE)._cols = cols;
59
- effects.enter(TYPE_BODY);
60
- return lineStart(code);
61
- }
62
-
63
- function lineStart(code) {
64
- if (code === codes.plusSign || code === codes.verticalBar) {
65
- rowLine = effects.enter(TYPE_ROW_LINE);
66
- effects.enter(TYPE_CELL_DIVIDER);
67
- effects.consume(code);
68
- effects.exit(TYPE_CELL_DIVIDER);
69
- colPos = 0;
70
- numCols = 0;
71
- return cellOrGridStart;
72
- }
73
- if (numRows < 3) {
74
- return nok(code);
75
- }
76
- effects.exit(TYPE_BODY);
77
- effects.exit(TYPE_TABLE);
78
- return ok(code);
79
- }
80
-
81
- function cellOrGridStart(code) {
82
- align = '';
83
- valign = '';
84
- if (code === codes.dash || code === codes.equalsTo
85
- || code === codes.colon || code === codes.greaterThan) {
86
- effects.enter(TYPE_GRID_DIVIDER)._colStart = colPos;
87
- colPos += 1;
88
- if (code === codes.colon) {
89
- align = 'left';
90
- } else if (code === codes.greaterThan) {
91
- align = 'justify';
92
- }
93
- effects.consume(code);
94
- return gridDivider;
95
- }
96
-
97
- if (code === codes.eof || markdownLineEnding(code)) {
98
- return lineEnd(code);
99
- }
100
-
101
- effects.enter(TYPE_CELL)._colStart = colPos;
102
- colPos += 1;
103
- effects.consume(code);
104
-
105
- if (markdownSpace(code)) {
106
- return cellSpace;
107
- }
108
- return cell;
109
- }
110
-
111
- function cellSpace(code) {
112
- if (code === codes.eof || markdownLineEnding(code)) {
113
- // mark as discarded, will be filtered out in transform
114
- effects.exit(TYPE_CELL)._discard = true;
115
- return lineEnd(code);
116
- }
117
- if (markdownSpace(code)) {
118
- colPos += 1;
119
- effects.consume(code);
120
- return cellSpace;
121
- }
122
- return cell(code);
123
- }
124
-
125
- function lineEnd(code) {
126
- if (numCols === 0) {
127
- return nok(code);
128
- }
129
- if (markdownLineEnding(code)) {
130
- effects.enter(types.lineEnding);
131
- effects.consume(code);
132
- effects.exit(types.lineEnding);
133
- }
134
- effects.exit(TYPE_ROW_LINE);
135
- if (code === codes.eof) {
136
- effects.exit(TYPE_BODY);
137
- effects.exit(TYPE_TABLE);
138
- return ok(code);
139
- }
140
- numRows += 1;
141
- return lineStart;
142
- }
143
-
144
- function gridDivider(code) {
145
- colPos += 1;
146
- if (code === codes.dash || code === codes.equalsTo) {
147
- if (!rowLine._type) {
148
- rowLine._type = code;
149
- }
150
- effects.consume(code);
151
- return gridDivider;
152
- }
153
- if (code === codes.colon) {
154
- if (!align) {
155
- align = 'right';
156
- } else if (align === 'left') {
157
- align = 'center';
158
- } else {
159
- return nok(code);
160
- }
161
- effects.consume(code);
162
- return gridDividerEnd;
163
- }
164
- if (code === codes.lessThan) {
165
- if (align !== 'justify') {
166
- return nok(code);
167
- }
168
- effects.consume(code);
169
- return gridDividerEnd;
170
- }
171
-
172
- if (V_ALIGN_CODES[code]) {
173
- if (valign) {
174
- return nok(code);
175
- }
176
- valign = V_ALIGN_CODES[code];
177
- effects.consume(code);
178
- return gridDivider;
179
- }
180
- if (code === codes.plusSign || code === codes.verticalBar) {
181
- colPos -= 1;
182
- return gridDividerEnd(code);
183
- }
184
- return nok(code);
185
- }
186
-
187
- function gridDividerEnd(code) {
188
- if (code !== codes.plusSign && code !== codes.verticalBar) {
189
- return nok(code);
190
- }
191
- // for a super small column, assume dash
192
- if (!rowLine._type) {
193
- rowLine._type = code.dash;
194
- }
195
- colPos += 1;
196
- // remember cols
197
- const idx = cols.indexOf(colPos);
198
- if (idx < 0) {
199
- cols.push(colPos);
200
- cols.sort((c0, c1) => c0 - c1);
201
- }
202
- const token = effects.exit(TYPE_GRID_DIVIDER);
203
- token._colEnd = colPos;
204
- token._align = align;
205
- token._valign = valign;
206
- effects.enter(TYPE_CELL_DIVIDER);
207
- effects.consume(code);
208
- effects.exit(TYPE_CELL_DIVIDER);
209
- numCols += 1;
210
- return cellOrGridStart;
211
- }
212
-
213
- function cell(code) {
214
- colPos += 1;
215
- // find existing col
216
- if (code === codes.verticalBar || code === codes.plusSign) {
217
- const idx = cols.indexOf(colPos);
218
- if (idx >= 0) {
219
- effects.exit(TYPE_CELL)._colEnd = colPos;
220
- effects.enter(TYPE_CELL_DIVIDER);
221
- effects.consume(code);
222
- effects.exit(TYPE_CELL_DIVIDER);
223
- numCols += 1;
224
- return cellOrGridStart;
225
- }
226
- effects.consume(code);
227
- return cell;
228
- }
229
- if (code === codes.eof) {
230
- // row with cells never terminate eof
231
- return nok(code);
232
- }
233
-
234
- effects.consume(code);
235
- return (code === codes.backslash)
236
- ? cellEscaped
237
- : cell;
238
- }
239
-
240
- function cellEscaped(code) {
241
- if (code === codes.backslash || code === codes.verticalBar || code === codes.plusSign) {
242
- colPos += 1;
243
- effects.consume(code);
244
- return cell;
245
- }
246
- return cell(code);
247
- }
248
- }
249
-
250
- function resolveHeaderAndFooter(events, context) {
251
- // detect headers:
252
- // no `=` lines -> only body
253
- // 1 `=` line -> header + body
254
- // 2 `=` lines -> header + body + footer
255
- const fatLines = [];
256
- let bodyStart = -1; // should default to 1. but just be sure
257
-
258
- for (let idx = 0; idx < events.length; idx += 1) {
259
- const [e, node] = events[idx];
260
- const { type } = node;
261
- if (type === TYPE_BODY) {
262
- if (e === 'enter') {
263
- bodyStart = idx;
264
- } else {
265
- // eslint-disable-next-line prefer-const
266
- let [hdrIdx, ftrIdx] = fatLines;
267
- const bdy = node;
268
- if (hdrIdx > bodyStart + 1) {
269
- // insert header above body
270
- const hdr = {
271
- type: TYPE_HEADER,
272
- start: bdy.start,
273
- end: events[hdrIdx][1].end,
274
- };
275
- bdy.start = hdr.end;
276
- events[bodyStart][1] = hdr;
277
- events.splice(
278
- hdrIdx,
279
- 0,
280
- ['exit', hdr, context],
281
- ['enter', bdy, context],
282
- );
283
- idx += 2;
284
- ftrIdx += 2;
285
- }
286
-
287
- if (ftrIdx) {
288
- // insert footer below body
289
- const ftr = {
290
- type: TYPE_FOOTER,
291
- start: events[ftrIdx][1].start,
292
- end: bdy.end,
293
- };
294
- bdy.end = ftr.start;
295
- events.splice(
296
- ftrIdx,
297
- 0,
298
- ['exit', bdy, context],
299
- ['enter', ftr, context],
300
- );
301
- idx += 2;
302
- events[idx][1] = ftr;
303
- }
304
- }
305
- } else if (type === TYPE_ROW_LINE && e === 'enter' && node._type === codes.equalsTo) {
306
- fatLines.push(idx);
307
- }
308
- }
309
- return events;
310
- }
311
-
312
- function resolveTable(events, context) {
313
- // remove discarded
314
- events = events.filter(([, node]) => !node._discard);
315
-
316
- events = resolveHeaderAndFooter(events, context);
317
- // let i = 0;
318
- // for (const [d, { type }] of events) {
319
- // if (d === 'exit') {
320
- // i -= 2;
321
- // }
322
- // console.log(' '.repeat(i), d, type);
323
- // if (d === 'enter') {
324
- // i += 2;
325
- // }
326
- // }
327
- return events;
328
- }
329
-
330
- function resolveAllTable(events, context) {
331
- // since we create a detached parser for each cell content later (in from-markdown.js)
332
- // we need to remember the definitions of the overall document. otherwise the cell parsers
333
- // would not detect the image and link references.
334
- const { defined } = context.parser;
335
-
336
- // find all grid tables and remember the definitions
337
- for (const [evt, node] of events) {
338
- if (evt === 'enter' && node.type === TYPE_TABLE) {
339
- node._definitions = defined;
340
- }
341
- }
342
- return events;
343
- }
344
- }
345
-
346
- export default function create(options = {}) {
347
- return {
348
- flow: {
349
- [codes.plusSign]: parse(options),
350
- },
351
- };
352
- }