@podlite/schema 0.0.66 → 0.0.68
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/CHANGELOG.podlite +44 -0
- package/esm/ast-helpers.d.ts +25 -1
- package/esm/ast-helpers.js +101 -2
- package/esm/ast-helpers.js.map +1 -1
- package/esm/attribute-names.d.ts +5 -0
- package/esm/attribute-names.js +36 -0
- package/esm/attribute-names.js.map +1 -0
- package/esm/block-names.d.ts +1 -0
- package/esm/block-names.js +6 -1
- package/esm/block-names.js.map +1 -1
- package/esm/exportAny.js +2 -2
- package/esm/exportAny.js.map +1 -1
- package/esm/exportHtml.js +60 -22
- package/esm/exportHtml.js.map +1 -1
- package/esm/exportMarkdown.js +62 -52
- package/esm/exportMarkdown.js.map +1 -1
- package/esm/folded-sections.d.ts +1 -0
- package/esm/folded-sections.js +80 -0
- package/esm/folded-sections.js.map +1 -0
- package/esm/grammarfc.js +6099 -15834
- package/esm/grammarfc.js.map +1 -1
- package/esm/guard.d.ts +5 -0
- package/esm/guard.js +39 -0
- package/esm/guard.js.map +1 -0
- package/esm/helpers/corePlugins.js +9 -3
- package/esm/helpers/corePlugins.js.map +1 -1
- package/esm/helpers/html-attr.d.ts +1 -0
- package/esm/helpers/html-attr.js +6 -0
- package/esm/helpers/html-attr.js.map +1 -0
- package/esm/index.d.ts +6 -2
- package/esm/index.js +6 -2
- package/esm/index.js.map +1 -1
- package/esm/pluggableParser.d.ts +1 -1
- package/esm/pluggableParser.js +7 -1
- package/esm/pluggableParser.js.map +1 -1
- package/esm/plugin-data-table.js +2 -1
- package/esm/plugin-data-table.js.map +1 -1
- package/esm/plugin-tables.js +5 -2
- package/esm/plugin-tables.js.map +1 -1
- package/esm/selectors.d.ts +1 -0
- package/esm/selectors.js +42 -19
- package/esm/selectors.js.map +1 -1
- package/esm/types.d.ts +30 -16
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/lib/ast-helpers.d.ts +25 -1
- package/lib/ast-helpers.js +106 -3
- package/lib/attribute-names.d.ts +5 -0
- package/lib/attribute-names.js +41 -0
- package/lib/block-names.d.ts +1 -0
- package/lib/block-names.js +8 -2
- package/lib/exportAny.js +1 -1
- package/lib/exportHtml.js +62 -24
- package/lib/exportMarkdown.js +61 -51
- package/lib/folded-sections.d.ts +1 -0
- package/lib/folded-sections.js +84 -0
- package/lib/grammarfc.js +6099 -15834
- package/lib/guard.d.ts +5 -0
- package/lib/guard.js +47 -0
- package/lib/helpers/corePlugins.js +9 -3
- package/lib/helpers/html-attr.d.ts +1 -0
- package/lib/helpers/html-attr.js +10 -0
- package/lib/index.d.ts +6 -2
- package/lib/index.js +11 -1
- package/lib/pluggableParser.d.ts +1 -1
- package/lib/pluggableParser.js +8 -1
- package/lib/plugin-data-table.js +2 -1
- package/lib/plugin-tables.js +5 -2
- package/lib/selectors.d.ts +1 -0
- package/lib/selectors.js +44 -20
- package/lib/types.d.ts +30 -16
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/schema/AstTree.json +626 -405
- package/schema/PodliteDocument.json +626 -405
package/lib/exportHtml.js
CHANGED
|
@@ -41,36 +41,58 @@ const handlers_1 = require("./helpers/handlers");
|
|
|
41
41
|
const makeTransformer_1 = require("./helpers/makeTransformer");
|
|
42
42
|
const config_1 = __importStar(require("./helpers/config"));
|
|
43
43
|
const image_base_1 = require("./image-base");
|
|
44
|
+
const guard_1 = require("./guard");
|
|
44
45
|
const writerHtml_1 = __importDefault(require("./writerHtml"));
|
|
45
46
|
const plugin_clean_location_1 = __importDefault(require("./plugin-clean-location"));
|
|
46
47
|
const ast_helpers_1 = require("./ast-helpers");
|
|
47
48
|
const link_config_1 = require("./helpers/link-config");
|
|
48
49
|
const entities_1 = require("entities");
|
|
49
|
-
const
|
|
50
|
+
const html_attr_1 = require("./helpers/html-attr");
|
|
51
|
+
// HTML gives an anchor without href to a link whose target the author never
|
|
52
|
+
// wrote; an empty href would claim the current document instead. The address is
|
|
53
|
+
// quoted like every other attribute value: a quote inside it would otherwise
|
|
54
|
+
// close the attribute and let the document write markup of its own.
|
|
55
|
+
const hrefAttr = (node, ctx) => {
|
|
56
|
+
const target = (0, ast_helpers_1.linkTarget)(node);
|
|
57
|
+
if (target === undefined)
|
|
58
|
+
return '';
|
|
59
|
+
const address = (0, ast_helpers_1.sameDocTarget)(target, ctx);
|
|
60
|
+
// A link level one refused points at nothing, and an anchor with no href is what
|
|
61
|
+
// html gives that case. An address shaped from a target that was never there only
|
|
62
|
+
// looks like a working link.
|
|
63
|
+
return address === undefined ? '' : ` href="${(0, html_attr_1.quoteAttribute)(String(address))}"`;
|
|
64
|
+
};
|
|
50
65
|
const linkConfigAttrs = config => {
|
|
51
66
|
const { newContext, title, lang, download } = (0, link_config_1.readLinkConfig)(config);
|
|
52
67
|
const attrs = [];
|
|
53
68
|
if (newContext)
|
|
54
69
|
attrs.push(' target="_blank"');
|
|
55
70
|
if (title !== undefined)
|
|
56
|
-
attrs.push(` title="${
|
|
71
|
+
attrs.push(` title="${(0, html_attr_1.quoteAttribute)(title)}"`);
|
|
57
72
|
if (lang !== undefined)
|
|
58
|
-
attrs.push(` hreflang="${
|
|
73
|
+
attrs.push(` hreflang="${(0, html_attr_1.quoteAttribute)(lang)}"`);
|
|
59
74
|
if (download === true)
|
|
60
75
|
attrs.push(' download');
|
|
61
76
|
else if (typeof download === 'string')
|
|
62
|
-
attrs.push(` download="${
|
|
77
|
+
attrs.push(` download="${(0, html_attr_1.quoteAttribute)(download)}"`);
|
|
63
78
|
return attrs.join('');
|
|
64
79
|
};
|
|
80
|
+
// Shaped by the same rule the address is: an anchor keeping a dot the address drops
|
|
81
|
+
// is how :id<v1.2> came to render an unreachable target. Every place that writes an
|
|
82
|
+
// anchor goes through here, or the two sides part again.
|
|
83
|
+
const anchorOf = (node, ctx) => {
|
|
84
|
+
const written = (0, ast_helpers_1.getExplicitNodeId)(node, ctx);
|
|
85
|
+
return written === null ? null : (ctx?.__anchors?.shape || ast_helpers_1.toFragment)(written);
|
|
86
|
+
};
|
|
65
87
|
const openTag = (tag, node, ctx, attrs = '') => {
|
|
66
|
-
const id = (
|
|
88
|
+
const id = anchorOf(node, ctx);
|
|
67
89
|
return `<${tag}${id ? ` id="${id}"` : ''}${attrs}>`;
|
|
68
90
|
};
|
|
69
91
|
const rules = {
|
|
70
92
|
':text': (writer, processor) => (node, ctx, interator) => {
|
|
71
93
|
// handle text with content
|
|
72
94
|
if (node.value) {
|
|
73
|
-
writer.write(ctx
|
|
95
|
+
writer.write((0, guard_1.isCovered)(node, ctx) ? (0, handlers_1.maskText)(node.value) : node.value);
|
|
74
96
|
}
|
|
75
97
|
else {
|
|
76
98
|
interator(node.content, ctx);
|
|
@@ -146,18 +168,12 @@ const rules = {
|
|
|
146
168
|
'H<>': (0, handlers_1.wrapContent)('<sup>', '</sup>'),
|
|
147
169
|
'J<>': (0, handlers_1.wrapContent)('<sub>', '</sub>'),
|
|
148
170
|
'L<>': (0, handlers_1.setFn)((node, ctx) => {
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
meta = node.content;
|
|
152
|
-
}
|
|
153
|
-
return (0, handlers_1.wrapContent)(`<a href="${(0, ast_helpers_1.sameDocTarget)(meta, ctx)}"${linkConfigAttrs((0, config_1.codeConfigWithDefaults)(node, ctx))}>`, `</a>`);
|
|
171
|
+
const attrs = linkConfigAttrs((0, config_1.codeConfigWithDefaults)(node, ctx));
|
|
172
|
+
return (0, handlers_1.wrapContent)(`<a${hrefAttr(node, ctx)}${attrs}>`, `</a>`);
|
|
154
173
|
}),
|
|
155
174
|
'W<>': (0, handlers_1.setFn)((node, ctx) => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
meta = node.content;
|
|
159
|
-
}
|
|
160
|
-
return (0, handlers_1.wrapContent)(`<a href="${(0, ast_helpers_1.sameDocTarget)(meta, ctx)}"${linkConfigAttrs((0, config_1.codeConfigWithDefaults)(node, ctx))} class="backlink">`, `</a>`);
|
|
175
|
+
const attrs = linkConfigAttrs((0, config_1.codeConfigWithDefaults)(node, ctx));
|
|
176
|
+
return (0, handlers_1.wrapContent)(`<a${hrefAttr(node, ctx)}${attrs} class="backlink">`, `</a>`);
|
|
161
177
|
}),
|
|
162
178
|
/**
|
|
163
179
|
* CSS rules for footnotes
|
|
@@ -243,12 +259,25 @@ const rules = {
|
|
|
243
259
|
pod: handlers_1.content,
|
|
244
260
|
':code': (0, handlers_1.wrapContent)('<pre><code>', '</code></pre>'),
|
|
245
261
|
code: (0, handlers_1.handleNested)((0, handlers_1.setFn)((node, ctx) => (0, handlers_1.wrapContent)(`${openTag('pre', node, ctx)}<code>`, '</code></pre>'))),
|
|
262
|
+
// a folded section is a heading plus the nodes under it; the disclosure is
|
|
263
|
+
// native so the reader needs no script to open it
|
|
264
|
+
_folded_section: (writer, processor) => (node, ctx, interator) => {
|
|
265
|
+
const [heading, ...rest] = (node.content || []);
|
|
266
|
+
const open = node.foldedState === false || node.foldedState === 0 || node.foldedState === '0';
|
|
267
|
+
writer.writeRaw(`<details class="folded-section"${open ? ' open' : ''}>`);
|
|
268
|
+
writer.writeRaw('<summary class="folded-section-summary">');
|
|
269
|
+
if (heading)
|
|
270
|
+
interator([heading], ctx);
|
|
271
|
+
writer.writeRaw('</summary><div class="folded-section-content">');
|
|
272
|
+
interator(rest, ctx);
|
|
273
|
+
writer.writeRaw('</div></details>');
|
|
274
|
+
},
|
|
246
275
|
data: handlers_1.emptyContent,
|
|
247
276
|
':verbatim': (writer, processor) => (node, ctx, interator) => {
|
|
248
277
|
if (node.error) {
|
|
249
278
|
writer.emit('errors', node.location);
|
|
250
279
|
}
|
|
251
|
-
if (ctx
|
|
280
|
+
if ((0, guard_1.isCovered)(node, ctx)) {
|
|
252
281
|
writer.write((0, handlers_1.maskText)(node.value));
|
|
253
282
|
return;
|
|
254
283
|
}
|
|
@@ -276,7 +305,7 @@ const rules = {
|
|
|
276
305
|
// block =para
|
|
277
306
|
// With an :id the block owns the <p> so the anchor lands on it; without one
|
|
278
307
|
// the inner paragraph renders as before.
|
|
279
|
-
para: (0, handlers_1.handleNested)((0, handlers_1.setFn)((node, ctx) => (
|
|
308
|
+
para: (0, handlers_1.handleNested)((0, handlers_1.setFn)((node, ctx) => anchorOf(node, ctx)
|
|
280
309
|
? (0, handlers_1.subUse)({ ':para': handlers_1.content }, (0, handlers_1.wrapContent)(openTag('p', node, ctx), '</p>'))
|
|
281
310
|
: handlers_1.content)),
|
|
282
311
|
':para': (0, handlers_1.setFn)((node, ctx) => (0, handlers_1.wrapContent)(openTag('p', node, ctx), '</p>')),
|
|
@@ -315,7 +344,7 @@ const rules = {
|
|
|
315
344
|
'comment:block': handlers_1.emptyContent,
|
|
316
345
|
'boundary:block': (writer, processor) => (node, ctx) => {
|
|
317
346
|
const conf = (0, config_1.default)(node, ctx);
|
|
318
|
-
const id = (
|
|
347
|
+
const id = anchorOf(node, ctx);
|
|
319
348
|
const idAttr = id ? ` id="${id}"` : '';
|
|
320
349
|
if (conf.exists('caption')) {
|
|
321
350
|
writer.writeRaw(`<hr${idAttr} title="`);
|
|
@@ -328,7 +357,7 @@ const rules = {
|
|
|
328
357
|
},
|
|
329
358
|
// The term opens the pair, so an :id on the definition lands on its <dt>.
|
|
330
359
|
defn: (0, handlers_1.setFn)((node, ctx) => {
|
|
331
|
-
const id = (
|
|
360
|
+
const id = anchorOf(node, ctx);
|
|
332
361
|
return id
|
|
333
362
|
? (0, handlers_1.subUse)({ 'term:para': (0, handlers_1.wrapContent)(`<dt id="${id}">`, '</dt><dd>') }, (0, handlers_1.wrapContent)('', '</dd>'))
|
|
334
363
|
: (0, handlers_1.wrapContent)('', '</dd>');
|
|
@@ -420,7 +449,12 @@ const rules = {
|
|
|
420
449
|
':toc-list': (0, handlers_1.setFn)((node, ctx) => (0, handlers_1.wrapContent)(`<ul class="toc-list listlevel${node.level}">`, '</ul>')),
|
|
421
450
|
':toc-item': (0, handlers_1.setFn)((node, ctx) => (0, handlers_1.wrapContent)('<li class="toc-item">', '</li>')),
|
|
422
451
|
':image': (writer, processor) => (node, ctx, interator) => {
|
|
423
|
-
|
|
452
|
+
const src = (0, html_attr_1.quoteAttribute)(String((0, image_base_1.applyImageBase)(node.src, ctx?.base) ?? ''));
|
|
453
|
+
// html reads a missing alt as "this image is part of the content" and an empty
|
|
454
|
+
// one as "decorative", so an alternative text the author never wrote is left out
|
|
455
|
+
const altText = (0, ast_helpers_1.writtenValue)(node.alt);
|
|
456
|
+
const alt = altText === undefined ? '' : ` alt="${(0, html_attr_1.quoteAttribute)(altText)}"`;
|
|
457
|
+
writer.writeRaw(`<img src="${src}"${alt}/>`);
|
|
424
458
|
},
|
|
425
459
|
};
|
|
426
460
|
const toHtml = opt => (0, exportAny_1.default)({
|
|
@@ -459,15 +493,19 @@ const toHtml = opt => (0, exportAny_1.default)({
|
|
|
459
493
|
})
|
|
460
494
|
.use(rules)
|
|
461
495
|
.use('*', (writer, processor) => (node, ctx, interator, defaultFn) => {
|
|
462
|
-
if (!node
|
|
496
|
+
if (!node)
|
|
463
497
|
return defaultFn();
|
|
464
498
|
if (ctx?.maskMode)
|
|
465
499
|
return defaultFn();
|
|
500
|
+
if (ctx?.renderMode === 'draft')
|
|
501
|
+
return defaultFn();
|
|
502
|
+
if (node.guarded)
|
|
503
|
+
return defaultFn(node, { ...(ctx || {}), maskMode: true }, interator);
|
|
504
|
+
if (node.type !== 'block')
|
|
505
|
+
return defaultFn();
|
|
466
506
|
const conf = (0, config_1.default)(node, ctx || {});
|
|
467
507
|
if (!conf.exists('masked') || !conf.getFirstValue('masked'))
|
|
468
508
|
return defaultFn();
|
|
469
|
-
if (ctx?.renderMode === 'draft')
|
|
470
|
-
return defaultFn();
|
|
471
509
|
return defaultFn(node, { ...(ctx || {}), maskMode: true }, interator);
|
|
472
510
|
});
|
|
473
511
|
exports.default = toHtml;
|
package/lib/exportMarkdown.js
CHANGED
|
@@ -37,6 +37,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
39
|
const exportAny_1 = __importDefault(require("./exportAny"));
|
|
40
|
+
const guard_1 = require("./guard");
|
|
40
41
|
const handlers_1 = require("./helpers/handlers");
|
|
41
42
|
const config_1 = __importStar(require("./helpers/config"));
|
|
42
43
|
const image_base_1 = require("./image-base");
|
|
@@ -51,10 +52,49 @@ const linkTitle = config => {
|
|
|
51
52
|
const { title } = (0, link_config_1.readLinkConfig)(config);
|
|
52
53
|
return title === undefined ? '' : ` "${title.replace(/"/g, '\\"')}"`;
|
|
53
54
|
};
|
|
55
|
+
// Markdown has no form for a link whose target the author never wrote — an empty
|
|
56
|
+
// address there claims the current document — so the text is written on its own.
|
|
57
|
+
// A bracket or a space inside the address would end it where markdown looks for
|
|
58
|
+
// the closing one, so such an address is written in angle brackets, the form
|
|
59
|
+
// markdown keeps for exactly that. An angle of its own is percent-encoded rather
|
|
60
|
+
// than dropped, so the address survives the round trip — no source text reaches
|
|
61
|
+
// here holding one today, since the parser ends the code on it.
|
|
62
|
+
const markdownAddress = (address) => /[()\s]/.test(address) ? `<${address.replace(/</g, '%3C').replace(/>/g, '%3E')}>` : address;
|
|
63
|
+
const linkWrap = (node, ctx) => {
|
|
64
|
+
const target = (0, ast_helpers_1.linkTarget)(node);
|
|
65
|
+
if (target === undefined)
|
|
66
|
+
return (0, handlers_1.wrapContent)('', '');
|
|
67
|
+
const resolved = (0, ast_helpers_1.sameDocTarget)(target, ctx, markdownAnchors(ctx));
|
|
68
|
+
// Markdown has no anchor without an address either, so a refused link keeps its
|
|
69
|
+
// text and loses the brackets.
|
|
70
|
+
if (resolved === undefined)
|
|
71
|
+
return (0, handlers_1.wrapContent)('', '');
|
|
72
|
+
const address = String(resolved);
|
|
73
|
+
return (0, handlers_1.wrapContent)(`[`, `](${markdownAddress(address)}${linkTitle((0, config_1.codeConfigWithDefaults)(node, ctx))})`);
|
|
74
|
+
};
|
|
75
|
+
// A cell's own text is written whole. Trimming each fragment on its own eats the
|
|
76
|
+
// spaces that sit between them — between a word and a markup code, or around a
|
|
77
|
+
// sign the parser split the text on — so only the cell edges are stripped.
|
|
78
|
+
const writeCellParts = (cell, writer, interator, ctx) => {
|
|
79
|
+
const parts = cell.content || [];
|
|
80
|
+
const last = parts.length - 1;
|
|
81
|
+
parts.forEach((part, i) => {
|
|
82
|
+
if (typeof part !== 'string') {
|
|
83
|
+
interator([part], ctx);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
let text = part;
|
|
87
|
+
if (i === 0)
|
|
88
|
+
text = text.replace(/^\s+/, '');
|
|
89
|
+
if (i === last)
|
|
90
|
+
text = text.replace(/\s+$/, '');
|
|
91
|
+
writer.write(text);
|
|
92
|
+
});
|
|
93
|
+
};
|
|
54
94
|
const rules = {
|
|
55
95
|
':text': (writer, processor) => (node, ctx, interator) => {
|
|
56
96
|
if (node.value) {
|
|
57
|
-
writer.write(ctx
|
|
97
|
+
writer.write((0, guard_1.isCovered)(node, ctx) ? (0, handlers_1.maskText)(node.value) : node.value);
|
|
58
98
|
}
|
|
59
99
|
else {
|
|
60
100
|
interator(node.content, ctx);
|
|
@@ -102,20 +142,8 @@ const rules = {
|
|
|
102
142
|
},
|
|
103
143
|
'H<>': (0, handlers_1.wrapContent)('<sup>', '</sup>'),
|
|
104
144
|
'J<>': (0, handlers_1.wrapContent)('<sub>', '</sub>'),
|
|
105
|
-
'L<>': (0, handlers_1.setFn)((node, ctx) =>
|
|
106
|
-
|
|
107
|
-
if (meta === null) {
|
|
108
|
-
meta = node.content;
|
|
109
|
-
}
|
|
110
|
-
return (0, handlers_1.wrapContent)(`[`, `](${(0, ast_helpers_1.sameDocTarget)(meta, ctx, markdownAnchors(ctx))}${linkTitle((0, config_1.codeConfigWithDefaults)(node, ctx))})`);
|
|
111
|
-
}),
|
|
112
|
-
'W<>': (0, handlers_1.setFn)((node, ctx) => {
|
|
113
|
-
let { meta } = node;
|
|
114
|
-
if (meta === null) {
|
|
115
|
-
meta = node.content;
|
|
116
|
-
}
|
|
117
|
-
return (0, handlers_1.wrapContent)(`[`, `](${(0, ast_helpers_1.sameDocTarget)(meta, ctx, markdownAnchors(ctx))}${linkTitle((0, config_1.codeConfigWithDefaults)(node, ctx))})`);
|
|
118
|
-
}),
|
|
145
|
+
'L<>': (0, handlers_1.setFn)((node, ctx) => linkWrap(node, ctx)),
|
|
146
|
+
'W<>': (0, handlers_1.setFn)((node, ctx) => linkWrap(node, ctx)),
|
|
119
147
|
'N<>': (writer, processor) => {
|
|
120
148
|
writer.addListener('end', () => {
|
|
121
149
|
if (!writer.hasOwnProperty('FOOTNOTES')) {
|
|
@@ -183,7 +211,7 @@ const rules = {
|
|
|
183
211
|
const conf = (0, config_1.default)(node, ctx);
|
|
184
212
|
const lang = conf.exists('lang') ? conf.getFirstValue('lang') : '';
|
|
185
213
|
writer.writeRaw('```' + lang + '\n');
|
|
186
|
-
const masked = ctx
|
|
214
|
+
const masked = (0, guard_1.isCovered)(node, ctx);
|
|
187
215
|
if (node.content) {
|
|
188
216
|
node.content.forEach(child => {
|
|
189
217
|
if (typeof child === 'string') {
|
|
@@ -203,7 +231,7 @@ const rules = {
|
|
|
203
231
|
const conf = (0, config_1.default)(node, ctx);
|
|
204
232
|
const lang = conf.exists('lang') ? conf.getFirstValue('lang') : '';
|
|
205
233
|
writer.writeRaw('```' + lang + '\n');
|
|
206
|
-
const masked = ctx
|
|
234
|
+
const masked = (0, guard_1.isCovered)(node, ctx);
|
|
207
235
|
if (node.content) {
|
|
208
236
|
node.content.forEach(child => {
|
|
209
237
|
if (typeof child === 'string') {
|
|
@@ -224,7 +252,7 @@ const rules = {
|
|
|
224
252
|
if (node.error) {
|
|
225
253
|
writer.emit('errors', node.location);
|
|
226
254
|
}
|
|
227
|
-
writer.writeRaw(ctx
|
|
255
|
+
writer.writeRaw((0, guard_1.isCovered)(node, ctx) ? (0, handlers_1.maskText)(node.value) : node.value);
|
|
228
256
|
},
|
|
229
257
|
':blankline': handlers_1.emptyContent,
|
|
230
258
|
':ambient': handlers_1.emptyContent,
|
|
@@ -366,16 +394,7 @@ const rules = {
|
|
|
366
394
|
if (rowspan)
|
|
367
395
|
attrs += ` rowspan="${rowspan}"`;
|
|
368
396
|
writer.writeRaw(`<${tag}${attrs}>`);
|
|
369
|
-
|
|
370
|
-
cell.content.forEach(c => {
|
|
371
|
-
if (typeof c === 'string') {
|
|
372
|
-
writer.write(c.trim());
|
|
373
|
-
}
|
|
374
|
-
else {
|
|
375
|
-
interator([c], ctx);
|
|
376
|
-
}
|
|
377
|
-
});
|
|
378
|
-
}
|
|
397
|
+
writeCellParts(cell, writer, interator, ctx);
|
|
379
398
|
writer.writeRaw(`</${tag}>`);
|
|
380
399
|
});
|
|
381
400
|
writer.writeRaw('</tr>\n');
|
|
@@ -393,15 +412,7 @@ const rules = {
|
|
|
393
412
|
return null;
|
|
394
413
|
writer.output = (str) => parts.push(str);
|
|
395
414
|
try {
|
|
396
|
-
;
|
|
397
|
-
(cell.content || []).forEach(c => {
|
|
398
|
-
if (typeof c === 'string') {
|
|
399
|
-
writer.write(c.trim());
|
|
400
|
-
}
|
|
401
|
-
else {
|
|
402
|
-
interator([c], ctx);
|
|
403
|
-
}
|
|
404
|
-
});
|
|
415
|
+
writeCellParts(cell, writer, interator, ctx);
|
|
405
416
|
}
|
|
406
417
|
finally {
|
|
407
418
|
writer.output = original;
|
|
@@ -419,16 +430,7 @@ const rules = {
|
|
|
419
430
|
writer.writeRaw(' ');
|
|
420
431
|
const folded = renderCell(cell);
|
|
421
432
|
if (folded === null) {
|
|
422
|
-
|
|
423
|
-
cell.content.forEach(c => {
|
|
424
|
-
if (typeof c === 'string') {
|
|
425
|
-
writer.write(c.trim());
|
|
426
|
-
}
|
|
427
|
-
else {
|
|
428
|
-
interator([c], ctx);
|
|
429
|
-
}
|
|
430
|
-
});
|
|
431
|
-
}
|
|
433
|
+
writeCellParts(cell, writer, interator, ctx);
|
|
432
434
|
}
|
|
433
435
|
else {
|
|
434
436
|
writer.writeRaw(folded);
|
|
@@ -463,7 +465,11 @@ const rules = {
|
|
|
463
465
|
':toc-list': handlers_1.emptyContent,
|
|
464
466
|
':toc-item': handlers_1.emptyContent,
|
|
465
467
|
':image': (writer, processor) => (node, ctx, interator) => {
|
|
466
|
-
|
|
468
|
+
// the alternative text sits between square brackets, where a `]` of its own
|
|
469
|
+
// would end it, and the address between round ones — the same shape a link has
|
|
470
|
+
const alt = ((0, ast_helpers_1.writtenValue)(node.alt) ?? '').replace(/([[\]\\])/g, '\\$1');
|
|
471
|
+
const src = markdownAddress(String((0, image_base_1.applyImageBase)(node.src, ctx?.base) ?? ''));
|
|
472
|
+
writer.writeRaw(``);
|
|
467
473
|
},
|
|
468
474
|
};
|
|
469
475
|
const toMarkdown = opt => (0, exportAny_1.default)({
|
|
@@ -491,15 +497,19 @@ const toMarkdown = opt => (0, exportAny_1.default)({
|
|
|
491
497
|
})
|
|
492
498
|
.use(rules)
|
|
493
499
|
.use('*', (writer, processor) => (node, ctx, interator, defaultFn) => {
|
|
494
|
-
if (!node
|
|
500
|
+
if (!node)
|
|
495
501
|
return defaultFn();
|
|
496
502
|
if (ctx?.maskMode)
|
|
497
503
|
return defaultFn();
|
|
504
|
+
if (ctx?.renderMode === 'draft')
|
|
505
|
+
return defaultFn();
|
|
506
|
+
if (node.guarded)
|
|
507
|
+
return defaultFn(node, { ...(ctx || {}), maskMode: true }, interator);
|
|
508
|
+
if (node.type !== 'block')
|
|
509
|
+
return defaultFn();
|
|
498
510
|
const conf = (0, config_1.default)(node, ctx || {});
|
|
499
511
|
if (!conf.exists('masked') || !conf.getFirstValue('masked'))
|
|
500
512
|
return defaultFn();
|
|
501
|
-
if (ctx?.renderMode === 'draft')
|
|
502
|
-
return defaultFn();
|
|
503
513
|
return defaultFn(node, { ...(ctx || {}), maskMode: true }, interator);
|
|
504
514
|
});
|
|
505
515
|
exports.default = toMarkdown;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const applyFoldedSections: (node: any) => any;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.applyFoldedSections = void 0;
|
|
4
|
+
// Folding of a section belongs to the tree, not to one renderer: the command
|
|
5
|
+
// line and every build-time producer read the same document as the editor does.
|
|
6
|
+
// Moved here from @podlite/to-jsx, where it lived and left exportHtml and
|
|
7
|
+
// exportMarkdown unable to fold anything.
|
|
8
|
+
// `:folded` on a heading folds the whole section — the heading plus every
|
|
9
|
+
// following node up to the next same-or-higher-level heading. Detect the
|
|
10
|
+
// attribute on =head nodes in a container's content array and wrap that
|
|
11
|
+
// range in a synthetic `_folded_section` block so the JSX renderer can emit
|
|
12
|
+
// <details> around it.
|
|
13
|
+
const getFoldedAttr = (node) => {
|
|
14
|
+
const config = node && node.config;
|
|
15
|
+
if (!Array.isArray(config))
|
|
16
|
+
return null;
|
|
17
|
+
const entry = config.find((c) => c && c.name === 'folded');
|
|
18
|
+
return entry ? entry.value : null;
|
|
19
|
+
};
|
|
20
|
+
const isHeadBlock = (node) => node && node.type === 'block' && node.name === 'head' && node.level !== undefined && node.level !== null;
|
|
21
|
+
const headLevel = (node) => Number(node.level);
|
|
22
|
+
const groupFoldedSections = (content) => {
|
|
23
|
+
if (!Array.isArray(content))
|
|
24
|
+
return content;
|
|
25
|
+
const result = [];
|
|
26
|
+
let i = 0;
|
|
27
|
+
while (i < content.length) {
|
|
28
|
+
const node = content[i];
|
|
29
|
+
if (isHeadBlock(node)) {
|
|
30
|
+
const folded = getFoldedAttr(node);
|
|
31
|
+
if (folded !== null) {
|
|
32
|
+
const level = headLevel(node);
|
|
33
|
+
const sectionNodes = [node];
|
|
34
|
+
let j = i + 1;
|
|
35
|
+
while (j < content.length) {
|
|
36
|
+
const next = content[j];
|
|
37
|
+
if (isHeadBlock(next) && headLevel(next) <= level)
|
|
38
|
+
break;
|
|
39
|
+
sectionNodes.push(next);
|
|
40
|
+
j++;
|
|
41
|
+
}
|
|
42
|
+
result.push({
|
|
43
|
+
type: 'block',
|
|
44
|
+
name: '_folded_section',
|
|
45
|
+
content: sectionNodes,
|
|
46
|
+
foldedState: folded,
|
|
47
|
+
location: node.location,
|
|
48
|
+
});
|
|
49
|
+
i = j;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
result.push(node);
|
|
54
|
+
i++;
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
};
|
|
58
|
+
// Walk the AST and apply `groupFoldedSections` to every block's `content`
|
|
59
|
+
// array, so :folded heads inside named blocks, defn, nested etc. fold the
|
|
60
|
+
// same way they do at the pod-level. Inside an already-built
|
|
61
|
+
// `_folded_section`, the first element is the heading the wrapper belongs
|
|
62
|
+
// to — skip it when grouping the rest, otherwise the same head would be
|
|
63
|
+
// re-wrapped on every recursion. Nested folds (a folded heading inside a
|
|
64
|
+
// folded section's body) are still picked up by grouping the remainder.
|
|
65
|
+
const applyFoldedSections = (node) => {
|
|
66
|
+
if (!node || typeof node !== 'object')
|
|
67
|
+
return node;
|
|
68
|
+
if (Array.isArray(node))
|
|
69
|
+
return node.map(exports.applyFoldedSections);
|
|
70
|
+
if (!Array.isArray(node.content))
|
|
71
|
+
return node;
|
|
72
|
+
if (node.name === '_folded_section') {
|
|
73
|
+
const [head, ...rest] = node.content;
|
|
74
|
+
const grouped = groupFoldedSections(rest);
|
|
75
|
+
return {
|
|
76
|
+
...node,
|
|
77
|
+
content: [(0, exports.applyFoldedSections)(head), ...grouped.map(exports.applyFoldedSections)],
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
const grouped = groupFoldedSections(node.content);
|
|
81
|
+
return { ...node, content: grouped.map(exports.applyFoldedSections) };
|
|
82
|
+
};
|
|
83
|
+
exports.applyFoldedSections = applyFoldedSections;
|
|
84
|
+
//# sourceMappingURL=folded-sections.js.map
|