@podlite/schema 0.0.65 → 0.0.66
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 +16 -0
- package/esm/blocks-helpers.d.ts +1 -1
- package/esm/blocks-helpers.js +2 -1
- package/esm/blocks-helpers.js.map +1 -1
- package/esm/exportMarkdown.js +43 -9
- package/esm/exportMarkdown.js.map +1 -1
- package/esm/grammarfc.js +7794 -6355
- package/esm/grammarfc.js.map +1 -1
- package/esm/plugin-data-table.d.ts +1 -1
- package/esm/plugin-data-table.js +11 -10
- package/esm/plugin-data-table.js.map +1 -1
- package/esm/plugin-formatting-codes.js +49 -13
- package/esm/plugin-formatting-codes.js.map +1 -1
- package/esm/plugin-tables.d.ts +4 -2
- package/esm/plugin-tables.js +60 -16
- package/esm/plugin-tables.js.map +1 -1
- package/esm/types.d.ts +3 -2
- package/esm/version.d.ts +1 -1
- package/esm/version.js +1 -1
- package/lib/blocks-helpers.d.ts +1 -1
- package/lib/blocks-helpers.js +2 -1
- package/lib/exportMarkdown.js +43 -9
- package/lib/grammarfc.js +7794 -6355
- package/lib/plugin-data-table.d.ts +1 -1
- package/lib/plugin-data-table.js +10 -9
- package/lib/plugin-formatting-codes.js +49 -13
- package/lib/plugin-tables.d.ts +4 -2
- package/lib/plugin-tables.js +61 -16
- package/lib/types.d.ts +3 -2
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/schema/AstTree.json +8 -1
- package/schema/PodliteDocument.json +8 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: () => (tree: any) => any;
|
|
1
|
+
declare const _default: (opt?: {}) => (tree: any) => any;
|
|
2
2
|
export default _default;
|
package/lib/plugin-data-table.js
CHANGED
|
@@ -65,7 +65,7 @@ function applyRename(rows, rename, hasHeader) {
|
|
|
65
65
|
}
|
|
66
66
|
return [headerRow, ...rows.slice(1)];
|
|
67
67
|
}
|
|
68
|
-
function processDataTable(node, tree) {
|
|
68
|
+
function processDataTable(node, tree, report) {
|
|
69
69
|
const attrs = (0, config_1.default)(node, {});
|
|
70
70
|
const srcRaw = attrs.getFirstValue('src');
|
|
71
71
|
const mimeAttr = attrs.getFirstValue('mime-type');
|
|
@@ -91,7 +91,7 @@ function processDataTable(node, tree) {
|
|
|
91
91
|
if (scheme === 'data') {
|
|
92
92
|
const dataBlock = (0, plugin_tables_1.findDataBlockByKey)(tree, target);
|
|
93
93
|
if (!dataBlock) {
|
|
94
|
-
|
|
94
|
+
report('table-source-unreadable', `no =data block found for data:${target}, table rendered as empty`, node);
|
|
95
95
|
return { ...node, name: 'table', content: [] };
|
|
96
96
|
}
|
|
97
97
|
if (mimeAttr) {
|
|
@@ -99,7 +99,7 @@ function processDataTable(node, tree) {
|
|
|
99
99
|
}
|
|
100
100
|
const dataMime = (0, config_1.default)(dataBlock, {}).getFirstValue('mime-type');
|
|
101
101
|
if (!dataMime) {
|
|
102
|
-
|
|
102
|
+
report('table-source-unreadable', `=data block ${target} has no :mime-type, table rendered as empty`, node);
|
|
103
103
|
return { ...node, name: 'table', content: [] };
|
|
104
104
|
}
|
|
105
105
|
const parsed = (0, plugin_tables_1.parseMimeType)(dataMime);
|
|
@@ -123,12 +123,12 @@ function processDataTable(node, tree) {
|
|
|
123
123
|
const isCsv = mimeType === 'text/csv';
|
|
124
124
|
const isTsv = mimeType === 'text/tab-separated-values';
|
|
125
125
|
if (!isCsv && !isTsv) {
|
|
126
|
-
|
|
126
|
+
report('table-source-unreadable', `unsupported mime-type ${mimeType}, table rendered as empty`, node);
|
|
127
127
|
return { ...node, name: 'table', content: [] };
|
|
128
128
|
}
|
|
129
129
|
let rows = isCsv ? (0, plugin_tables_1.parseCsv)(csvText) : (0, plugin_tables_1.parseTsv)(csvText);
|
|
130
130
|
if (rows.length === 0) {
|
|
131
|
-
|
|
131
|
+
report('table-source-unreadable', `${isCsv ? 'CSV' : 'TSV'} source has no rows, table rendered as empty`, node);
|
|
132
132
|
return { ...node, name: 'table', content: [] };
|
|
133
133
|
}
|
|
134
134
|
if (columns) {
|
|
@@ -142,16 +142,17 @@ function processDataTable(node, tree) {
|
|
|
142
142
|
name: 'table',
|
|
143
143
|
content: (0, plugin_tables_1.csvToTableContent)(rows, hasHeader, attrs.getAllValues('allow')),
|
|
144
144
|
};
|
|
145
|
-
return (0, plugin_tables_1.normalizeCellCounts)(filledNode, 'data-table');
|
|
145
|
+
return (0, plugin_tables_1.normalizeCellCounts)(filledNode, 'data-table', report);
|
|
146
146
|
}
|
|
147
|
-
exports.default = () => tree => {
|
|
147
|
+
exports.default = (opt = {}) => tree => {
|
|
148
|
+
const report = (0, plugin_tables_1.makeTableReport)(opt);
|
|
148
149
|
const transformer = (0, makeTransformer_1.default)({
|
|
149
150
|
'data-table': node => {
|
|
150
151
|
try {
|
|
151
|
-
return processDataTable(node, tree);
|
|
152
|
+
return processDataTable(node, tree, report);
|
|
152
153
|
}
|
|
153
154
|
catch (err) {
|
|
154
|
-
|
|
155
|
+
report('table-source-unreadable', err.message, node);
|
|
155
156
|
return { ...node, name: 'table', content: [] };
|
|
156
157
|
}
|
|
157
158
|
},
|
|
@@ -41,49 +41,85 @@ const makeTransformer_1 = __importDefault(require("./helpers/makeTransformer"));
|
|
|
41
41
|
const makeTransformer_2 = require("./helpers/makeTransformer");
|
|
42
42
|
const config_1 = __importDefault(require("./helpers/config"));
|
|
43
43
|
const parseAttributes_1 = require("./helpers/parseAttributes");
|
|
44
|
+
// `=config C<> :allow<I>` names a markup code, not a block: the trailing angles
|
|
45
|
+
// are the marker, and what it declares belongs to the code they name
|
|
46
|
+
const codeConfigOwner = (name) => typeof name === 'string' && /^[A-Z]<>$/.test(name) ? name[0] : null;
|
|
47
|
+
const collectAllowedIn = (content, inherited) => {
|
|
48
|
+
if (!Array.isArray(content))
|
|
49
|
+
return inherited;
|
|
50
|
+
let map = inherited;
|
|
51
|
+
for (const child of content) {
|
|
52
|
+
if (!child || typeof child !== 'object')
|
|
53
|
+
continue;
|
|
54
|
+
const node = child;
|
|
55
|
+
if (node.type !== 'config')
|
|
56
|
+
continue;
|
|
57
|
+
const owner = codeConfigOwner(node.name);
|
|
58
|
+
if (!owner)
|
|
59
|
+
continue;
|
|
60
|
+
if (map === inherited)
|
|
61
|
+
map = { ...inherited };
|
|
62
|
+
map[owner] = (0, config_1.default)(node, {}).getAllValues('allow');
|
|
63
|
+
}
|
|
64
|
+
return map;
|
|
65
|
+
};
|
|
44
66
|
const middle = () => tree => {
|
|
45
67
|
const transformerBlocks = (0, makeTransformer_1.default)({
|
|
46
68
|
':para': (n, ctx, visiter) => {
|
|
69
|
+
const allowedIn = ctx.allowedIn;
|
|
47
70
|
return (0, makeTransformer_1.default)({
|
|
48
71
|
':text': (n, ctx) => {
|
|
49
|
-
return fcparser.parse(n.value, { parseAttributes: parseAttributes_1.parseAttributes });
|
|
72
|
+
return fcparser.parse(n.value, { allowedIn, parseAttributes: parseAttributes_1.parseAttributes });
|
|
50
73
|
},
|
|
51
74
|
':verbatim': (n, ctx) => {
|
|
52
|
-
return fcparser.parse(n.value, { parseAttributes: parseAttributes_1.parseAttributes });
|
|
75
|
+
return fcparser.parse(n.value, { allowedIn, parseAttributes: parseAttributes_1.parseAttributes });
|
|
53
76
|
},
|
|
54
77
|
})(n, { ...ctx });
|
|
55
78
|
return n;
|
|
56
79
|
},
|
|
57
80
|
':block': (n, ctx, visiter) => {
|
|
81
|
+
// a block is a lexical scope: a code configured inside it stays inside
|
|
82
|
+
const allowedIn = collectAllowedIn('content' in n ? n.content : undefined, ctx.allowedIn || {});
|
|
58
83
|
// only =pod may have childs blocks
|
|
59
84
|
if ('name' in n && n.name === 'pod')
|
|
60
85
|
return {
|
|
61
86
|
...n,
|
|
62
|
-
content: visiter(n.content, ctx, visiter),
|
|
87
|
+
content: visiter(n.content, { ...ctx, allowedIn }, visiter),
|
|
63
88
|
};
|
|
64
89
|
const conf = (0, config_1.default)(n, ctx);
|
|
65
90
|
const name = 'name' in n ? n.name : '';
|
|
66
91
|
// Blocks whose content is verbatim by default — fcode parsing only
|
|
67
92
|
// kicks in when :allow opts in (per spec, "Formatting within code blocks").
|
|
68
93
|
const isVerbatimDefault = ['code', 'data', 'markdown', 'picture', 'formula'].includes(name);
|
|
69
|
-
const allowValues = conf.getAllValues('allow');
|
|
70
94
|
if ((0, makeTransformer_2.isNamedBlock)(name))
|
|
71
95
|
return n;
|
|
96
|
+
// A table owns rows, and the text sits in the cells, so :allow written on
|
|
97
|
+
// the table reaches them. The nearest declaration wins: cell, row, table.
|
|
98
|
+
const inheritsAllow = name === 'row' || name === 'cell';
|
|
99
|
+
const declared = conf.exists('allow')
|
|
100
|
+
? conf.getAllValues('allow')
|
|
101
|
+
: inheritsAllow
|
|
102
|
+
? ctx.allowFromTable
|
|
103
|
+
: undefined;
|
|
104
|
+
const allowValues = declared || [];
|
|
105
|
+
const passesAllow = name === 'table' || name === 'row' ? declared : ctx.allowFromTable;
|
|
72
106
|
if (isVerbatimDefault && allowValues.length === 0)
|
|
73
107
|
return n;
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const allowed = allowValues.sort();
|
|
108
|
+
// declared empty means no code acts on this text; nested blocks still get
|
|
109
|
+
// their turn, since a cell may declare a set of its own
|
|
110
|
+
const literal = inheritsAllow && declared !== undefined && declared.length === 0;
|
|
111
|
+
const allowed = [...allowValues].sort();
|
|
112
|
+
const inner = { ...ctx, allowedIn, allowFromTable: passesAllow };
|
|
78
113
|
const transformer = (0, makeTransformer_1.default)({
|
|
79
|
-
':verbatim': (
|
|
80
|
-
':text': (
|
|
81
|
-
':block': (
|
|
114
|
+
':verbatim': (node, ctx) => literal ? node : fcparser.parse(node.value, { allowed, allowedIn, parseAttributes: parseAttributes_1.parseAttributes }),
|
|
115
|
+
':text': (node, ctx) => literal ? node : fcparser.parse(node.value, { allowed, allowedIn, parseAttributes: parseAttributes_1.parseAttributes }),
|
|
116
|
+
':block': (node, ctx) => transformerBlocks(node, { ...ctx, allowedIn, allowFromTable: passesAllow }),
|
|
82
117
|
});
|
|
83
|
-
return { ...n, content: transformer(n.content,
|
|
118
|
+
return { ...n, content: transformer(n.content, inner) };
|
|
84
119
|
},
|
|
85
120
|
});
|
|
86
|
-
|
|
121
|
+
// a document needs no enclosing block, so the top level is a scope of its own
|
|
122
|
+
return transformerBlocks(tree, { allowedIn: collectAllowedIn(tree, {}) });
|
|
87
123
|
};
|
|
88
124
|
exports.default = middle;
|
|
89
125
|
//# sourceMappingURL=plugin-formatting-codes.js.map
|
package/lib/plugin-tables.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export declare function parseMimeType(raw: any): {
|
|
|
7
7
|
export declare function findDataBlockByKey(tree: any, key: any): any;
|
|
8
8
|
export declare function extractDataText(dataNode: any): any;
|
|
9
9
|
export declare function csvToTableContent(csvRows: any, hasHeader?: boolean, allow?: string[]): any;
|
|
10
|
-
export
|
|
11
|
-
declare
|
|
10
|
+
export type TableReport = (code: string, message: string, node: any) => void;
|
|
11
|
+
export declare function makeTableReport(opt: any): TableReport;
|
|
12
|
+
export declare function normalizeCellCounts(tableNode: any, source?: string, report?: TableReport): any;
|
|
13
|
+
declare const _default: (opt?: {}) => (tree: any) => any;
|
|
12
14
|
export default _default;
|
package/lib/plugin-tables.js
CHANGED
|
@@ -9,6 +9,7 @@ exports.parseMimeType = parseMimeType;
|
|
|
9
9
|
exports.findDataBlockByKey = findDataBlockByKey;
|
|
10
10
|
exports.extractDataText = extractDataText;
|
|
11
11
|
exports.csvToTableContent = csvToTableContent;
|
|
12
|
+
exports.makeTableReport = makeTableReport;
|
|
12
13
|
exports.normalizeCellCounts = normalizeCellCounts;
|
|
13
14
|
/**
|
|
14
15
|
* Plugin for fill term's for defn. From S26:
|
|
@@ -216,16 +217,27 @@ function csvToTableContent(csvRows, hasHeader = false, allow = []) {
|
|
|
216
217
|
return buildRowBlock(cells, hasHeader && i === 0);
|
|
217
218
|
});
|
|
218
219
|
}
|
|
219
|
-
|
|
220
|
+
function makeTableReport(opt) {
|
|
221
|
+
const diagnostics = opt && Array.isArray(opt.diagnostics) ? opt.diagnostics : null;
|
|
222
|
+
return (code, message, node) => {
|
|
223
|
+
const location = node && node.location;
|
|
224
|
+
if (!diagnostics || !location)
|
|
225
|
+
return;
|
|
226
|
+
const seen = diagnostics.some(d => d.message === message && d.location.start.offset === location.start.offset);
|
|
227
|
+
if (!seen)
|
|
228
|
+
diagnostics.push({ severity: 'warning', code, message, location });
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
const noReport = () => { };
|
|
220
232
|
// Rule 2 — table-level cell count validation. Pad short rows with empty
|
|
221
|
-
// cells; truncate long rows.
|
|
233
|
+
// cells; truncate long rows. Report whenever a row is changed.
|
|
222
234
|
// Expected count is taken from the `:header` row if present, otherwise from
|
|
223
235
|
// the row with the maximum cell count.
|
|
224
236
|
//
|
|
225
237
|
// Skipped when any cell uses `:colspan` or `:rowspan`: a spanning cell
|
|
226
238
|
// occupies multiple columns, so naive cell counting would misreport row
|
|
227
239
|
// width and drop legitimate spanned cells.
|
|
228
|
-
function normalizeCellCounts(tableNode, source = 'table') {
|
|
240
|
+
function normalizeCellCounts(tableNode, source = 'table', report = noReport) {
|
|
229
241
|
if (!tableNode || !Array.isArray(tableNode.content))
|
|
230
242
|
return tableNode;
|
|
231
243
|
const rows = tableNode.content.filter(c => c && c.type === 'block' && c.name === 'row');
|
|
@@ -252,13 +264,13 @@ function normalizeCellCounts(tableNode, source = 'table') {
|
|
|
252
264
|
const padding = [];
|
|
253
265
|
for (let i = cells.length; i < expected; i++)
|
|
254
266
|
padding.push(buildCellBlock(''));
|
|
255
|
-
|
|
267
|
+
report('table-row-cells', `${source} row has ${cells.length} of ${expected} cells, padded with ${padding.length} empty. A row continued on the next line needs a blank line before the next row`, tableNode);
|
|
256
268
|
mutated = true;
|
|
257
269
|
return { ...child, content: [...child.content, ...padding] };
|
|
258
270
|
}
|
|
259
271
|
// cells.length > expected → truncate
|
|
260
272
|
const dropped = cells.length - expected;
|
|
261
|
-
|
|
273
|
+
report('table-row-cells', `${source} row has ${cells.length} of ${expected} cells, dropped ${dropped}`, tableNode);
|
|
262
274
|
mutated = true;
|
|
263
275
|
// Keep non-cell entries (e.g. blanklines) and the first `expected` cells
|
|
264
276
|
let keepCells = expected;
|
|
@@ -282,7 +294,7 @@ function normalizeCellCounts(tableNode, source = 'table') {
|
|
|
282
294
|
// for visible separators (`|` / `+`) surrounded by whitespace; lines without
|
|
283
295
|
// any visible separator fall back to whitespace separation. Warns when more
|
|
284
296
|
// than one separator type is observed within a single table.
|
|
285
|
-
function detectMixedSeparators(lines) {
|
|
297
|
+
function detectMixedSeparators(lines, report = noReport, node = null) {
|
|
286
298
|
const seen = new Set();
|
|
287
299
|
for (const line of lines) {
|
|
288
300
|
if (!line || typeof line !== 'string')
|
|
@@ -297,7 +309,7 @@ function detectMixedSeparators(lines) {
|
|
|
297
309
|
break;
|
|
298
310
|
}
|
|
299
311
|
if (seen.size > 1) {
|
|
300
|
-
|
|
312
|
+
report('table-mixed-separators', `table mixes separator styles: ${Array.from(seen).join(', ')}. Keep one`, node);
|
|
301
313
|
}
|
|
302
314
|
}
|
|
303
315
|
// Rule 4 — replace =table with =code block. Used when a referenced =data
|
|
@@ -448,9 +460,41 @@ const wrapImplicitCells = rowNode => {
|
|
|
448
460
|
});
|
|
449
461
|
return { ...rowNode, content: wrapped };
|
|
450
462
|
};
|
|
463
|
+
// An abbreviated `=for row` owns its own paragraph, so cells written under it
|
|
464
|
+
// stay at table level and both the row and the cells lose their meaning. They
|
|
465
|
+
// are attached to the row above, and the author is told, per the same recovery
|
|
466
|
+
// contract that pads and truncates rows.
|
|
467
|
+
const attachOrphanCells = (tableNode, report = noReport) => {
|
|
468
|
+
const content = tableNode.content;
|
|
469
|
+
if (!Array.isArray(content))
|
|
470
|
+
return tableNode;
|
|
471
|
+
if (!content.some(c => c && c.type === 'block' && c.name === 'cell'))
|
|
472
|
+
return tableNode;
|
|
473
|
+
const out = [];
|
|
474
|
+
let openRow = null;
|
|
475
|
+
for (const child of content) {
|
|
476
|
+
if (child && child.type === 'block' && child.name === 'row') {
|
|
477
|
+
openRow = { ...child, content: Array.isArray(child.content) ? [...child.content] : [] };
|
|
478
|
+
out.push(openRow);
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
if (child && child.type === 'block' && child.name === 'cell') {
|
|
482
|
+
if (!openRow) {
|
|
483
|
+
openRow = { type: 'block', name: 'row', margin: child.margin || '', content: [] };
|
|
484
|
+
out.push(openRow);
|
|
485
|
+
}
|
|
486
|
+
openRow.content.push(child);
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
out.push(child);
|
|
490
|
+
}
|
|
491
|
+
report('table-cell-outside-row', 'a cell written outside a row was attached to the row above it; an abbreviated =for row holds only its own paragraph, so write =begin row and =end row around the cells', tableNode);
|
|
492
|
+
return { ...tableNode, content: out };
|
|
493
|
+
};
|
|
451
494
|
const isStructured = tableNode => Array.isArray(tableNode.content) &&
|
|
452
495
|
tableNode.content.some(c => c && c.type === 'block' && (c.name === 'row' || c.name === 'cell'));
|
|
453
|
-
exports.default = () => tree => {
|
|
496
|
+
exports.default = (opt = {}) => tree => {
|
|
497
|
+
const report = makeTableReport(opt);
|
|
454
498
|
const transformer = (0, makeTransformer_1.default)({
|
|
455
499
|
table: (node, ctx, visiter) => {
|
|
456
500
|
// CSV/data source reference (spec §1672):
|
|
@@ -461,7 +505,7 @@ exports.default = () => tree => {
|
|
|
461
505
|
const dataBlock = findDataBlockByKey(tree, ref.target);
|
|
462
506
|
if (!dataBlock) {
|
|
463
507
|
// Rule 4: source not found → empty table (still a =table block)
|
|
464
|
-
|
|
508
|
+
report('table-source-unreadable', `no =data block found for data:${ref.target}, table rendered as empty`, node);
|
|
465
509
|
return { ...node, content: [] };
|
|
466
510
|
}
|
|
467
511
|
const rawMime = (0, config_1.default)(dataBlock, {}).getFirstValue('mime-type');
|
|
@@ -472,22 +516,23 @@ exports.default = () => tree => {
|
|
|
472
516
|
const text = extractDataText(dataBlock);
|
|
473
517
|
const rows = isCsv ? parseCsv(text) : parseTsv(text);
|
|
474
518
|
if (rows.length === 0) {
|
|
475
|
-
|
|
519
|
+
report('table-source-unreadable', `${isCsv ? 'CSV' : 'TSV'} source data:${ref.target} has no rows, table rendered as empty`, node);
|
|
476
520
|
return { ...node, content: [] };
|
|
477
521
|
}
|
|
478
522
|
const hasHeader = mimeParams.header === 'present';
|
|
479
523
|
const allow = (0, config_1.default)(node, {}).getAllValues('allow');
|
|
480
524
|
const filledNode = { ...node, content: csvToTableContent(rows, hasHeader, allow) };
|
|
481
|
-
return normalizeCellCounts(filledNode, `table data:${ref.target}
|
|
525
|
+
return normalizeCellCounts(filledNode, `table data:${ref.target}`, report);
|
|
482
526
|
}
|
|
483
527
|
// Rule 4: source not tabular → render as code block so content remains visible
|
|
484
|
-
|
|
528
|
+
report('table-source-unreadable', `=data :key<${ref.target}> has non-tabular mime-type ${rawMime || '(none)'}, rendered as =code`, node);
|
|
485
529
|
return buildCodeFromDataBlock(node, dataBlock);
|
|
486
530
|
}
|
|
487
531
|
// structured mode: transform row children (wrap implicit cells), then
|
|
488
532
|
// apply Rule 2 cell count normalization.
|
|
489
533
|
if (isStructured(node)) {
|
|
490
|
-
const
|
|
534
|
+
const attached = attachOrphanCells(node, report);
|
|
535
|
+
const transformedContent = (attached.content || []).map(c => {
|
|
491
536
|
if (c && c.name === 'row')
|
|
492
537
|
return wrapImplicitCells(c);
|
|
493
538
|
return c;
|
|
@@ -495,7 +540,7 @@ exports.default = () => tree => {
|
|
|
495
540
|
// a matched rule replaces the node without descending, so recurse
|
|
496
541
|
// here or tables nested inside cells keep their raw text rows
|
|
497
542
|
const recursed = visiter ? visiter(transformedContent, ctx) : transformedContent;
|
|
498
|
-
return normalizeCellCounts({ ...
|
|
543
|
+
return normalizeCellCounts({ ...attached, content: recursed }, 'table', report);
|
|
499
544
|
}
|
|
500
545
|
let rows = [];
|
|
501
546
|
const collectValues = row => {
|
|
@@ -521,7 +566,7 @@ exports.default = () => tree => {
|
|
|
521
566
|
const lines = flattenDeep(rows.map(splitToLines));
|
|
522
567
|
const separators = flattenDeep(seps.map(splitToLines));
|
|
523
568
|
// Rule 3: warn on mixed separator types within a single table
|
|
524
|
-
detectMixedSeparators(lines);
|
|
569
|
+
detectMixedSeparators(lines, report, node);
|
|
525
570
|
// collect text rows
|
|
526
571
|
let textRows = [];
|
|
527
572
|
(0, makeTransformer_1.default)({
|
|
@@ -560,7 +605,7 @@ exports.default = () => tree => {
|
|
|
560
605
|
},
|
|
561
606
|
'head:text': head => makeHeaderRow(splitToCells(head.value).map(makeCell)),
|
|
562
607
|
})(node);
|
|
563
|
-
return normalizeCellCounts(res, 'table');
|
|
608
|
+
return normalizeCellCounts(res, 'table', report);
|
|
564
609
|
},
|
|
565
610
|
});
|
|
566
611
|
return transformer(tree, {});
|
package/lib/types.d.ts
CHANGED
|
@@ -98,6 +98,7 @@ export interface Image {
|
|
|
98
98
|
type: 'image';
|
|
99
99
|
src: string;
|
|
100
100
|
alt?: string;
|
|
101
|
+
link?: string;
|
|
101
102
|
}
|
|
102
103
|
export interface Toc {
|
|
103
104
|
type: 'toc';
|
|
@@ -139,7 +140,7 @@ export interface RootBlock extends Omit<Block, 'location'> {
|
|
|
139
140
|
}
|
|
140
141
|
export interface ParseDiagnostic {
|
|
141
142
|
severity: 'warning';
|
|
142
|
-
code: 'value-unreadable' | 'directive-unreadable';
|
|
143
|
+
code: 'value-unreadable' | 'directive-unreadable' | 'table-row-cells' | 'table-cell-outside-row' | 'table-mixed-separators' | 'table-source-unreadable';
|
|
143
144
|
message: string;
|
|
144
145
|
location: Location;
|
|
145
146
|
}
|
|
@@ -364,7 +365,7 @@ export interface BlockTable extends Omit<Block, 'content'> {
|
|
|
364
365
|
export interface TableCell {
|
|
365
366
|
name: 'cell';
|
|
366
367
|
type: 'block';
|
|
367
|
-
content: Array<
|
|
368
|
+
content: Array<PodNode>;
|
|
368
369
|
}
|
|
369
370
|
export interface TableRow {
|
|
370
371
|
name: 'row';
|
package/lib/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const version = "0.0.
|
|
1
|
+
export declare const version = "0.0.66";
|
package/lib/version.js
CHANGED
package/package.json
CHANGED
package/schema/AstTree.json
CHANGED
|
@@ -1348,6 +1348,10 @@
|
|
|
1348
1348
|
"code": {
|
|
1349
1349
|
"enum": [
|
|
1350
1350
|
"directive-unreadable",
|
|
1351
|
+
"table-cell-outside-row",
|
|
1352
|
+
"table-mixed-separators",
|
|
1353
|
+
"table-row-cells",
|
|
1354
|
+
"table-source-unreadable",
|
|
1351
1355
|
"value-unreadable"
|
|
1352
1356
|
],
|
|
1353
1357
|
"type": "string"
|
|
@@ -1378,6 +1382,9 @@
|
|
|
1378
1382
|
},
|
|
1379
1383
|
"alt": {
|
|
1380
1384
|
"type": "string"
|
|
1385
|
+
},
|
|
1386
|
+
"link": {
|
|
1387
|
+
"type": "string"
|
|
1381
1388
|
}
|
|
1382
1389
|
},
|
|
1383
1390
|
"required": [
|
|
@@ -1529,7 +1536,7 @@
|
|
|
1529
1536
|
"content": {
|
|
1530
1537
|
"type": "array",
|
|
1531
1538
|
"items": {
|
|
1532
|
-
"
|
|
1539
|
+
"$ref": "#/definitions/PodNode"
|
|
1533
1540
|
}
|
|
1534
1541
|
}
|
|
1535
1542
|
},
|
|
@@ -1348,6 +1348,10 @@
|
|
|
1348
1348
|
"code": {
|
|
1349
1349
|
"enum": [
|
|
1350
1350
|
"directive-unreadable",
|
|
1351
|
+
"table-cell-outside-row",
|
|
1352
|
+
"table-mixed-separators",
|
|
1353
|
+
"table-row-cells",
|
|
1354
|
+
"table-source-unreadable",
|
|
1351
1355
|
"value-unreadable"
|
|
1352
1356
|
],
|
|
1353
1357
|
"type": "string"
|
|
@@ -1378,6 +1382,9 @@
|
|
|
1378
1382
|
},
|
|
1379
1383
|
"alt": {
|
|
1380
1384
|
"type": "string"
|
|
1385
|
+
},
|
|
1386
|
+
"link": {
|
|
1387
|
+
"type": "string"
|
|
1381
1388
|
}
|
|
1382
1389
|
},
|
|
1383
1390
|
"required": [
|
|
@@ -1529,7 +1536,7 @@
|
|
|
1529
1536
|
"content": {
|
|
1530
1537
|
"type": "array",
|
|
1531
1538
|
"items": {
|
|
1532
|
-
"
|
|
1539
|
+
"$ref": "#/definitions/PodNode"
|
|
1533
1540
|
}
|
|
1534
1541
|
}
|
|
1535
1542
|
},
|