@quarto/jupyterlab-quarto 0.1.44 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +1 -1
- package/README.md +48 -15
- package/lib/__tests__/jupyterlab_quarto.spec.d.ts +3 -0
- package/lib/__tests__/jupyterlab_quarto.spec.js +9 -0
- package/lib/ast/ast.d.ts +2 -0
- package/lib/ast/ast.js +40 -0
- package/lib/const.d.ts +4 -0
- package/lib/const.js +11 -0
- package/lib/hooks/codemirror.d.ts +5 -0
- package/lib/hooks/codemirror.js +77 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +61 -0
- package/lib/manager.d.ts +8 -0
- package/lib/manager.js +115 -0
- package/lib/plugins/callouts.d.ts +2 -0
- package/lib/plugins/callouts.js +210 -0
- package/lib/plugins/cites.d.ts +2 -0
- package/lib/plugins/cites.js +166 -0
- package/lib/plugins/decorator.d.ts +2 -0
- package/lib/plugins/decorator.js +58 -0
- package/lib/plugins/divs.d.ts +5 -0
- package/lib/plugins/divs.js +111 -0
- package/lib/plugins/figure-divs.d.ts +2 -0
- package/lib/plugins/figure-divs.js +54 -0
- package/lib/plugins/figures.d.ts +16 -0
- package/lib/plugins/figures.js +98 -0
- package/lib/plugins/gridtables/common/gridtables/GetCells.d.ts +7 -0
- package/lib/plugins/gridtables/common/gridtables/GetCells.js +43 -0
- package/lib/plugins/gridtables/common/gridtables/GetColumnWidths.d.ts +7 -0
- package/lib/plugins/gridtables/common/gridtables/GetColumnWidths.js +22 -0
- package/lib/plugins/gridtables/common/markdown-it/ColumnAlignments.d.ts +7 -0
- package/lib/plugins/gridtables/common/markdown-it/ColumnAlignments.js +12 -0
- package/lib/plugins/gridtables/common/markdown-it/EmitTable.d.ts +4 -0
- package/lib/plugins/gridtables/common/markdown-it/EmitTable.js +64 -0
- package/lib/plugins/gridtables/common/markdown-it/GetCharCodeAtStartOfLine.d.ts +8 -0
- package/lib/plugins/gridtables/common/markdown-it/GetCharCodeAtStartOfLine.js +17 -0
- package/lib/plugins/gridtables/common/markdown-it/GetLine.d.ts +2 -0
- package/lib/plugins/gridtables/common/markdown-it/GetLine.js +9 -0
- package/lib/plugins/gridtables/common/markdown-it/ParseTable.d.ts +3 -0
- package/lib/plugins/gridtables/common/markdown-it/ParseTable.js +152 -0
- package/lib/plugins/gridtables/common/markdown-it/ParseTableResult.d.ts +12 -0
- package/lib/plugins/gridtables/common/markdown-it/ParseTableResult.js +17 -0
- package/lib/plugins/gridtables/index.d.ts +1 -0
- package/lib/plugins/gridtables/index.js +10 -0
- package/lib/plugins/gridtables/interfaces/markdown-it/IState.d.ts +10 -0
- package/lib/plugins/gridtables/interfaces/markdown-it/IState.js +5 -0
- package/lib/plugins/gridtables/interfaces/markdown-it/IToken.d.ts +6 -0
- package/lib/plugins/gridtables/interfaces/markdown-it/IToken.js +5 -0
- package/lib/plugins/gridtables/interfaces/markdown-it/TRuleFunction.d.ts +3 -0
- package/lib/plugins/gridtables/interfaces/markdown-it/TRuleFunction.js +5 -0
- package/lib/plugins/gridtables/rules/gridtable.d.ts +3 -0
- package/lib/plugins/gridtables/rules/gridtable.js +25 -0
- package/lib/plugins/index.d.ts +15 -0
- package/lib/plugins/index.js +21 -0
- package/lib/plugins/math.d.ts +6 -0
- package/lib/plugins/math.js +179 -0
- package/lib/plugins/mermaid/index.d.ts +4 -0
- package/lib/plugins/mermaid/index.js +60 -0
- package/lib/plugins/shortcodes.d.ts +3 -0
- package/lib/plugins/shortcodes.js +32 -0
- package/lib/plugins/spans.d.ts +2 -0
- package/lib/plugins/spans.js +37 -0
- package/lib/plugins/table-captions.d.ts +2 -0
- package/lib/plugins/table-captions.js +72 -0
- package/lib/plugins/utils/html.d.ts +11 -0
- package/lib/plugins/utils/html.js +50 -0
- package/lib/plugins/utils/markdownit.d.ts +15 -0
- package/lib/plugins/utils/markdownit.js +46 -0
- package/lib/plugins/utils/tok.d.ts +7 -0
- package/lib/plugins/utils/tok.js +13 -0
- package/lib/plugins/yaml.d.ts +2 -0
- package/lib/plugins/yaml.js +330 -0
- package/lib/providers/attrs.d.ts +1 -0
- package/lib/providers/attrs.js +15 -0
- package/lib/providers/callouts.d.ts +1 -0
- package/lib/providers/callouts.js +15 -0
- package/lib/providers/cites.d.ts +1 -0
- package/lib/providers/cites.js +15 -0
- package/lib/providers/decorator.d.ts +1 -0
- package/lib/providers/decorator.js +15 -0
- package/lib/providers/deflist.d.ts +1 -0
- package/lib/providers/deflist.js +15 -0
- package/lib/providers/divs.d.ts +1 -0
- package/lib/providers/divs.js +27 -0
- package/lib/providers/figure-divs.d.ts +1 -0
- package/lib/providers/figure-divs.js +15 -0
- package/lib/providers/figures.d.ts +1 -0
- package/lib/providers/figures.js +15 -0
- package/lib/providers/footnotes.d.ts +1 -0
- package/lib/providers/footnotes.js +15 -0
- package/lib/providers/gridtables.d.ts +1 -0
- package/lib/providers/gridtables.js +15 -0
- package/lib/providers/math.d.ts +1 -0
- package/lib/providers/math.js +104 -0
- package/lib/providers/mermaid.d.ts +1 -0
- package/lib/providers/mermaid.js +17 -0
- package/lib/providers/provider.d.ts +3 -0
- package/lib/providers/provider.js +12 -0
- package/lib/providers/shortcodes.d.ts +1 -0
- package/lib/providers/shortcodes.js +15 -0
- package/lib/providers/spans.d.ts +1 -0
- package/lib/providers/spans.js +15 -0
- package/lib/providers/sub.d.ts +1 -0
- package/lib/providers/sub.js +15 -0
- package/lib/providers/sup.d.ts +1 -0
- package/lib/providers/sup.js +15 -0
- package/lib/providers/table-captions.d.ts +1 -0
- package/lib/providers/table-captions.js +15 -0
- package/lib/providers/tasklists.d.ts +1 -0
- package/lib/providers/tasklists.js +15 -0
- package/lib/providers/yaml.d.ts +1 -0
- package/lib/providers/yaml.js +15 -0
- package/lib/types.d.ts +43 -0
- package/lib/types.js +1 -0
- package/lib/widgets.d.ts +14 -0
- package/lib/widgets.js +57 -0
- package/package.json +105 -39
- package/style/base.css +34 -33
- package/style/index.css +1 -1
- package/schema/plugin.json +0 -8
- package/src/@types/markdown-it-deflist.d.ts +0 -10
- package/src/@types/markdown-it-footnote.d.ts +0 -10
- package/src/@types/markdown-it-gridtables.d.ts +0 -10
- package/src/@types/markdown-it-implicit-figures.d.ts +0 -10
- package/src/@types/markdown-it-sub.d.ts +0 -10
- package/src/@types/markdown-it-sup.d.ts +0 -10
- package/src/@types/markdown-it-task-lists.d.ts +0 -10
@@ -0,0 +1,98 @@
|
|
1
|
+
/*
|
2
|
+
* figures.ts
|
3
|
+
*
|
4
|
+
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
import { kTokParaClose, kTokParaOpen } from './utils/tok';
|
8
|
+
export const kTokFigureOpen = 'figure_open';
|
9
|
+
export const kTokFigureClose = 'figure_close';
|
10
|
+
export const kTokFigCaptionOpen = 'figcaption_open';
|
11
|
+
export const kTokFigCaptionClose = 'figcaption_close';
|
12
|
+
export const mutateToFigureTok = (token, type) => {
|
13
|
+
token.type = type === 'open' ? kTokFigureOpen : kTokFigureClose;
|
14
|
+
token.tag = 'figure';
|
15
|
+
};
|
16
|
+
export function figuresPlugin(md, options) {
|
17
|
+
options = options || {};
|
18
|
+
md.core.ruler.before('linkify', 'implicit_figures', state => {
|
19
|
+
// reset tabIndex on md.render()
|
20
|
+
let tabIndex = 1;
|
21
|
+
// do not process first and last token
|
22
|
+
for (let i = 1, l = state.tokens.length; i < l - 1; ++i) {
|
23
|
+
const token = state.tokens[i];
|
24
|
+
if (token.type !== 'inline') {
|
25
|
+
continue;
|
26
|
+
}
|
27
|
+
// children: image alone, or link_open -> image -> link_close
|
28
|
+
if (!token.children ||
|
29
|
+
(token.children.length !== 1 && token.children.length !== 3)) {
|
30
|
+
continue;
|
31
|
+
}
|
32
|
+
// one child, should be img
|
33
|
+
if (token.children.length === 1 && token.children[0].type !== 'image') {
|
34
|
+
continue;
|
35
|
+
}
|
36
|
+
// three children, should be image enclosed in link
|
37
|
+
if (token.children.length === 3 &&
|
38
|
+
(token.children[0].type !== 'link_open' ||
|
39
|
+
token.children[1].type !== 'image' ||
|
40
|
+
token.children[2].type !== 'link_close')) {
|
41
|
+
continue;
|
42
|
+
}
|
43
|
+
// prev token is paragraph open
|
44
|
+
if (i !== 0 && state.tokens[i - 1].type !== kTokParaOpen) {
|
45
|
+
continue;
|
46
|
+
}
|
47
|
+
// next token is paragraph close
|
48
|
+
if (i !== l - 1 && state.tokens[i + 1].type !== kTokParaClose) {
|
49
|
+
continue;
|
50
|
+
}
|
51
|
+
// The image
|
52
|
+
const image = token.children.length === 1 ? token.children[0] : token.children[1];
|
53
|
+
// The image must have a caption to count as a figure
|
54
|
+
if (!image.children || image.children.length === 0) {
|
55
|
+
continue;
|
56
|
+
}
|
57
|
+
// We have inline token containing an image only.
|
58
|
+
// Previous token is paragraph open.
|
59
|
+
// Next token is paragraph close.
|
60
|
+
// Lets replace the paragraph tokens with figure tokens.
|
61
|
+
const figure = state.tokens[i - 1];
|
62
|
+
mutateToFigureTok(figure, 'open');
|
63
|
+
mutateToFigureTok(state.tokens[i + 1], 'close');
|
64
|
+
if (options.dataType === true) {
|
65
|
+
state.tokens[i - 1].attrPush(['data-type', 'image']);
|
66
|
+
}
|
67
|
+
if (options.link === true && token.children.length === 1) {
|
68
|
+
token.children.unshift(new state.Token('link_open', 'a', 1));
|
69
|
+
const src = image.attrGet('src');
|
70
|
+
if (src !== null) {
|
71
|
+
token.children[0].attrPush(['href', src]);
|
72
|
+
}
|
73
|
+
token.children.push(new state.Token('link_close', 'a', -1));
|
74
|
+
}
|
75
|
+
if (options.figcaption === true) {
|
76
|
+
if (image.children && image.children.length) {
|
77
|
+
token.children.push(new state.Token(kTokFigCaptionOpen, 'figcaption', 1));
|
78
|
+
token.children.splice(token.children.length, 0, ...image.children);
|
79
|
+
token.children.push(new state.Token(kTokFigCaptionClose, 'figcaption', -1));
|
80
|
+
image.children.length = 0;
|
81
|
+
}
|
82
|
+
}
|
83
|
+
if (options.copyAttrs && image.attrs) {
|
84
|
+
const f = options.copyAttrs === true ? '' : options.copyAttrs;
|
85
|
+
figure.attrs = image.attrs.filter(([k]) => k.match(f));
|
86
|
+
}
|
87
|
+
if (options.tabindex === true) {
|
88
|
+
// add a tabindex property
|
89
|
+
// you could use this with css-tricks.com/expanding-images-html5
|
90
|
+
state.tokens[i - 1].attrPush(['tabindex', String(tabIndex)]);
|
91
|
+
tabIndex++;
|
92
|
+
}
|
93
|
+
if (options.lazyLoading === true) {
|
94
|
+
image.attrPush(['loading', 'lazy']);
|
95
|
+
}
|
96
|
+
}
|
97
|
+
});
|
98
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
/**
|
6
|
+
* getCells parses the lines found for a certain row, and transforms these to
|
7
|
+
* the separate cell lines.
|
8
|
+
*
|
9
|
+
* @param lines The lines for the row.
|
10
|
+
*/
|
11
|
+
export default function getCells(lines) {
|
12
|
+
const cells = [];
|
13
|
+
for (let i = 0; i < lines[0].length; i++) {
|
14
|
+
let cell = [];
|
15
|
+
for (let j = 0; j < lines.length; j++) {
|
16
|
+
const s = trimEnd(lines[j][i]);
|
17
|
+
if (s.length === 0 && cell.length === 0) {
|
18
|
+
// skip leading empty lines
|
19
|
+
continue;
|
20
|
+
}
|
21
|
+
cell.push(s);
|
22
|
+
}
|
23
|
+
// remove trailing empty lines
|
24
|
+
let j = cell.length - 1;
|
25
|
+
for (; j >= 0; j--) {
|
26
|
+
if (cell[j].length > 0) {
|
27
|
+
break;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
if (j < cell.length - 1) {
|
31
|
+
cell = cell.slice(0, j + 1);
|
32
|
+
}
|
33
|
+
cells.push(cell);
|
34
|
+
}
|
35
|
+
return cells;
|
36
|
+
}
|
37
|
+
function trimEnd(s) {
|
38
|
+
const trimmed = s.trim();
|
39
|
+
if (trimmed.length === 0) {
|
40
|
+
return '';
|
41
|
+
}
|
42
|
+
return s.slice(0, s.indexOf(trimmed) + trimmed.length);
|
43
|
+
}
|
@@ -0,0 +1,7 @@
|
|
1
|
+
/**
|
2
|
+
* getColumnWidths parses the provided line and returns the associated column widths.
|
3
|
+
*
|
4
|
+
* @param line The separator line to parse for the column widths.
|
5
|
+
* @returns The column widths for the provided line, or an empty array if the line is invalid.
|
6
|
+
*/
|
7
|
+
export default function getColumnWidths(line: string): number[];
|
@@ -0,0 +1,22 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
/**
|
6
|
+
* getColumnWidths parses the provided line and returns the associated column widths.
|
7
|
+
*
|
8
|
+
* @param line The separator line to parse for the column widths.
|
9
|
+
* @returns The column widths for the provided line, or an empty array if the line is invalid.
|
10
|
+
*/
|
11
|
+
export default function getColumnWidths(line) {
|
12
|
+
// try to parse as a row separator line
|
13
|
+
let columnMatch = line.substr(1).match(/[:-][-]+[:-]\+/g);
|
14
|
+
if (columnMatch === null) {
|
15
|
+
// try to parse as a header separator line
|
16
|
+
columnMatch = line.substr(1).match(/[:=][=]+[:=]\+/g);
|
17
|
+
}
|
18
|
+
if (columnMatch === null) {
|
19
|
+
return [];
|
20
|
+
}
|
21
|
+
return columnMatch.map(s => s.length);
|
22
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
var ColumnAlignments;
|
6
|
+
(function (ColumnAlignments) {
|
7
|
+
ColumnAlignments["None"] = "";
|
8
|
+
ColumnAlignments["Left"] = "left";
|
9
|
+
ColumnAlignments["Center"] = "center";
|
10
|
+
ColumnAlignments["Right"] = "right";
|
11
|
+
})(ColumnAlignments || (ColumnAlignments = {}));
|
12
|
+
export default ColumnAlignments;
|
@@ -0,0 +1,64 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
import getCells from '../gridtables/GetCells';
|
6
|
+
import ColumnAlignments from './ColumnAlignments';
|
7
|
+
export default function emitTable(md, state, result) {
|
8
|
+
let offsets = result.SeparatorLineOffsets;
|
9
|
+
let token = state.push('table_open', 'table', 1);
|
10
|
+
token.map = [offsets[0], offsets[offsets.length - 1]];
|
11
|
+
if (result.HeaderLines.length > 0) {
|
12
|
+
// emit table header
|
13
|
+
const token = state.push('thead_open', 'thead', 1);
|
14
|
+
token.map = [offsets[0], offsets[1]];
|
15
|
+
const cells = getCells(result.HeaderLines);
|
16
|
+
processRow(md, state, 'th', result.ColumnAlignments, offsets[0], offsets[1], cells);
|
17
|
+
state.push('thead_close', 'thead', -1);
|
18
|
+
offsets = offsets.slice(1);
|
19
|
+
}
|
20
|
+
// emit table body
|
21
|
+
token = state.push('tbody_open', 'tbody', 1);
|
22
|
+
token.map = [offsets[0], offsets[offsets.length - 1]];
|
23
|
+
for (let i = 0; i < result.RowLines.length; i++) {
|
24
|
+
const cells = getCells(result.RowLines[i]);
|
25
|
+
processRow(md, state, 'td', result.ColumnAlignments, offsets[i], offsets[i + 1], cells);
|
26
|
+
}
|
27
|
+
state.push('tbody_close', 'tbody', -1);
|
28
|
+
state.push('table_close', 'table', -1);
|
29
|
+
}
|
30
|
+
function processRow(md, state, tag, columnAlignments, lineBegin, lineEnd, cells) {
|
31
|
+
const token = state.push('tr_open', 'tr', 1);
|
32
|
+
token.map = [lineBegin, lineEnd];
|
33
|
+
for (let i = 0; i < cells.length; i++) {
|
34
|
+
const token = state.push(tag + '_open', tag, 1);
|
35
|
+
token.map = [lineBegin + 1, lineEnd - 1];
|
36
|
+
if (columnAlignments[i] !== ColumnAlignments.None) {
|
37
|
+
token.attrSet('style', `text-align: ${columnAlignments[i]};`);
|
38
|
+
}
|
39
|
+
if (cells[i].length === 0) {
|
40
|
+
// empty cell
|
41
|
+
}
|
42
|
+
else if (cells[i].length === 1) {
|
43
|
+
// single line cell -> emit as inline markdown
|
44
|
+
const token = state.push('inline', '', 0);
|
45
|
+
token.content = cells[i][0].trim();
|
46
|
+
token.children = [];
|
47
|
+
}
|
48
|
+
else {
|
49
|
+
// multi line cell -> render and emit as html
|
50
|
+
let cell = md.render(cells[i].join('\r\n')).trim();
|
51
|
+
// remove single p tag because we're in a table cell
|
52
|
+
if (cell.slice(0, 3) === '<p>' &&
|
53
|
+
cell.slice(-4) === '</p>' &&
|
54
|
+
cell.indexOf('<p>', 3) === -1) {
|
55
|
+
cell = cell.slice(3, cell.length - 4);
|
56
|
+
}
|
57
|
+
const token = state.push('html_block', '', 0);
|
58
|
+
token.content = cell;
|
59
|
+
token.children = [];
|
60
|
+
}
|
61
|
+
state.push(tag + '_close', tag, -1);
|
62
|
+
}
|
63
|
+
state.push('tr_close', 'tr', -1);
|
64
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import IState from '../../interfaces/markdown-it/IState';
|
2
|
+
/**
|
3
|
+
* Returns the char code of the character at the start of the current line,
|
4
|
+
* or -1 if this is not available (e.g. on an empty line).
|
5
|
+
*
|
6
|
+
* @param state The Markdown It state.
|
7
|
+
*/
|
8
|
+
export default function getCharCodeAtStartOfLine(state: IState, line: number): number;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
/**
|
6
|
+
* Returns the char code of the character at the start of the current line,
|
7
|
+
* or -1 if this is not available (e.g. on an empty line).
|
8
|
+
*
|
9
|
+
* @param state The Markdown It state.
|
10
|
+
*/
|
11
|
+
export default function getCharCodeAtStartOfLine(state, line) {
|
12
|
+
const pos = state.bMarks[line] + state.tShift[line];
|
13
|
+
if (pos >= state.eMarks[line]) {
|
14
|
+
return -1;
|
15
|
+
}
|
16
|
+
return state.src.charCodeAt(pos);
|
17
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
export default function getLine(state, line) {
|
6
|
+
const start = state.bMarks[line] + state.blkIndent;
|
7
|
+
const end = state.eMarks[line];
|
8
|
+
return state.src.substr(start, end - start);
|
9
|
+
}
|
@@ -0,0 +1,152 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
import wcwidth from 'wcwidth';
|
6
|
+
import getColumnWidths from '../gridtables/GetColumnWidths';
|
7
|
+
import ColumnAlignments from './ColumnAlignments';
|
8
|
+
import getLine from './GetLine';
|
9
|
+
import ParseTableResult from './ParseTableResult';
|
10
|
+
export default function parseTable(state, startLine, endLine) {
|
11
|
+
const result = new ParseTableResult();
|
12
|
+
let rowLine = getLine(state, startLine);
|
13
|
+
if (rowLine.charAt(0) !== '+') {
|
14
|
+
// line does not start with a '+'
|
15
|
+
return result;
|
16
|
+
}
|
17
|
+
result.ColumnWidths = getColumnWidths(rowLine);
|
18
|
+
if (result.ColumnWidths.length === 0) {
|
19
|
+
// no columns found
|
20
|
+
return result;
|
21
|
+
}
|
22
|
+
// initialize column alignments
|
23
|
+
result.ColumnAlignments = result.ColumnWidths.map(() => ColumnAlignments.None);
|
24
|
+
if (rowLine.indexOf(':') >= 0) {
|
25
|
+
// column alignment specifiers present in first row line
|
26
|
+
result.HeaderLess = true;
|
27
|
+
// set column alignments
|
28
|
+
result.ColumnAlignments = getColumnAlignments(rowLine, result.ColumnWidths);
|
29
|
+
// remove alignment specifiers for further matching
|
30
|
+
rowLine = rowLine.replace(/[:]/g, '-');
|
31
|
+
}
|
32
|
+
// create header line matcher
|
33
|
+
const headerLineMatcher = new RegExp('^\\+' +
|
34
|
+
result.ColumnWidths.map(w => `[=:][=]{${w - 3}}[=:]\\+`).join('') +
|
35
|
+
'$');
|
36
|
+
// build column offsets
|
37
|
+
result.ColumnOffsets = [0];
|
38
|
+
for (let i = 0; i < result.ColumnWidths.length - 1; i++) {
|
39
|
+
result.ColumnOffsets.push(result.ColumnOffsets[i] + result.ColumnWidths[i]);
|
40
|
+
}
|
41
|
+
// create cell line matcher
|
42
|
+
const cellLineMatcher = new RegExp('^\\|' +
|
43
|
+
result.ColumnWidths.map(w => `([^|]{${Math.ceil((w - 1) / 2)},${w - 1}})\\|`).join('') +
|
44
|
+
'$');
|
45
|
+
// save first separator line offset
|
46
|
+
result.SeparatorLineOffsets.push(startLine);
|
47
|
+
// continue to scan until a complete table is found, or an invalid line is encountered
|
48
|
+
let currentRow = [];
|
49
|
+
let currentLine = startLine + 1;
|
50
|
+
for (; currentLine <= endLine; currentLine++) {
|
51
|
+
const line = getLine(state, currentLine);
|
52
|
+
if (line.charCodeAt(0) === 0x2b) {
|
53
|
+
// '+'
|
54
|
+
// separator line
|
55
|
+
if (currentRow.length === 0) {
|
56
|
+
// no row lines since last separator -> invalid table
|
57
|
+
return result;
|
58
|
+
}
|
59
|
+
// save separator line offset
|
60
|
+
result.SeparatorLineOffsets.push(currentLine);
|
61
|
+
if (line === rowLine) {
|
62
|
+
// new regular row
|
63
|
+
result.RowLines.push(currentRow);
|
64
|
+
if (result.HeaderLines.length === 0) {
|
65
|
+
result.HeaderLess = true;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
else if (!result.HeaderLess && line.match(headerLineMatcher)) {
|
69
|
+
// found header line
|
70
|
+
if (result.HeaderLines.length > 0 || result.RowLines.length > 0) {
|
71
|
+
// header already found, or not the first row -> invalid table
|
72
|
+
return result;
|
73
|
+
}
|
74
|
+
// header row
|
75
|
+
result.HeaderLines = currentRow;
|
76
|
+
if (line.indexOf(':') >= 0) {
|
77
|
+
// set column alignments
|
78
|
+
result.ColumnAlignments = getColumnAlignments(line, result.ColumnWidths);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
else {
|
82
|
+
// not a header or regular row -> invalid table
|
83
|
+
return result;
|
84
|
+
}
|
85
|
+
// reset current row
|
86
|
+
currentRow = [];
|
87
|
+
}
|
88
|
+
else if (line.charCodeAt(0) === 0x7c) {
|
89
|
+
// '|'
|
90
|
+
// cell line
|
91
|
+
const matches = line.match(cellLineMatcher);
|
92
|
+
if (matches === null) {
|
93
|
+
// cell line does not match -> invalid table
|
94
|
+
return result;
|
95
|
+
}
|
96
|
+
const cells = validateColumnWidths(matches, result.ColumnWidths);
|
97
|
+
if (cells === null) {
|
98
|
+
// cell line does not match -> invalid table
|
99
|
+
return result;
|
100
|
+
}
|
101
|
+
// add the line to the current row
|
102
|
+
currentRow.push(cells);
|
103
|
+
}
|
104
|
+
else {
|
105
|
+
// not a separator or cell line, check if we have a complete table
|
106
|
+
if (currentRow.length === 0 &&
|
107
|
+
(result.HeaderLines.length > 0 || result.RowLines.length > 0)) {
|
108
|
+
// found a complete table
|
109
|
+
break;
|
110
|
+
}
|
111
|
+
return result;
|
112
|
+
}
|
113
|
+
}
|
114
|
+
result.CurrentLine = currentLine;
|
115
|
+
result.Success = true;
|
116
|
+
return result;
|
117
|
+
}
|
118
|
+
function getColumnAlignments(line, columnWidths) {
|
119
|
+
const alignments = [];
|
120
|
+
let left = 1;
|
121
|
+
let right = -1;
|
122
|
+
for (let i = 0; i < columnWidths.length; i++) {
|
123
|
+
right += columnWidths[i];
|
124
|
+
let alignment = ColumnAlignments.None;
|
125
|
+
if (line.charAt(right) === ':') {
|
126
|
+
if (line.charAt(left) === ':') {
|
127
|
+
alignment = ColumnAlignments.Center;
|
128
|
+
}
|
129
|
+
else {
|
130
|
+
alignment = ColumnAlignments.Right;
|
131
|
+
}
|
132
|
+
}
|
133
|
+
else if (line.charAt(left) === ':') {
|
134
|
+
alignment = ColumnAlignments.Left;
|
135
|
+
}
|
136
|
+
alignments.push(alignment);
|
137
|
+
left += columnWidths[i];
|
138
|
+
}
|
139
|
+
return alignments;
|
140
|
+
}
|
141
|
+
function validateColumnWidths(matches, columnWidths) {
|
142
|
+
const cells = [];
|
143
|
+
for (let i = 0; i < columnWidths.length; i++) {
|
144
|
+
const cell = matches[i + 1];
|
145
|
+
const columnWidth = wcwidth(cell) + 1; // add 1 for separator
|
146
|
+
if (columnWidth !== columnWidths[i]) {
|
147
|
+
return null;
|
148
|
+
}
|
149
|
+
cells.push(cell);
|
150
|
+
}
|
151
|
+
return cells;
|
152
|
+
}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import ColumnAlignments from './ColumnAlignments';
|
2
|
+
export default class ParseTableResult {
|
3
|
+
Success: boolean;
|
4
|
+
ColumnWidths: number[];
|
5
|
+
ColumnOffsets: number[];
|
6
|
+
ColumnAlignments: ColumnAlignments[];
|
7
|
+
HeaderLess: boolean;
|
8
|
+
HeaderLines: string[][];
|
9
|
+
RowLines: string[][][];
|
10
|
+
SeparatorLineOffsets: number[];
|
11
|
+
CurrentLine: number;
|
12
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
export default class ParseTableResult {
|
6
|
+
constructor() {
|
7
|
+
this.Success = false;
|
8
|
+
this.ColumnWidths = [];
|
9
|
+
this.ColumnOffsets = [];
|
10
|
+
this.ColumnAlignments = [];
|
11
|
+
this.HeaderLess = false;
|
12
|
+
this.HeaderLines = [];
|
13
|
+
this.RowLines = [];
|
14
|
+
this.SeparatorLineOffsets = [];
|
15
|
+
this.CurrentLine = 0;
|
16
|
+
}
|
17
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export default function gridTableRulePlugin(md: any): void;
|
@@ -0,0 +1,10 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
import gridTableRule from './rules/gridtable';
|
6
|
+
export default function gridTableRulePlugin(
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
8
|
+
md) {
|
9
|
+
md.block.ruler.before('table', 'gridtable', gridTableRule(md));
|
10
|
+
}
|
@@ -0,0 +1,5 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
export {};
|
@@ -0,0 +1,5 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
export {};
|
@@ -0,0 +1,5 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
export {};
|
@@ -0,0 +1,25 @@
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
2
|
+
* Copyright (c) Bas Verweij. All rights reserved.
|
3
|
+
* Licensed under the MIT License. See LICENSE in the project root for license information.
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
5
|
+
import emitTable from '../common/markdown-it/EmitTable';
|
6
|
+
import getCharCodeAtStartOfLine from '../common/markdown-it/GetCharCodeAtStartOfLine';
|
7
|
+
import parseTable from '../common/markdown-it/ParseTable';
|
8
|
+
export default function gridTableRule(md) {
|
9
|
+
return function (state, startLine, endLine, silent) {
|
10
|
+
if (getCharCodeAtStartOfLine(state, startLine) !== 0x2b) {
|
11
|
+
// line does not start with a '+'
|
12
|
+
return false;
|
13
|
+
}
|
14
|
+
const parseResult = parseTable(state, startLine, endLine);
|
15
|
+
if (!parseResult.Success) {
|
16
|
+
return false;
|
17
|
+
}
|
18
|
+
if (silent) {
|
19
|
+
return true;
|
20
|
+
}
|
21
|
+
emitTable(md, state, parseResult);
|
22
|
+
state.line = parseResult.CurrentLine;
|
23
|
+
return true;
|
24
|
+
};
|
25
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
import gridTableRulePlugin from './gridtables';
|
2
|
+
export { gridTableRulePlugin };
|
3
|
+
import mermaidPlugin from './mermaid';
|
4
|
+
export { mermaidPlugin };
|
5
|
+
export * from './callouts';
|
6
|
+
export * from './cites';
|
7
|
+
export * from './decorator';
|
8
|
+
export * from './divs';
|
9
|
+
export * from './figure-divs';
|
10
|
+
export * from './figures';
|
11
|
+
export * from './math';
|
12
|
+
export * from './shortcodes';
|
13
|
+
export * from './spans';
|
14
|
+
export * from './table-captions';
|
15
|
+
export * from './yaml';
|
@@ -0,0 +1,21 @@
|
|
1
|
+
/*
|
2
|
+
* index.ts
|
3
|
+
*
|
4
|
+
* Copyright (C) 2020-2023 Posit Software, PBC
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
import gridTableRulePlugin from './gridtables';
|
8
|
+
export { gridTableRulePlugin };
|
9
|
+
import mermaidPlugin from './mermaid';
|
10
|
+
export { mermaidPlugin };
|
11
|
+
export * from './callouts';
|
12
|
+
export * from './cites';
|
13
|
+
export * from './decorator';
|
14
|
+
export * from './divs';
|
15
|
+
export * from './figure-divs';
|
16
|
+
export * from './figures';
|
17
|
+
export * from './math';
|
18
|
+
export * from './shortcodes';
|
19
|
+
export * from './spans';
|
20
|
+
export * from './table-captions';
|
21
|
+
export * from './yaml';
|