@quarto/jupyterlab-quarto 0.1.44 → 0.2.3

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.
Files changed (127) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +48 -15
  3. package/lib/__tests__/jupyterlab_quarto.spec.d.ts +3 -0
  4. package/lib/__tests__/jupyterlab_quarto.spec.js +9 -0
  5. package/lib/ast/ast.d.ts +2 -0
  6. package/lib/ast/ast.js +40 -0
  7. package/lib/const.d.ts +4 -0
  8. package/lib/const.js +11 -0
  9. package/lib/hooks/codemirror.d.ts +5 -0
  10. package/lib/hooks/codemirror.js +77 -0
  11. package/lib/index.d.ts +5 -0
  12. package/lib/index.js +61 -0
  13. package/lib/manager.d.ts +8 -0
  14. package/lib/manager.js +115 -0
  15. package/lib/plugins/callouts.d.ts +2 -0
  16. package/lib/plugins/callouts.js +210 -0
  17. package/lib/plugins/cites.d.ts +2 -0
  18. package/lib/plugins/cites.js +166 -0
  19. package/lib/plugins/decorator.d.ts +2 -0
  20. package/lib/plugins/decorator.js +58 -0
  21. package/lib/plugins/divs.d.ts +5 -0
  22. package/lib/plugins/divs.js +111 -0
  23. package/lib/plugins/figure-divs.d.ts +2 -0
  24. package/lib/plugins/figure-divs.js +54 -0
  25. package/lib/plugins/figures.d.ts +16 -0
  26. package/lib/plugins/figures.js +98 -0
  27. package/lib/plugins/gridtables/common/gridtables/GetCells.d.ts +7 -0
  28. package/lib/plugins/gridtables/common/gridtables/GetCells.js +43 -0
  29. package/lib/plugins/gridtables/common/gridtables/GetColumnWidths.d.ts +7 -0
  30. package/lib/plugins/gridtables/common/gridtables/GetColumnWidths.js +22 -0
  31. package/lib/plugins/gridtables/common/markdown-it/ColumnAlignments.d.ts +7 -0
  32. package/lib/plugins/gridtables/common/markdown-it/ColumnAlignments.js +12 -0
  33. package/lib/plugins/gridtables/common/markdown-it/EmitTable.d.ts +4 -0
  34. package/lib/plugins/gridtables/common/markdown-it/EmitTable.js +64 -0
  35. package/lib/plugins/gridtables/common/markdown-it/GetCharCodeAtStartOfLine.d.ts +8 -0
  36. package/lib/plugins/gridtables/common/markdown-it/GetCharCodeAtStartOfLine.js +17 -0
  37. package/lib/plugins/gridtables/common/markdown-it/GetLine.d.ts +2 -0
  38. package/lib/plugins/gridtables/common/markdown-it/GetLine.js +9 -0
  39. package/lib/plugins/gridtables/common/markdown-it/ParseTable.d.ts +3 -0
  40. package/lib/plugins/gridtables/common/markdown-it/ParseTable.js +152 -0
  41. package/lib/plugins/gridtables/common/markdown-it/ParseTableResult.d.ts +12 -0
  42. package/lib/plugins/gridtables/common/markdown-it/ParseTableResult.js +17 -0
  43. package/lib/plugins/gridtables/index.d.ts +1 -0
  44. package/lib/plugins/gridtables/index.js +10 -0
  45. package/lib/plugins/gridtables/interfaces/markdown-it/IState.d.ts +10 -0
  46. package/lib/plugins/gridtables/interfaces/markdown-it/IState.js +5 -0
  47. package/lib/plugins/gridtables/interfaces/markdown-it/IToken.d.ts +6 -0
  48. package/lib/plugins/gridtables/interfaces/markdown-it/IToken.js +5 -0
  49. package/lib/plugins/gridtables/interfaces/markdown-it/TRuleFunction.d.ts +3 -0
  50. package/lib/plugins/gridtables/interfaces/markdown-it/TRuleFunction.js +5 -0
  51. package/lib/plugins/gridtables/rules/gridtable.d.ts +3 -0
  52. package/lib/plugins/gridtables/rules/gridtable.js +25 -0
  53. package/lib/plugins/index.d.ts +15 -0
  54. package/lib/plugins/index.js +21 -0
  55. package/lib/plugins/math.d.ts +6 -0
  56. package/lib/plugins/math.js +179 -0
  57. package/lib/plugins/mermaid/index.d.ts +4 -0
  58. package/lib/plugins/mermaid/index.js +60 -0
  59. package/lib/plugins/shortcodes.d.ts +3 -0
  60. package/lib/plugins/shortcodes.js +32 -0
  61. package/lib/plugins/spans.d.ts +2 -0
  62. package/lib/plugins/spans.js +37 -0
  63. package/lib/plugins/table-captions.d.ts +2 -0
  64. package/lib/plugins/table-captions.js +72 -0
  65. package/lib/plugins/utils/html.d.ts +11 -0
  66. package/lib/plugins/utils/html.js +50 -0
  67. package/lib/plugins/utils/markdownit.d.ts +15 -0
  68. package/lib/plugins/utils/markdownit.js +46 -0
  69. package/lib/plugins/utils/tok.d.ts +7 -0
  70. package/lib/plugins/utils/tok.js +13 -0
  71. package/lib/plugins/yaml.d.ts +2 -0
  72. package/lib/plugins/yaml.js +330 -0
  73. package/lib/providers/attrs.d.ts +1 -0
  74. package/lib/providers/attrs.js +15 -0
  75. package/lib/providers/callouts.d.ts +1 -0
  76. package/lib/providers/callouts.js +15 -0
  77. package/lib/providers/cites.d.ts +1 -0
  78. package/lib/providers/cites.js +15 -0
  79. package/lib/providers/decorator.d.ts +1 -0
  80. package/lib/providers/decorator.js +15 -0
  81. package/lib/providers/deflist.d.ts +1 -0
  82. package/lib/providers/deflist.js +15 -0
  83. package/lib/providers/divs.d.ts +1 -0
  84. package/lib/providers/divs.js +27 -0
  85. package/lib/providers/figure-divs.d.ts +1 -0
  86. package/lib/providers/figure-divs.js +15 -0
  87. package/lib/providers/figures.d.ts +1 -0
  88. package/lib/providers/figures.js +15 -0
  89. package/lib/providers/footnotes.d.ts +1 -0
  90. package/lib/providers/footnotes.js +15 -0
  91. package/lib/providers/gridtables.d.ts +1 -0
  92. package/lib/providers/gridtables.js +15 -0
  93. package/lib/providers/math.d.ts +1 -0
  94. package/lib/providers/math.js +104 -0
  95. package/lib/providers/mermaid.d.ts +1 -0
  96. package/lib/providers/mermaid.js +17 -0
  97. package/lib/providers/provider.d.ts +3 -0
  98. package/lib/providers/provider.js +12 -0
  99. package/lib/providers/shortcodes.d.ts +1 -0
  100. package/lib/providers/shortcodes.js +15 -0
  101. package/lib/providers/spans.d.ts +1 -0
  102. package/lib/providers/spans.js +15 -0
  103. package/lib/providers/sub.d.ts +1 -0
  104. package/lib/providers/sub.js +15 -0
  105. package/lib/providers/sup.d.ts +1 -0
  106. package/lib/providers/sup.js +15 -0
  107. package/lib/providers/table-captions.d.ts +1 -0
  108. package/lib/providers/table-captions.js +15 -0
  109. package/lib/providers/tasklists.d.ts +1 -0
  110. package/lib/providers/tasklists.js +15 -0
  111. package/lib/providers/yaml.d.ts +1 -0
  112. package/lib/providers/yaml.js +15 -0
  113. package/lib/types.d.ts +43 -0
  114. package/lib/types.js +1 -0
  115. package/lib/widgets.d.ts +14 -0
  116. package/lib/widgets.js +57 -0
  117. package/package.json +105 -39
  118. package/style/base.css +34 -33
  119. package/style/index.css +1 -1
  120. package/schema/plugin.json +0 -8
  121. package/src/@types/markdown-it-deflist.d.ts +0 -10
  122. package/src/@types/markdown-it-footnote.d.ts +0 -10
  123. package/src/@types/markdown-it-gridtables.d.ts +0 -10
  124. package/src/@types/markdown-it-implicit-figures.d.ts +0 -10
  125. package/src/@types/markdown-it-sub.d.ts +0 -10
  126. package/src/@types/markdown-it-sup.d.ts +0 -10
  127. package/src/@types/markdown-it-task-lists.d.ts +0 -10
