structured-render 0.0.0 → 0.0.1
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/LICENSE-CC0 +121 -0
- package/LICENSE-MIT +21 -0
- package/README.md +13 -0
- package/dist/augments/shadow-styles.d.ts +7 -0
- package/dist/augments/shadow-styles.js +17 -0
- package/dist/elements/vir-markdown.element.d.ts +16 -0
- package/dist/elements/vir-markdown.element.js +73 -0
- package/dist/elements/vir-source.element.d.ts +24 -0
- package/dist/elements/vir-source.element.js +158 -0
- package/dist/elements/vir-structured-render.element.d.ts +19 -0
- package/dist/elements/vir-structured-render.element.js +346 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +26 -0
- package/dist/render/browser-rendering.d.ts +90 -0
- package/dist/render/browser-rendering.js +233 -0
- package/dist/render/html-to-pdf.d.ts +50 -0
- package/dist/render/html-to-pdf.js +7 -0
- package/dist/render/render-html.d.ts +38 -0
- package/dist/render/render-html.js +504 -0
- package/dist/render/render-image.d.ts +24 -0
- package/dist/render/render-image.js +35 -0
- package/dist/render/render-markdown-styles.d.ts +62 -0
- package/dist/render/render-markdown-styles.js +242 -0
- package/dist/render/render-markdown.d.ts +8 -0
- package/dist/render/render-markdown.js +169 -0
- package/dist/render/render-pdf.d.ts +35 -0
- package/dist/render/render-pdf.js +65 -0
- package/dist/render/render-types.d.ts +134 -0
- package/dist/render/render-types.js +41 -0
- package/dist/structured-render-data/create-section.d.ts +23 -0
- package/dist/structured-render-data/create-section.js +16 -0
- package/dist/structured-render-data/sections/code-block.section.d.ts +30 -0
- package/dist/structured-render-data/sections/code-block.section.js +11 -0
- package/dist/structured-render-data/sections/empty.section.d.ts +14 -0
- package/dist/structured-render-data/sections/empty.section.js +9 -0
- package/dist/structured-render-data/sections/icon.section.d.ts +25 -0
- package/dist/structured-render-data/sections/icon.section.js +40 -0
- package/dist/structured-render-data/sections/inline-code.section.d.ts +29 -0
- package/dist/structured-render-data/sections/inline-code.section.js +9 -0
- package/dist/structured-render-data/sections/list.section.d.ts +169 -0
- package/dist/structured-render-data/sections/list.section.js +29 -0
- package/dist/structured-render-data/sections/markdown.section.d.ts +29 -0
- package/dist/structured-render-data/sections/markdown.section.js +9 -0
- package/dist/structured-render-data/sections/processing.section.d.ts +14 -0
- package/dist/structured-render-data/sections/processing.section.js +9 -0
- package/dist/structured-render-data/sections/source.section.d.ts +59 -0
- package/dist/structured-render-data/sections/source.section.js +47 -0
- package/dist/structured-render-data/sections/table.section.d.ts +939 -0
- package/dist/structured-render-data/sections/table.section.js +99 -0
- package/dist/structured-render-data/sections/tag.section.d.ts +39 -0
- package/dist/structured-render-data/sections/tag.section.js +20 -0
- package/dist/structured-render-data/sections/text.section.d.ts +48 -0
- package/dist/structured-render-data/sections/text.section.js +25 -0
- package/dist/structured-render-data/structured-render-card.d.ts +918 -0
- package/dist/structured-render-data/structured-render-card.js +11 -0
- package/dist/structured-render-data/structured-render-data.d.ts +919 -0
- package/dist/structured-render-data/structured-render-data.js +8 -0
- package/dist/structured-render-data/structured-render-section.d.ts +1857 -0
- package/dist/structured-render-data/structured-render-section.js +115 -0
- package/package.json +75 -11
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import { assert, check } from '@augment-vir/assert';
|
|
2
|
+
import { ensureArray, filterMap, mapEnumToObject, mapObjectValues, mergeDefinedProperties, stringify, } from '@augment-vir/common';
|
|
3
|
+
import { extractEventTarget } from '@augment-vir/web';
|
|
4
|
+
import { classMap, css, defineTypedEvent, html, ifDefined, join, listen, nothing, testId, unsafeCSS, } from 'element-vir';
|
|
5
|
+
import { defineTable, ViraCollapsibleWrapper, ViraColorVariant, ViraEmphasis, ViraIcon, ViraSize, ViraTableOrientation, ViraTag, } from 'vira';
|
|
6
|
+
import { VirMarkdown } from '../elements/vir-markdown.element.js';
|
|
7
|
+
import { VirSource } from '../elements/vir-source.element.js';
|
|
8
|
+
import { createStructuredRenderIcon } from '../structured-render-data/sections/icon.section.js';
|
|
9
|
+
import { createCleanSources, } from '../structured-render-data/sections/source.section.js';
|
|
10
|
+
import { StructuredRenderCellDirection, StructuredRenderTableFooterAlignment, } from '../structured-render-data/sections/table.section.js';
|
|
11
|
+
import { StructuredRenderSectionType, } from '../structured-render-data/structured-render-section.js';
|
|
12
|
+
import { defaultRenderHtmlOptions, } from './render-types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Render Structured Render data to HTML templates.
|
|
15
|
+
*
|
|
16
|
+
* @category Render
|
|
17
|
+
*/
|
|
18
|
+
export function renderStructuredHtml(data, options) {
|
|
19
|
+
const finalOptions = mergeDefinedProperties(defaultRenderHtmlOptions, options);
|
|
20
|
+
return renderInternalStructuredHtml(data, finalOptions, []);
|
|
21
|
+
}
|
|
22
|
+
function formatText(text) {
|
|
23
|
+
if (text == undefined) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
else if (!check.isString(text)) {
|
|
27
|
+
return String(text);
|
|
28
|
+
}
|
|
29
|
+
const trimmedText = text.trim();
|
|
30
|
+
if (!trimmedText) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
const splits = trimmedText.split('\n');
|
|
34
|
+
return splits.flatMap((split, index) => {
|
|
35
|
+
return html `
|
|
36
|
+
${split}${index < splits.length - 1
|
|
37
|
+
? html `
|
|
38
|
+
<br />
|
|
39
|
+
`
|
|
40
|
+
: ''}
|
|
41
|
+
`;
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const htmlRenderers = {
|
|
45
|
+
icon(section, options) {
|
|
46
|
+
const icon = createStructuredRenderIcon(section, options);
|
|
47
|
+
if (!icon) {
|
|
48
|
+
return nothing;
|
|
49
|
+
}
|
|
50
|
+
return html `
|
|
51
|
+
<${ViraIcon.assign({
|
|
52
|
+
icon,
|
|
53
|
+
})}></${ViraIcon}>
|
|
54
|
+
`;
|
|
55
|
+
},
|
|
56
|
+
codeBlock(section) {
|
|
57
|
+
return html `
|
|
58
|
+
<pre>${section.code}</pre>
|
|
59
|
+
`;
|
|
60
|
+
},
|
|
61
|
+
empty() {
|
|
62
|
+
return undefined;
|
|
63
|
+
},
|
|
64
|
+
inlineCode(section) {
|
|
65
|
+
return html `
|
|
66
|
+
<code>${section.code}</code>
|
|
67
|
+
`;
|
|
68
|
+
},
|
|
69
|
+
list(section, options, keyChain) {
|
|
70
|
+
const itemTemplates = filterMap(section.items, (item, itemIndex) => {
|
|
71
|
+
if (!item.icon && !item.content) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
const itemTemplate = item.content
|
|
75
|
+
? renderInternalStructuredHtml(item.content, options, [
|
|
76
|
+
...keyChain,
|
|
77
|
+
itemIndex,
|
|
78
|
+
'content',
|
|
79
|
+
])
|
|
80
|
+
: undefined;
|
|
81
|
+
const iconTemplate = item.icon
|
|
82
|
+
? renderInternalStructuredHtml(item.icon, options, [
|
|
83
|
+
...keyChain,
|
|
84
|
+
itemIndex,
|
|
85
|
+
'icon',
|
|
86
|
+
])
|
|
87
|
+
: nothing;
|
|
88
|
+
return html `
|
|
89
|
+
<li class="list-item-with-icon">${iconTemplate}${itemTemplate}</li>
|
|
90
|
+
`;
|
|
91
|
+
}, check.isTruthy);
|
|
92
|
+
if (!itemTemplates.length) {
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
return html `
|
|
96
|
+
<ul>
|
|
97
|
+
${itemTemplates}
|
|
98
|
+
</ul>
|
|
99
|
+
`;
|
|
100
|
+
},
|
|
101
|
+
markdown(section, options) {
|
|
102
|
+
return html `
|
|
103
|
+
<${VirMarkdown.assign({
|
|
104
|
+
markdownString: section.markdown,
|
|
105
|
+
renderStyles: options.markdownStyles,
|
|
106
|
+
})}></${VirMarkdown}>
|
|
107
|
+
`;
|
|
108
|
+
},
|
|
109
|
+
tag(section) {
|
|
110
|
+
const customColorStyles = section.color &&
|
|
111
|
+
'custom' in section.color &&
|
|
112
|
+
(section.color.custom.backgroundColor || section.color.custom.foregroundColor)
|
|
113
|
+
? css `
|
|
114
|
+
${section.color.custom.backgroundColor
|
|
115
|
+
? css `
|
|
116
|
+
${ViraTag.cssVars['vira-tag-background-color'].name}: ${unsafeCSS(section.color.custom.backgroundColor)};
|
|
117
|
+
`
|
|
118
|
+
: css ``}
|
|
119
|
+
${section.color.custom.foregroundColor
|
|
120
|
+
? css `
|
|
121
|
+
${ViraTag.cssVars['vira-tag-text-color'].name}: ${unsafeCSS(section.color.custom.foregroundColor)};
|
|
122
|
+
`
|
|
123
|
+
: css ``}
|
|
124
|
+
`
|
|
125
|
+
: undefined;
|
|
126
|
+
const colorVariant = section.color && 'variant' in section.color ? section.color.variant : undefined;
|
|
127
|
+
return html `
|
|
128
|
+
<${ViraTag.assign({
|
|
129
|
+
text: section.text,
|
|
130
|
+
color: customColorStyles ? ViraColorVariant.None : colorVariant,
|
|
131
|
+
size: section.useBigTag ? ViraSize.Medium : ViraSize.Small,
|
|
132
|
+
emphasis: ViraEmphasis.Subtle,
|
|
133
|
+
})}
|
|
134
|
+
style=${ifDefined(customColorStyles)}
|
|
135
|
+
></${ViraTag}>
|
|
136
|
+
`;
|
|
137
|
+
},
|
|
138
|
+
processing(section, options) {
|
|
139
|
+
return html `
|
|
140
|
+
<${ViraIcon.assign({
|
|
141
|
+
icon: options.processingIcon,
|
|
142
|
+
})}></${ViraIcon}>
|
|
143
|
+
<span>${options.processingString}...</span>
|
|
144
|
+
`;
|
|
145
|
+
},
|
|
146
|
+
source(section, options) {
|
|
147
|
+
return html `
|
|
148
|
+
<${VirSource.assign({
|
|
149
|
+
options,
|
|
150
|
+
sources: section,
|
|
151
|
+
})}></${VirSource}>
|
|
152
|
+
`;
|
|
153
|
+
},
|
|
154
|
+
table(section, options, keyChain) {
|
|
155
|
+
const { headerRow, rows } = defineTable(filterMap(section.headers, (header, headerIndex) => {
|
|
156
|
+
if (header.hidden) {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
key: header.key,
|
|
161
|
+
content: header.text
|
|
162
|
+
? renderInternalStructuredHtml(header.text, options, [
|
|
163
|
+
...keyChain,
|
|
164
|
+
'headers',
|
|
165
|
+
headerIndex,
|
|
166
|
+
])
|
|
167
|
+
: header.key,
|
|
168
|
+
};
|
|
169
|
+
}, check.isTruthy), section.entries, (row, rowIndex) => {
|
|
170
|
+
return mapObjectValues(row.data, (key, content) => {
|
|
171
|
+
const contents = ensureArray(content).filter(check.isTruthy);
|
|
172
|
+
if (!contents.length) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
const contentTemplates = Array.from(join(filterMap(contents, (innerContent, contentIndex) => renderInternalStructuredHtml(innerContent, options, [
|
|
176
|
+
...keyChain,
|
|
177
|
+
rowIndex,
|
|
178
|
+
contentIndex,
|
|
179
|
+
]), check.isTruthy), html `
|
|
180
|
+
<br />
|
|
181
|
+
`));
|
|
182
|
+
return contentTemplates;
|
|
183
|
+
});
|
|
184
|
+
}, {
|
|
185
|
+
orientation: section.direction === StructuredRenderCellDirection.Horizontal
|
|
186
|
+
? ViraTableOrientation.Vertical
|
|
187
|
+
: ViraTableOrientation.Horizontal,
|
|
188
|
+
});
|
|
189
|
+
const tableHasRowSource = rows.some((row) => !!row.data?.sources?.length);
|
|
190
|
+
const columnCount = rows[0]?.cells.length || 0;
|
|
191
|
+
return html `
|
|
192
|
+
<table
|
|
193
|
+
cellspacing="0"
|
|
194
|
+
cellpadding="0"
|
|
195
|
+
class=${classMap({
|
|
196
|
+
vertical: section.direction === StructuredRenderCellDirection.Vertical,
|
|
197
|
+
horizontal: section.direction === StructuredRenderCellDirection.Horizontal,
|
|
198
|
+
'wide-table': section.direction === StructuredRenderCellDirection.Horizontal && headerRow
|
|
199
|
+
? headerRow.length > 5
|
|
200
|
+
: section.direction === StructuredRenderCellDirection.Vertical &&
|
|
201
|
+
rows[0]
|
|
202
|
+
? rows[0].cells.length > 5
|
|
203
|
+
: false,
|
|
204
|
+
})}
|
|
205
|
+
>
|
|
206
|
+
${headerRow
|
|
207
|
+
? html `
|
|
208
|
+
<thead>
|
|
209
|
+
<tr>
|
|
210
|
+
${headerRow.map((headerCell) => {
|
|
211
|
+
return html `
|
|
212
|
+
<th>${headerCell.content}</th>
|
|
213
|
+
`;
|
|
214
|
+
})}
|
|
215
|
+
${tableHasRowSource
|
|
216
|
+
? html `
|
|
217
|
+
<th class="source-cell"></th>
|
|
218
|
+
`
|
|
219
|
+
: nothing}
|
|
220
|
+
</tr>
|
|
221
|
+
</thead>
|
|
222
|
+
`
|
|
223
|
+
: nothing}
|
|
224
|
+
<tbody>
|
|
225
|
+
${rows.map((row, rowIndex) => {
|
|
226
|
+
const rowKeyChain = [
|
|
227
|
+
...keyChain,
|
|
228
|
+
rowIndex,
|
|
229
|
+
];
|
|
230
|
+
const rowSources = createCleanSources(row.data?.sources);
|
|
231
|
+
const cells = row.cells.map((cell, index) => {
|
|
232
|
+
const isLastCell = index === row.cells.length - 1;
|
|
233
|
+
const cellTag = section.direction === StructuredRenderCellDirection.Vertical &&
|
|
234
|
+
index === 0
|
|
235
|
+
? 'th'
|
|
236
|
+
: 'td';
|
|
237
|
+
const cellTemplate = html `
|
|
238
|
+
<${cellTag}>${cell.content}</${cellTag}>
|
|
239
|
+
`;
|
|
240
|
+
if (rowSources?.length && isLastCell) {
|
|
241
|
+
return html `
|
|
242
|
+
${cellTemplate}
|
|
243
|
+
<td class="source-cell">
|
|
244
|
+
${createSourceTrigger('', options, rowKeyChain, rowSources)}
|
|
245
|
+
</td>
|
|
246
|
+
`;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
return cellTemplate;
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
const sourceRow = rowSources?.length
|
|
253
|
+
? html `
|
|
254
|
+
<tr class="source-row">
|
|
255
|
+
<td colspan=${cells.length}>
|
|
256
|
+
${createExpandingSource(options, rowKeyChain, rowSources)}
|
|
257
|
+
</td>
|
|
258
|
+
</tr>
|
|
259
|
+
`
|
|
260
|
+
: nothing;
|
|
261
|
+
return html `
|
|
262
|
+
<tr>
|
|
263
|
+
${cells}
|
|
264
|
+
${tableHasRowSource && !rowSources?.length
|
|
265
|
+
? html `
|
|
266
|
+
<td class="source-cell"></td>
|
|
267
|
+
`
|
|
268
|
+
: nothing}
|
|
269
|
+
</tr>
|
|
270
|
+
${sourceRow}
|
|
271
|
+
`;
|
|
272
|
+
})}
|
|
273
|
+
</tbody>
|
|
274
|
+
${section.footerRows?.length
|
|
275
|
+
? html `
|
|
276
|
+
<tfoot>
|
|
277
|
+
${section.footerRows.map((footerRow, rowIndex) => {
|
|
278
|
+
const cells = ensureArray(footerRow.cells);
|
|
279
|
+
if (!cells.length) {
|
|
280
|
+
return nothing;
|
|
281
|
+
}
|
|
282
|
+
const firstCellColspan = footerRow.alignment ===
|
|
283
|
+
StructuredRenderTableFooterAlignment.Right
|
|
284
|
+
? columnCount - cells.length + 1
|
|
285
|
+
: 0;
|
|
286
|
+
const cellTemplates = cells.map((cell, cellIndex) => {
|
|
287
|
+
const rawColspan = cellIndex ? 0 : firstCellColspan;
|
|
288
|
+
const colspan = rawColspan < 1 ? undefined : rawColspan;
|
|
289
|
+
const cellContents = cell
|
|
290
|
+
? renderInternalStructuredHtml(cell, options, [
|
|
291
|
+
...keyChain,
|
|
292
|
+
'footers',
|
|
293
|
+
rowIndex,
|
|
294
|
+
cellIndex,
|
|
295
|
+
])
|
|
296
|
+
: nothing;
|
|
297
|
+
return html `
|
|
298
|
+
<td
|
|
299
|
+
colspan=${ifDefined(colspan)}
|
|
300
|
+
class=${classMap({
|
|
301
|
+
'right-aligned-footer-cell': !!colspan,
|
|
302
|
+
})}
|
|
303
|
+
>
|
|
304
|
+
${cellContents}
|
|
305
|
+
</td>
|
|
306
|
+
`;
|
|
307
|
+
});
|
|
308
|
+
return html `
|
|
309
|
+
<tr>${cellTemplates}</tr>
|
|
310
|
+
`;
|
|
311
|
+
})}
|
|
312
|
+
</tfoot>
|
|
313
|
+
`
|
|
314
|
+
: nothing}
|
|
315
|
+
</table>
|
|
316
|
+
`;
|
|
317
|
+
},
|
|
318
|
+
text(section, options, keyChain) {
|
|
319
|
+
const formattedText = formatText(section.text);
|
|
320
|
+
const styleClass = section.style ? `text-style-${section.style}` : undefined;
|
|
321
|
+
if (!formattedText) {
|
|
322
|
+
return undefined;
|
|
323
|
+
}
|
|
324
|
+
return html `
|
|
325
|
+
${renderInternalStructuredHtml(section.icon, options, [
|
|
326
|
+
...keyChain,
|
|
327
|
+
'icon',
|
|
328
|
+
])}
|
|
329
|
+
<span
|
|
330
|
+
class=${[
|
|
331
|
+
styleClass,
|
|
332
|
+
'text-section-text-content',
|
|
333
|
+
].join(' ')}
|
|
334
|
+
>
|
|
335
|
+
${formattedText}
|
|
336
|
+
</span>
|
|
337
|
+
`;
|
|
338
|
+
},
|
|
339
|
+
};
|
|
340
|
+
function renderInternalStructuredHtml(data, options, keyChain) {
|
|
341
|
+
return structuredRenderToHtmlArray(data, options, keyChain).filter(check.isTruthy);
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Used for both HTML class names and test ids.
|
|
345
|
+
*
|
|
346
|
+
* @category Internal
|
|
347
|
+
*/
|
|
348
|
+
export const structuredRenderSectionHtmlNames = mapEnumToObject(StructuredRenderSectionType, (sectionType) => {
|
|
349
|
+
return [
|
|
350
|
+
sectionType,
|
|
351
|
+
'section',
|
|
352
|
+
].join('-');
|
|
353
|
+
});
|
|
354
|
+
/**
|
|
355
|
+
* A test id that you can use to target a section in the Structured Render HTML output.
|
|
356
|
+
*
|
|
357
|
+
* @category Internal
|
|
358
|
+
*/
|
|
359
|
+
export const structuredRenderSectionHtmlTestId = 'structured-render-section';
|
|
360
|
+
function structuredRenderToHtmlArray(data, options, keyChain) {
|
|
361
|
+
if (!data) {
|
|
362
|
+
return [];
|
|
363
|
+
}
|
|
364
|
+
else if (check.isArray(data)) {
|
|
365
|
+
return data.flatMap((entry, index) => structuredRenderToHtmlArray(entry, options, [
|
|
366
|
+
...keyChain,
|
|
367
|
+
index,
|
|
368
|
+
]));
|
|
369
|
+
}
|
|
370
|
+
else if ('type' in data) {
|
|
371
|
+
const sectionTitle = ('sectionTitle' in data && keyChain.length > 0 && data.sectionTitle) || undefined;
|
|
372
|
+
const sectionTemplate = htmlRenderers[data.type](data, options, keyChain);
|
|
373
|
+
const sources = ('sources' in data && data.sources) || undefined;
|
|
374
|
+
return [
|
|
375
|
+
sectionTitle
|
|
376
|
+
? html `
|
|
377
|
+
<h3>${sectionTitle}</h3>
|
|
378
|
+
`
|
|
379
|
+
: undefined,
|
|
380
|
+
html `
|
|
381
|
+
<div
|
|
382
|
+
class=${classMap({
|
|
383
|
+
'section-wrapper': true,
|
|
384
|
+
'top-section-wrapper': keyChain.length === 0,
|
|
385
|
+
[structuredRenderSectionHtmlNames[data.type]]: true,
|
|
386
|
+
})}
|
|
387
|
+
${testId(structuredRenderSectionHtmlTestId)}
|
|
388
|
+
${testId(structuredRenderSectionHtmlNames[data.type])}
|
|
389
|
+
>
|
|
390
|
+
${createSourceWrapper(sectionTemplate, options, keyChain, sources)}
|
|
391
|
+
</div>
|
|
392
|
+
`,
|
|
393
|
+
];
|
|
394
|
+
}
|
|
395
|
+
else if ('sections' in data) {
|
|
396
|
+
return [
|
|
397
|
+
data.cardTitle
|
|
398
|
+
? html `
|
|
399
|
+
<h2>${data.cardTitle}</h2>
|
|
400
|
+
`
|
|
401
|
+
: undefined,
|
|
402
|
+
...structuredRenderToHtmlArray(data.sections, options, [
|
|
403
|
+
...keyChain,
|
|
404
|
+
'sections',
|
|
405
|
+
]),
|
|
406
|
+
];
|
|
407
|
+
}
|
|
408
|
+
else {
|
|
409
|
+
assert.tsType(data).equals();
|
|
410
|
+
throw new Error(`Unexpected structured render type: ${stringify(data)}`);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* This event is emitted when source sections have been expanded and can be used to track which
|
|
415
|
+
* sections are expanded.
|
|
416
|
+
*
|
|
417
|
+
* @category Internal
|
|
418
|
+
*/
|
|
419
|
+
export const SourceExpansionEvent = defineTypedEvent()('source-expansion');
|
|
420
|
+
function createSourceTrigger(content, options, rawKeyChain, rawSources) {
|
|
421
|
+
const sources = createCleanSources(rawSources);
|
|
422
|
+
if (!sources) {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
425
|
+
const sourceKeyChain = [
|
|
426
|
+
...rawKeyChain,
|
|
427
|
+
'source-icon',
|
|
428
|
+
];
|
|
429
|
+
const sourceKey = makeChainKey(sourceKeyChain);
|
|
430
|
+
const isSourceExpanded = !!options.currentlyExpanded[sourceKey];
|
|
431
|
+
const sourceIconTemplate = html `
|
|
432
|
+
<div class="source-icon-wrapper">
|
|
433
|
+
<button class="source-icon-button">
|
|
434
|
+
<${ViraIcon.assign({
|
|
435
|
+
icon: options.sourceIcon,
|
|
436
|
+
fitContainer: true,
|
|
437
|
+
})}
|
|
438
|
+
${listen('click', (event) => {
|
|
439
|
+
const eventTarget = extractEventTarget(event, HTMLElement);
|
|
440
|
+
eventTarget.dispatchEvent(new SourceExpansionEvent({
|
|
441
|
+
expanded: !isSourceExpanded,
|
|
442
|
+
key: makeChainKey(sourceKeyChain),
|
|
443
|
+
}));
|
|
444
|
+
})}
|
|
445
|
+
></${ViraIcon}>
|
|
446
|
+
</button>
|
|
447
|
+
</div>
|
|
448
|
+
`;
|
|
449
|
+
return html `
|
|
450
|
+
<div class="source-content-wrapper">${content}${sourceIconTemplate}</div>
|
|
451
|
+
`;
|
|
452
|
+
}
|
|
453
|
+
function createExpandingSource(options, rawKeyChain, rawSources) {
|
|
454
|
+
const sources = createCleanSources(rawSources);
|
|
455
|
+
if (!sources) {
|
|
456
|
+
return undefined;
|
|
457
|
+
}
|
|
458
|
+
const sourceKeyChain = [
|
|
459
|
+
...rawKeyChain,
|
|
460
|
+
'source-icon',
|
|
461
|
+
];
|
|
462
|
+
const sourceKey = makeChainKey(sourceKeyChain);
|
|
463
|
+
const isSourceExpanded = !!options.currentlyExpanded[sourceKey];
|
|
464
|
+
return html `
|
|
465
|
+
<${ViraCollapsibleWrapper.assign({
|
|
466
|
+
expanded: isSourceExpanded,
|
|
467
|
+
expandOnPrint: options.expandSourcesOnPrint,
|
|
468
|
+
})}
|
|
469
|
+
class="collapsible-source-wrapper ${classMap({
|
|
470
|
+
'expanded-source': isSourceExpanded,
|
|
471
|
+
})}"
|
|
472
|
+
>
|
|
473
|
+
<span slot=${ViraCollapsibleWrapper.slotNames.header}></span>
|
|
474
|
+
<${VirSource.assign({
|
|
475
|
+
options,
|
|
476
|
+
sources,
|
|
477
|
+
})}></${VirSource}>
|
|
478
|
+
</${ViraCollapsibleWrapper}>
|
|
479
|
+
`;
|
|
480
|
+
}
|
|
481
|
+
function createSourceWrapper(content, options, rawKeyChain, rawSources) {
|
|
482
|
+
const sources = createCleanSources(rawSources);
|
|
483
|
+
if (!sources) {
|
|
484
|
+
return content;
|
|
485
|
+
}
|
|
486
|
+
return html `
|
|
487
|
+
${createSourceTrigger(content, options, rawKeyChain, rawSources)}
|
|
488
|
+
${createExpandingSource(options, rawKeyChain, rawSources)}
|
|
489
|
+
`;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Makes a chain key used to track which HTML sections are opened.
|
|
493
|
+
*
|
|
494
|
+
* @category Internal
|
|
495
|
+
*/
|
|
496
|
+
export function makeChainKey(keyChain) {
|
|
497
|
+
return [
|
|
498
|
+
'key',
|
|
499
|
+
...keyChain,
|
|
500
|
+
]
|
|
501
|
+
.join(';')
|
|
502
|
+
.replaceAll(' ', '_')
|
|
503
|
+
.replaceAll(/[^\w;]/g, '');
|
|
504
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
|
+
import { OutputImageType } from './browser-rendering.js';
|
|
3
|
+
import { type RenderInput, type RenderMarkdownOptions } from './render-types.js';
|
|
4
|
+
/**
|
|
5
|
+
* Render to an image. Only works in Node.js, not a browser.
|
|
6
|
+
*
|
|
7
|
+
* @category Render
|
|
8
|
+
* @returns The output file path.
|
|
9
|
+
*/
|
|
10
|
+
export declare function renderToNodeImage(structuredRenderData: Readonly<RenderInput>, params: Readonly<{
|
|
11
|
+
saveLocationPath: string;
|
|
12
|
+
options?: PartialWithUndefined<RenderMarkdownOptions> | undefined;
|
|
13
|
+
}>): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Render to an image. Only works in a browser, not Node.js.
|
|
16
|
+
*
|
|
17
|
+
* @category Render
|
|
18
|
+
*/
|
|
19
|
+
export declare function renderToBrowserImage(structuredRenderData: Readonly<RenderInput>, { imageOutputType, ...params }: Readonly<{
|
|
20
|
+
fileName: string;
|
|
21
|
+
} & PartialWithUndefined<{
|
|
22
|
+
options: PartialWithUndefined<RenderMarkdownOptions>;
|
|
23
|
+
imageOutputType: OutputImageType;
|
|
24
|
+
}>>): Promise<unknown>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { isRuntimeEnv, RuntimeEnv } from '@augment-vir/common';
|
|
2
|
+
import { OutputImageType, renderInBrowser, renderInNode } from './browser-rendering.js';
|
|
3
|
+
/**
|
|
4
|
+
* Render to an image. Only works in Node.js, not a browser.
|
|
5
|
+
*
|
|
6
|
+
* @category Render
|
|
7
|
+
* @returns The output file path.
|
|
8
|
+
*/
|
|
9
|
+
export async function renderToNodeImage(structuredRenderData, params) {
|
|
10
|
+
if (isRuntimeEnv(RuntimeEnv.Web)) {
|
|
11
|
+
throw new Error(`${renderToNodeImage.name} cannot run inside of a browser.`);
|
|
12
|
+
}
|
|
13
|
+
return await renderInNode(structuredRenderData, {
|
|
14
|
+
outputType: {
|
|
15
|
+
image: true,
|
|
16
|
+
},
|
|
17
|
+
...params,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Render to an image. Only works in a browser, not Node.js.
|
|
22
|
+
*
|
|
23
|
+
* @category Render
|
|
24
|
+
*/
|
|
25
|
+
export async function renderToBrowserImage(structuredRenderData, { imageOutputType, ...params }) {
|
|
26
|
+
if (!isRuntimeEnv(RuntimeEnv.Web)) {
|
|
27
|
+
throw new Error(`${renderToBrowserImage.name} cannot run outside of a browser.`);
|
|
28
|
+
}
|
|
29
|
+
return renderInBrowser(structuredRenderData, {
|
|
30
|
+
outputType: {
|
|
31
|
+
image: imageOutputType || OutputImageType.Download,
|
|
32
|
+
},
|
|
33
|
+
...params,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type PartialWithUndefined } from '@augment-vir/common';
|
|
2
|
+
import { CSSResult } from 'element-vir';
|
|
3
|
+
import { type SingleCssVarDefinition } from 'lit-css-vars';
|
|
4
|
+
/**
|
|
5
|
+
* The id attached to the content div which will be rendered to the PDF or image. Use this to create
|
|
6
|
+
* style selectors.
|
|
7
|
+
*
|
|
8
|
+
* @category Internal
|
|
9
|
+
*/
|
|
10
|
+
export declare const contentDivClass = "structured-rendering-markdown-rendering-content-for-screenshot";
|
|
11
|
+
/**
|
|
12
|
+
* Base CSS reset styles that are always applied to the content div, regardless of custom style
|
|
13
|
+
* overrides. These ensure no unwanted whitespace from default browser margins on the first and last
|
|
14
|
+
* child elements.
|
|
15
|
+
*
|
|
16
|
+
* @category Internal
|
|
17
|
+
*/
|
|
18
|
+
export declare const baseContentResetStyles = "\n.structured-rendering-markdown-rendering-content-for-screenshot > *:first-child {\n margin-top: 0;\n}\n.structured-rendering-markdown-rendering-content-for-screenshot > *:last-child {\n margin-bottom: 0;\n}\n";
|
|
19
|
+
/**
|
|
20
|
+
* The standard rendering style configuration.
|
|
21
|
+
*
|
|
22
|
+
* @category Internal
|
|
23
|
+
*/
|
|
24
|
+
export declare const defaultMarkdownStyleConfiguration: {
|
|
25
|
+
accentColor: string;
|
|
26
|
+
bodySize: string;
|
|
27
|
+
h1Size: string;
|
|
28
|
+
h2Size: string;
|
|
29
|
+
h3Size: string;
|
|
30
|
+
h4Size: string;
|
|
31
|
+
h5Size: string;
|
|
32
|
+
h6Size: string;
|
|
33
|
+
bodyGap: string;
|
|
34
|
+
smallTextSize: string;
|
|
35
|
+
liSpacing: string;
|
|
36
|
+
bodyFont: string;
|
|
37
|
+
codeFont: string;
|
|
38
|
+
codeSize: string;
|
|
39
|
+
codeBackgroundColor: CSSResult;
|
|
40
|
+
/** The selector used that all styles will be applied to. */
|
|
41
|
+
contentSelector: string;
|
|
42
|
+
tableBorderColor: CSSResult;
|
|
43
|
+
tableBorderWidth: string;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* The standard rendering style configuration.
|
|
47
|
+
*
|
|
48
|
+
* @category Internal
|
|
49
|
+
*/
|
|
50
|
+
export type MarkdownStyleConfiguration = Record<keyof typeof defaultMarkdownStyleConfiguration, string | CSSResult | SingleCssVarDefinition>;
|
|
51
|
+
/**
|
|
52
|
+
* Default plain styles for markdown converted to HTML.
|
|
53
|
+
*
|
|
54
|
+
* @category Internal
|
|
55
|
+
*/
|
|
56
|
+
export declare const defaultMarkdownRenderStyles: CSSResult;
|
|
57
|
+
/**
|
|
58
|
+
* Configure a stylesheet for rendering.
|
|
59
|
+
*
|
|
60
|
+
* @category Internal
|
|
61
|
+
*/
|
|
62
|
+
export declare function configureDefaultMarkdownRenderStyles(styleOptions?: PartialWithUndefined<MarkdownStyleConfiguration> | undefined): CSSResult;
|