@@ -0,0 +1,210 @@
1
+ import Token from 'markdown-it/lib/token';
2
+ import { addClass, readAttrValue } from './utils/markdownit';
3
+ import { kTokDivClose, kTokDivOpen } from './divs';
4
+ const kTokCalloutOpen = 'quarto_callout_open';
5
+ const kTokCalloutClose = 'quarto_callout_close';
6
+ const kTokCalloutTitleOpen = 'quarto_callout_title_open';
7
+ const kTokCalloutTitleClose = 'quarto_callout_title_close';
8
+ const kTokCalloutContentOpen = 'quarto_callout_content_open';
9
+ const kTokCalloutContentClose = 'quarto_callout_content_close';
10
+ const kCalloutPrefix = 'callout-';
11
+ const kCalloutRuleName = 'quarto-callouts';
12
+ export const calloutPlugin = (md) => {
13
+ // Handle pandoc-style divs
14
+ md.core.ruler.push(kCalloutRuleName, state => {
15
+ const noteStartCallout = (callout, depth) => {
16
+ if (calloutDepth === -1) {
17
+ calloutDepth = depth;
18
+ }
19
+ state.env['quarto-active-callout'] = callout;
20
+ };
21
+ const noteCloseCallout = () => {
22
+ calloutDepth = -1;
23
+ state.env['quarto-active-callout'] = undefined;
24
+ };
25
+ const activeCallout = () => {
26
+ return state.env['quarto-active-callout'];
27
+ };
28
+ const isCloseCallout = (depth) => {
29
+ return calloutDepth === depth;
30
+ };
31
+ const titleOpenTok = (title) => {
32
+ const token = new Token(kTokCalloutTitleOpen, '', 1);
33
+ token.tag = 'div';
34
+ token.attrs = [['class', 'callout-header']];
35
+ if (title) {
36
+ token.attrs.push(['title', title]);
37
+ }
38
+ return token;
39
+ };
40
+ const titleCloseTok = () => {
41
+ const token = new Token(kTokCalloutTitleClose, '', -1);
42
+ token.tag = 'div';
43
+ return token;
44
+ };
45
+ const contentOpenTok = () => {
46
+ const token = new Token(kTokCalloutContentOpen, '', 1);
47
+ token.tag = 'div';
48
+ token.attrs = [['class', 'callout-body-container callout-body']];
49
+ return token;
50
+ };
51
+ const contentCloseTok = () => {
52
+ const token = new Token(kTokCalloutContentClose, '', -1);
53
+ token.tag = 'div';
54
+ return token;
55
+ };
56
+ const outTokens = [];
57
+ let calloutDepth = -1;
58
+ let divDepth = 0;
59
+ // just started callout - process title
60
+ // finished processing title - process content
61
+ let calloutState = 'scanning';
62
+ for (const token of state.tokens) {
63
+ switch (calloutState) {
64
+ case 'add-title':
65
+ if (token.type === 'heading_open') {
66
+ outTokens.push(titleOpenTok());
67
+ calloutState = 'capturing-title';
68
+ }
69
+ else {
70
+ const callout = activeCallout();
71
+ outTokens.push(titleOpenTok(callout.title));
72
+ outTokens.push(titleCloseTok());
73
+ calloutState = 'add-body';
74
+ }
75
+ break;
76
+ case 'capturing-title':
77
+ if (token.type === 'heading_close') {
78
+ outTokens.push(titleCloseTok());
79
+ calloutState = 'add-body';
80
+ }
81
+ else {
82
+ outTokens.push(token);
83
+ }
84
+ break;
85
+ case 'add-body':
86
+ outTokens.push(contentOpenTok());
87
+ outTokens.push(token);
88
+ calloutState = 'capturing-body';
89
+ break;
90
+ case 'scanning':
91
+ default:
92
+ if (token.type === kTokDivOpen) {
93
+ divDepth++;
94
+ const callout = parseCallout(token.attrs);
95
+ if (callout) {
96
+ noteStartCallout(callout, divDepth);
97
+ calloutState = 'add-title';
98
+ const openCallout = new Token(kTokCalloutOpen, '', 1);
99
+ openCallout.attrs = openCallout.attrs || [];
100
+ openCallout.meta = callout;
101
+ outTokens.push(openCallout);
102
+ }
103
+ else {
104
+ outTokens.push(token);
105
+ }
106
+ }
107
+ else if (token.type === kTokDivClose) {
108
+ if (isCloseCallout(divDepth)) {
109
+ outTokens.push(contentCloseTok());
110
+ outTokens.push(new Token(kTokCalloutClose, '', -1));
111
+ noteCloseCallout();
112
+ }
113
+ else {
114
+ outTokens.push(token);
115
+ }
116
+ divDepth--;
117
+ }
118
+ else {
119
+ outTokens.push(token);
120
+ }
121
+ break;
122
+ }
123
+ }
124
+ state.tokens = outTokens;
125
+ return false;
126
+ });
127
+ md.renderer.rules[kTokCalloutOpen] = renderStartCallout;
128
+ md.renderer.rules[kTokCalloutClose] = renderEndCallout;
129
+ md.renderer.rules[kTokCalloutTitleOpen] = renderStartCalloutTitle;
130
+ md.renderer.rules[kTokCalloutTitleClose] = renderEndCalloutTitle;
131
+ };
132
+ // Render pandoc-style divs
133
+ function renderStartCallout(tokens, idx, _options, _env, self) {
134
+ const token = tokens[idx];
135
+ const callout = token.meta;
136
+ // Add classes decorating as callout
137
+ token.attrs = addClass(`callout ${callout.clz}`, token.attrs);
138
+ // Add class that reflects the style
139
+ token.attrs = addClass(appearanceClass(callout.appearance), token.attrs);
140
+ return `<div ${self.renderAttrs(token)}>`;
141
+ }
142
+ // Render pandoc-style divs
143
+ function renderEndCallout() {
144
+ return '</div>';
145
+ }
146
+ function renderStartCalloutTitle(tokens, idx) {
147
+ const token = tokens[idx];
148
+ const title = readAttrValue('title', token.attrs) || '';
149
+ const startContent = `
150
+ <div class="callout-header">
151
+ <div class="callout-icon-container">
152
+ <i class="callout-icon"></i>
153
+ </div>
154
+ <div class="callout-title-container">${title}
155
+ `;
156
+ return startContent;
157
+ }
158
+ function renderEndCalloutTitle() {
159
+ return '</div>\n</div>';
160
+ }
161
+ const calloutAppearance = (val) => {
162
+ if (val) {
163
+ switch (val) {
164
+ case 'minimal':
165
+ return 'minimal';
166
+ case 'simple':
167
+ return 'simple';
168
+ case 'default':
169
+ default:
170
+ return 'default';
171
+ }
172
+ }
173
+ else {
174
+ return 'default';
175
+ }
176
+ };
177
+ const parseCallout = (attrs) => {
178
+ if (attrs === null) {
179
+ return undefined;
180
+ }
181
+ const classAttr = attrs.find(attr => {
182
+ return attr[0] === 'class';
183
+ });
184
+ if (!classAttr) {
185
+ return undefined;
186
+ }
187
+ const classes = classAttr[1].split(' ');
188
+ const calloutClass = classes.find(clz => {
189
+ return clz.startsWith('callout-');
190
+ });
191
+ if (calloutClass) {
192
+ const type = calloutClass.replace(kCalloutPrefix, '');
193
+ const title = readAttrValue('title', attrs) ||
194
+ type.slice(0, 1).toUpperCase() + type.slice(1);
195
+ const appearance = calloutAppearance(readAttrValue('appearance', attrs));
196
+ return {
197
+ type: type || 'note',
198
+ clz: calloutClass,
199
+ title,
200
+ appearance
201
+ };
202
+ }
203
+ else {
204
+ return undefined;
205
+ }
206
+ };
207
+ const appearanceClass = (appearance) => {
208
+ const style = appearance || 'default';
209
+ return `callout-style-${style}`;
210
+ };
@@ -0,0 +1,2 @@
1
+ import type MarkdownIt from 'markdown-it/lib';
2
+ export declare const citationPlugin: (md: MarkdownIt) => void;
@@ -0,0 +1,166 @@
1
+ /*
2
+ * citation.ts
3
+ *
4
+ * Copyright (C) 2020-2023 Posit Software, PBC
5
+ *
6
+ */
7
+ const kTokCite = 'quarto_cite';
8
+ export const citationPlugin = (md) => {
9
+ // Very simple plugin example that surrounds @text with `code`
10
+ md.core.ruler.push('quarto-citation', state => {
11
+ const tokens = state.tokens;
12
+ for (const token of tokens) {
13
+ if (token.type === 'inline' && token.children) {
14
+ // Rebuild the child list
15
+ const children = [];
16
+ for (let i = 0; i < token.children.length; i++) {
17
+ const child = token.children[i];
18
+ if (child.type === 'text') {
19
+ const content = child.content;
20
+ const textToken = (text) => {
21
+ const newToken = new state.Token('text', '', 0);
22
+ newToken.content = text.join('');
23
+ return newToken;
24
+ };
25
+ let text = [];
26
+ const flushText = () => {
27
+ if (text.length) {
28
+ children.push(textToken(text));
29
+ text = [];
30
+ }
31
+ };
32
+ let cite = [];
33
+ const flushCite = () => {
34
+ var _a;
35
+ if (cite.length) {
36
+ // Determine the cite style
37
+ let style = cite[0] === '-' ? 'suppress-author' : 'in-text';
38
+ if (bracketCount > 0) {
39
+ style = 'normal';
40
+ }
41
+ // The classes
42
+ const clz = ['cite', style];
43
+ // If the cite ends in punctuation, trim that off and make that text
44
+ const puncText = [];
45
+ // Trim off ending punctuation
46
+ if ([
47
+ ':',
48
+ '.',
49
+ '#',
50
+ '$',
51
+ '%',
52
+ '&',
53
+ '-',
54
+ '+',
55
+ '?',
56
+ '<',
57
+ '>',
58
+ '~',
59
+ '/',
60
+ '!'
61
+ ].includes(cite[cite.length - 1])) {
62
+ puncText.push(cite[cite.length - 1]);
63
+ cite = cite.slice(0, -1);
64
+ }
65
+ // Make a cite token
66
+ const newToken = new state.Token(kTokCite, '', 0);
67
+ newToken.content = cite.join('');
68
+ newToken.attrs = newToken.attrs || [];
69
+ (_a = newToken.attrs) === null || _a === void 0 ? void 0 : _a.push(['class', clz.join(' ')]);
70
+ children.push(newToken);
71
+ cite = [];
72
+ if (puncText.length > 0) {
73
+ children.push(textToken(puncText));
74
+ }
75
+ }
76
+ };
77
+ let capture = 'text';
78
+ let bracketCount = 0;
79
+ for (let j = 0; j < content.length; j++) {
80
+ const char = content.charAt(j);
81
+ if (char === '@') {
82
+ if ((text.length === 1 && text[0] === '-') ||
83
+ (text.length > 1 &&
84
+ text[text.length - 1] === '-' &&
85
+ text[text.length - 2] === '[')) {
86
+ cite.push('-');
87
+ cite.push(char);
88
+ text.pop();
89
+ flushText();
90
+ capture = 'cite';
91
+ }
92
+ else if (text[text.length - 1] === ' ') {
93
+ flushText();
94
+ cite.push(char);
95
+ capture = 'cite';
96
+ }
97
+ else if (text[text.length - 1] === '-' &&
98
+ text[text.length - 2] === ' ') {
99
+ text = text.slice(0, -1);
100
+ flushText();
101
+ cite.push('-');
102
+ cite.push(char);
103
+ capture = 'cite';
104
+ }
105
+ else if (text[text.length - 1] === '[' &&
106
+ text[text.length - 2] === ' ') {
107
+ flushText();
108
+ cite.push(char);
109
+ capture = 'cite';
110
+ }
111
+ else if (text.length === 0) {
112
+ cite.push(char);
113
+ capture = 'cite';
114
+ }
115
+ else {
116
+ if (capture === 'cite') {
117
+ cite.push(char);
118
+ }
119
+ else {
120
+ text.push(char);
121
+ }
122
+ }
123
+ }
124
+ else if (char === ' ') {
125
+ capture = 'text';
126
+ flushCite();
127
+ text.push(char);
128
+ }
129
+ else if (char === '[') {
130
+ bracketCount++;
131
+ text.push(char);
132
+ }
133
+ else if (char === ']') {
134
+ bracketCount--;
135
+ capture = 'text';
136
+ flushCite();
137
+ text.push(char);
138
+ }
139
+ else {
140
+ if (capture === 'cite') {
141
+ cite.push(char);
142
+ }
143
+ else {
144
+ text.push(char);
145
+ }
146
+ }
147
+ }
148
+ flushCite();
149
+ flushText();
150
+ }
151
+ else {
152
+ children.push(child);
153
+ }
154
+ }
155
+ token.children = children.length > 0 ? children : null;
156
+ }
157
+ }
158
+ });
159
+ md.renderer.rules[kTokCite] = renderCite;
160
+ };
161
+ // Render pandoc-style divs
162
+ function renderCite(tokens, idx, _options, _env, self) {
163
+ const token = tokens[idx];
164
+ const citeContent = `<code ${self.renderAttrs(token)}>${token.content}</code>`;
165
+ return citeContent;
166
+ }
@@ -0,0 +1,2 @@
1
+ import type MarkdownIt from 'markdown-it/lib';
2
+ export declare const decoratorPlugin: (md: MarkdownIt) => void;
@@ -0,0 +1,58 @@
1
+ import Token from 'markdown-it/lib/token';
2
+ import { attributeDecorator, decorator } from './utils/html';
3
+ import { kTokDivOpen } from './divs';
4
+ import { kTokFigureOpen } from './figures';
5
+ import { kTokHeadingOpen, kTokTableOpen } from './utils/tok';
6
+ import { kTokMathBlock } from './math';
7
+ const kTokDecorator = 'quarto_decorator';
8
+ const kQuartoDecoratorOptions = 'quarto-decorator-options';
9
+ export const decoratorPlugin = (md) => {
10
+ md.core.ruler.push('quarto-decorator', state => {
11
+ const outTokens = [];
12
+ for (const token of state.tokens) {
13
+ if (token.type === 'fence' && !token.attrs && token.info) {
14
+ outTokens.push(decoratorTokForToken(token));
15
+ }
16
+ else if (token.type === kTokHeadingOpen && token.attrs) {
17
+ outTokens.push(decoratorTokForToken(token));
18
+ }
19
+ else if (token.type === kTokDivOpen && token.attrs) {
20
+ outTokens.push(decoratorTokForToken(token));
21
+ }
22
+ else if (token.type === kTokFigureOpen && token.attrs) {
23
+ outTokens.push(decoratorTokForToken(token, { hide: { attributes: true } }));
24
+ }
25
+ else if (token.type === kTokTableOpen && token.attrs) {
26
+ outTokens.push(decoratorTokForToken(token));
27
+ }
28
+ else if (token.type === kTokMathBlock && token.attrs) {
29
+ outTokens.push(decoratorTokForToken(token));
30
+ }
31
+ outTokens.push(token);
32
+ }
33
+ state.tokens = outTokens;
34
+ });
35
+ md.renderer.rules[kTokDecorator] = renderDecorator;
36
+ };
37
+ function decoratorTokForToken(token, options) {
38
+ const decoratorTok = new Token(kTokDecorator, 'div', 1);
39
+ decoratorTok.attrs = token.attrs;
40
+ decoratorTok.info = token.info;
41
+ if (options) {
42
+ decoratorTok.meta = decoratorTok.meta || {};
43
+ decoratorTok.meta[kQuartoDecoratorOptions] = options;
44
+ }
45
+ return decoratorTok;
46
+ }
47
+ // Render pandoc-style divs
48
+ function renderDecorator(tokens, idx) {
49
+ var _a;
50
+ const token = tokens[idx];
51
+ const decoratorOptions = (_a = token.meta) === null || _a === void 0 ? void 0 : _a[kQuartoDecoratorOptions];
52
+ if (token.info) {
53
+ return decorator([token.info]);
54
+ }
55
+ else {
56
+ return attributeDecorator(token, decoratorOptions);
57
+ }
58
+ }
@@ -0,0 +1,5 @@
1
+ import type MarkdownIt from 'markdown-it/lib';
2
+ export declare const kDivRuleName = "pandocDiv";
3
+ export declare const kTokDivOpen = "pandoc_div_open";
4
+ export declare const kTokDivClose = "pandoc_div_close";
5
+ export declare const divPlugin: (md: MarkdownIt) => void;
@@ -0,0 +1,111 @@
1
+ import { addClass } from './utils/markdownit';
2
+ export const kDivRuleName = 'pandocDiv';
3
+ export const kTokDivOpen = 'pandoc_div_open';
4
+ export const kTokDivClose = 'pandoc_div_close';
5
+ export const divPlugin = (md) => {
6
+ // Render pandoc-style divs
7
+ function renderStartDiv(tokens, idx, _options, _env, self) {
8
+ // Add a class to designate that this is a quarto dev
9
+ const token = tokens[idx];
10
+ token.attrs = addClass('quarto-div', token.attrs);
11
+ return `<div ${self.renderAttrs(token)}>`;
12
+ }
13
+ // Render pandoc-style divs
14
+ function renderEndDiv() {
15
+ return '</div>';
16
+ }
17
+ // TODO Implement a better test during validation run
18
+ // Handle pandoc-style divs
19
+ md.block.ruler.before('fence', kDivRuleName, (state, start, _end, silent) => {
20
+ // This is a validation run, can ignore
21
+ if (silent) {
22
+ return true;
23
+ }
24
+ // Get the line for parsing
25
+ const lineStart = state.bMarks[start] + state.tShift[start];
26
+ const lineEnd = state.eMarks[start];
27
+ const line = state.src.slice(lineStart, lineEnd);
28
+ // The current state of the divs (e.g. is there an open)
29
+ // div. Data structure holds key that is the number of colons
30
+ const divState = state.env.quartoOpenDivs || {};
31
+ const incrementDivCount = (fence) => {
32
+ var _a;
33
+ state.env.quartoDivLevel = ((_a = state.env.quartoDivLevel) !== null && _a !== void 0 ? _a : 0) + 1;
34
+ state.env.quartoOpenDivs = state.env.quartoOpenDivs || {};
35
+ const current = state.env.quartoOpenDivs[fence] || 0;
36
+ state.env.quartoOpenDivs[fence] = Math.max(0, current + 1);
37
+ };
38
+ const decrementDivCount = (fence) => {
39
+ state.env.quartoDivLevel--;
40
+ state.env.quartoOpenDivs = state.env.quartoOpenDivs || {};
41
+ const current = state.env.quartoOpenDivs[fence] || 0;
42
+ state.env.quartoOpenDivs[fence] = Math.max(0, current - 1);
43
+ };
44
+ // Three or more colons followed by a an optional brace with attributes
45
+ const divBraceRegex = /^(:::+)\s*(?:(\{[\s\S]+?\}))?$/;
46
+ // Three or more colons followed by a string with no braces
47
+ const divNoBraceRegex = /^(:::+)\s*(?:([^{}\s]+?))?$/;
48
+ const matchers = [divBraceRegex, divNoBraceRegex];
49
+ let match;
50
+ for (const matcher of matchers) {
51
+ match = matcher.exec(line);
52
+ if (match) {
53
+ break;
54
+ }
55
+ }
56
+ if (match) {
57
+ // There is a div here, is one already open?
58
+ const divFence = match[1];
59
+ const attr = match[2];
60
+ // Is this open?
61
+ let isOpenDiv = false;
62
+ const openCount = divState[divFence];
63
+ if (!openCount || openCount === 0) {
64
+ // There isn't an existing open div at this level (number of colons)
65
+ isOpenDiv = true;
66
+ }
67
+ else if (attr) {
68
+ // If it has attributes it is always open
69
+ isOpenDiv = true;
70
+ }
71
+ if (isOpenDiv) {
72
+ // Add to the open count (or set it to 1)
73
+ incrementDivCount(divFence);
74
+ // Make an open token
75
+ const token = state.push(kTokDivOpen, 'div', 1);
76
+ token.markup = line;
77
+ // Allow this to be parsed for attributes by markdown-it-attr
78
+ if (attr && attr.startsWith('{')) {
79
+ token.info = attr;
80
+ }
81
+ else if (attr) {
82
+ token.info = `{.${attr}}`;
83
+ }
84
+ token.block = true;
85
+ token.meta = {
86
+ line: state.line,
87
+ level: state.env.quartoDivLevel
88
+ };
89
+ }
90
+ else {
91
+ // Subtract from the open count (min zero)
92
+ const level = state.env.quartoDivLevel;
93
+ decrementDivCount(divFence);
94
+ // Make a close token
95
+ const token = state.push(kTokDivClose, 'div', -1);
96
+ token.markup = line;
97
+ token.meta = {
98
+ line: state.line,
99
+ level
100
+ };
101
+ }
102
+ state.line = start + 1;
103
+ return true;
104
+ }
105
+ else {
106
+ return false;
107
+ }
108
+ }, { alt: [] });
109
+ md.renderer.rules[kTokDivOpen] = renderStartDiv;
110
+ md.renderer.rules[kTokDivClose] = renderEndDiv;
111
+ };
@@ -0,0 +1,2 @@
1
+ import MarkdownIt from 'markdown-it';
2
+ export declare const figureDivsPlugin: (md: MarkdownIt) => void;
@@ -0,0 +1,54 @@
1
+ /*
2
+ * figure-divs.ts
3
+ *
4
+ * Copyright (C) 2020-2023 Posit Software, PBC
5
+ *
6
+ */
7
+ import { readAttrValue } from './utils/markdownit';
8
+ import { kTokInline, kTokParaClose, kTokParaOpen } from './utils/tok';
9
+ import { kTokDivClose, kTokDivOpen } from './divs';
10
+ import { kTokFigCaptionClose, kTokFigCaptionOpen, mutateToFigureTok } from './figures';
11
+ const kFigureDivRuleName = 'quarto-figure-divs';
12
+ const kFigurePrefix = 'fig-';
13
+ export const figureDivsPlugin = (md) => {
14
+ // Handle pandoc-style divs
15
+ md.core.ruler.push(kFigureDivRuleName, state => {
16
+ const isFigureDiv = [];
17
+ for (let i = 0; i < state.tokens.length; i++) {
18
+ const token = state.tokens[i];
19
+ if (token.type === kTokDivOpen) {
20
+ const id = readAttrValue('id', token.attrs);
21
+ if (id === null || id === void 0 ? void 0 : id.startsWith(kFigurePrefix)) {
22
+ isFigureDiv.push(true);
23
+ mutateToFigureTok(token, 'open');
24
+ }
25
+ else {
26
+ // Note the div, but not a figure div
27
+ isFigureDiv.push(false);
28
+ }
29
+ }
30
+ else if (token.type === kTokDivClose) {
31
+ const isFigDiv = isFigureDiv.pop();
32
+ if (isFigDiv) {
33
+ // If the preview token is paragraph, use that as the caption
34
+ if (i - 3 >= 0) {
35
+ const maybeParaStart = state.tokens[i - 3];
36
+ const maybeInline = state.tokens[i - 2];
37
+ const maybeParaEnd = state.tokens[i - 1];
38
+ if (maybeParaStart.type === kTokParaOpen &&
39
+ maybeParaEnd.type === kTokParaClose &&
40
+ maybeInline.type === kTokInline) {
41
+ mutateToFigCaption(state.tokens[i - 3], 'open');
42
+ mutateToFigCaption(state.tokens[i - 1], 'close');
43
+ }
44
+ }
45
+ mutateToFigureTok(token, 'close');
46
+ }
47
+ }
48
+ }
49
+ });
50
+ };
51
+ const mutateToFigCaption = (token, type) => {
52
+ token.tag = 'figcaption';
53
+ token.type = type === 'open' ? kTokFigCaptionClose : kTokFigCaptionOpen;
54
+ };
@@ -0,0 +1,16 @@
1
+ import MarkdownIt from 'markdown-it';
2
+ import Token from 'markdown-it/lib/token';
3
+ export interface FigureOptions {
4
+ dataType?: boolean;
5
+ link?: boolean;
6
+ figcaption?: boolean;
7
+ copyAttrs?: boolean;
8
+ tabindex?: boolean;
9
+ lazyLoading?: boolean;
10
+ }
11
+ export declare const kTokFigureOpen = "figure_open";
12
+ export declare const kTokFigureClose = "figure_close";
13
+ export declare const kTokFigCaptionOpen = "figcaption_open";
14
+ export declare const kTokFigCaptionClose = "figcaption_close";
15
+ export declare const mutateToFigureTok: (token: Token, type: 'open' | 'close') => void;
16
+ export declare function figuresPlugin(md: MarkdownIt, options: FigureOptions): void;