@bendyline/squisq-formats 1.2.3 → 1.3.0
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/dist/__tests__/html.test.js +78 -4
- package/dist/__tests__/html.test.js.map +1 -1
- package/dist/__tests__/pdfExport.test.js +1 -1
- package/dist/__tests__/pdfExport.test.js.map +1 -1
- package/dist/__tests__/plainHtml.test.d.ts +5 -0
- package/dist/__tests__/plainHtml.test.d.ts.map +1 -0
- package/dist/__tests__/plainHtml.test.js +327 -0
- package/dist/__tests__/plainHtml.test.js.map +1 -0
- package/dist/__tests__/plainHtmlBundle.test.d.ts +11 -0
- package/dist/__tests__/plainHtmlBundle.test.d.ts.map +1 -0
- package/dist/__tests__/plainHtmlBundle.test.js +210 -0
- package/dist/__tests__/plainHtmlBundle.test.js.map +1 -0
- package/dist/chunk-33YRFXZZ.js +1187 -0
- package/dist/chunk-33YRFXZZ.js.map +1 -0
- package/dist/{chunk-EUQQYBZZ.js → chunk-ERZ627GR.js} +4 -4
- package/dist/chunk-ERZ627GR.js.map +1 -0
- package/dist/{chunk-MEZF76JA.js → chunk-UDS45KUJ.js} +68 -25
- package/dist/chunk-UDS45KUJ.js.map +1 -0
- package/dist/{chunk-NGWHV77G.js → chunk-VN2KEOYB.js} +7 -6
- package/dist/chunk-VN2KEOYB.js.map +1 -0
- package/dist/docx/export.d.ts.map +1 -1
- package/dist/docx/export.js +153 -22
- package/dist/docx/export.js.map +1 -1
- package/dist/epub/export.js +3 -3
- package/dist/epub/export.js.map +1 -1
- package/dist/html/docsHtmlBundle.d.ts +53 -0
- package/dist/html/docsHtmlBundle.d.ts.map +1 -0
- package/dist/html/docsHtmlBundle.js +299 -0
- package/dist/html/docsHtmlBundle.js.map +1 -0
- package/dist/html/htmlTemplate.d.ts.map +1 -1
- package/dist/html/htmlTemplate.js +43 -0
- package/dist/html/htmlTemplate.js.map +1 -1
- package/dist/html/index.d.ts +6 -0
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +31 -3
- package/dist/html/index.js.map +1 -1
- package/dist/html/plainHtml.d.ts +79 -0
- package/dist/html/plainHtml.d.ts.map +1 -0
- package/dist/html/plainHtml.js +614 -0
- package/dist/html/plainHtml.js.map +1 -0
- package/dist/html/plainHtmlBundle.d.ts +93 -0
- package/dist/html/plainHtmlBundle.d.ts.map +1 -0
- package/dist/html/plainHtmlBundle.js +357 -0
- package/dist/html/plainHtmlBundle.js.map +1 -0
- package/dist/pptx/export.d.ts.map +1 -1
- package/dist/pptx/export.js +10 -8
- package/dist/pptx/export.js.map +1 -1
- package/package.json +3 -2
- package/src/__tests__/html.test.ts +82 -4
- package/src/__tests__/pdfExport.test.ts +1 -1
- package/src/__tests__/plainHtml.test.ts +372 -0
- package/src/__tests__/plainHtmlBundle.test.ts +235 -0
- package/src/docx/export.ts +163 -22
- package/src/epub/export.ts +3 -3
- package/src/html/docsHtmlBundle.ts +369 -0
- package/src/html/htmlTemplate.ts +40 -0
- package/src/html/index.ts +32 -3
- package/src/html/plainHtml.ts +736 -0
- package/src/html/plainHtmlBundle.ts +419 -0
- package/src/pptx/export.ts +10 -9
- package/dist/chunk-EUQQYBZZ.js.map +0 -1
- package/dist/chunk-MEZF76JA.js.map +0 -1
- package/dist/chunk-NGWHV77G.js.map +0 -1
- package/dist/chunk-UM5V2XZG.js +0 -242
- package/dist/chunk-UM5V2XZG.js.map +0 -1
|
@@ -0,0 +1,614 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain HTML Export — semantic, player-free
|
|
3
|
+
*
|
|
4
|
+
* Renders a MarkdownDocument to a self-contained HTML string. Unlike
|
|
5
|
+
* `docToHtml` (which bundles the SquisqPlayer IIFE and renders SVG block
|
|
6
|
+
* cards), this output is what a reader-mode tool would produce: semantic
|
|
7
|
+
* `<h1>`/`<p>`/`<ul>`/etc. with a small embedded stylesheet, no JS, no
|
|
8
|
+
* runtime path-rewriting. Drives both the "Page" preview tab in the
|
|
9
|
+
* editor and the plain-style branch of the export dialog so what users
|
|
10
|
+
* see live matches the file they download.
|
|
11
|
+
*
|
|
12
|
+
* Image URLs default to the markdown's own paths. Pass `images` to
|
|
13
|
+
* substitute a different value per source URL — typically pre-resolved
|
|
14
|
+
* blob URLs (live preview) or data URIs (single-file export).
|
|
15
|
+
*/
|
|
16
|
+
import { resolveFontFamily, buildGoogleFontsUrl, resolveTheme } from '@bendyline/squisq/schemas';
|
|
17
|
+
// ── Public API ─────────────────────────────────────────────────────
|
|
18
|
+
/**
|
|
19
|
+
* Render a parsed markdown document as a complete, semantic HTML page.
|
|
20
|
+
*
|
|
21
|
+
* When `options.theme` is provided, the output adopts the theme's
|
|
22
|
+
* colors and typography. Google-hosted fonts referenced by the theme
|
|
23
|
+
* are loaded via a single `<link>` to fonts.googleapis.com so the page
|
|
24
|
+
* renders consistently when opened standalone.
|
|
25
|
+
*/
|
|
26
|
+
export function markdownDocToPlainHtml(doc, options = {}) {
|
|
27
|
+
const { title = 'Document', images, links, themeId, iconsCss } = options;
|
|
28
|
+
// Fall back chain for theme: explicit `theme` → explicit `themeId`
|
|
29
|
+
// option → doc frontmatter `themeId`. Hosts whose export dialog
|
|
30
|
+
// tracks themes by id can pass `themeId` straight through; authored
|
|
31
|
+
// docs with `themeId: warm-earth` in frontmatter get styled
|
|
32
|
+
// automatically when neither is supplied.
|
|
33
|
+
const theme = options.theme ??
|
|
34
|
+
(themeId ? resolveTheme(themeId) : undefined) ??
|
|
35
|
+
(typeof doc.frontmatter?.themeId === 'string'
|
|
36
|
+
? resolveTheme(doc.frontmatter.themeId)
|
|
37
|
+
: undefined);
|
|
38
|
+
const ctx = { images, links };
|
|
39
|
+
const body = renderTopLevel(doc.children, ctx);
|
|
40
|
+
const fontsLink = theme ? renderFontsLink(theme) : '';
|
|
41
|
+
// Resolve how to load FontAwesome — only when the doc actually uses
|
|
42
|
+
// icons. When the host supplies `iconsCss` (typical for sandboxed
|
|
43
|
+
// iframe previews where cross-origin font fetches get blocked), we
|
|
44
|
+
// inline it as a `<style>` block; otherwise we fall back to the
|
|
45
|
+
// public cdnjs `<link>` which works for standalone HTML files.
|
|
46
|
+
const usesIcons = docUsesIcons(doc);
|
|
47
|
+
let iconsLink = '';
|
|
48
|
+
if (usesIcons) {
|
|
49
|
+
iconsLink = iconsCss ? `<style data-fa-inline>\n${iconsCss}\n</style>\n` : FONT_AWESOME_LINK;
|
|
50
|
+
}
|
|
51
|
+
const themedCss = theme ? renderThemedCss(theme) : DEFAULT_CSS;
|
|
52
|
+
return `<!DOCTYPE html>
|
|
53
|
+
<html lang="en">
|
|
54
|
+
<head>
|
|
55
|
+
<meta charset="UTF-8">
|
|
56
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
57
|
+
<title>${escapeHtml(title)}</title>
|
|
58
|
+
${fontsLink}${iconsLink}<style>
|
|
59
|
+
${themedCss}
|
|
60
|
+
${FEATURE_CSS}
|
|
61
|
+
</style>
|
|
62
|
+
</head>
|
|
63
|
+
<body>
|
|
64
|
+
${body}
|
|
65
|
+
</body>
|
|
66
|
+
</html>`;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Hosted FontAwesome Free CSS. Pinned to a specific release so the
|
|
70
|
+
* integrity hash stays in sync — bump both fields together when
|
|
71
|
+
* upgrading. Cdnjs serves the matching SRI hash on every release page.
|
|
72
|
+
*/
|
|
73
|
+
const FONT_AWESOME_LINK = `<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css" integrity="sha512-SnH5WK+bZxgPHs44uWIX+LLJAJ9/2PkPKZ5QiAj6Ta86w+fsb2TkcmfRyVX3pBnMFcV7oQPJkl9QevSCWr3W6A==" crossorigin="anonymous" referrerpolicy="no-referrer">
|
|
74
|
+
`;
|
|
75
|
+
/** Walk the doc looking for any `inlineIcon` node. Cheap depth-first
|
|
76
|
+
* traversal — bails out at the first hit. */
|
|
77
|
+
function docUsesIcons(doc) {
|
|
78
|
+
function visit(node) {
|
|
79
|
+
if (!node || typeof node !== 'object')
|
|
80
|
+
return false;
|
|
81
|
+
const n = node;
|
|
82
|
+
if (n.type === 'inlineIcon')
|
|
83
|
+
return true;
|
|
84
|
+
if (Array.isArray(n.children)) {
|
|
85
|
+
for (const child of n.children)
|
|
86
|
+
if (visit(child))
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
return visit(doc);
|
|
92
|
+
}
|
|
93
|
+
// ── Top-level walk with feature-section grouping ───────────────────
|
|
94
|
+
/**
|
|
95
|
+
* Walk the document's top-level children, grouping headings that carry
|
|
96
|
+
* a `leftFeature` / `rightFeature` template annotation with the body
|
|
97
|
+
* blocks that follow them (up to the next sibling-or-higher heading).
|
|
98
|
+
* Each group renders as a single `<section class="squisq-feature ...">`
|
|
99
|
+
* with a media column and a text column — the plain-HTML analogue of
|
|
100
|
+
* the SVG layer layout produced by `getLayers` for the same templates.
|
|
101
|
+
*/
|
|
102
|
+
function renderTopLevel(children, ctx) {
|
|
103
|
+
const out = [];
|
|
104
|
+
for (let i = 0; i < children.length; i++) {
|
|
105
|
+
const node = children[i];
|
|
106
|
+
if (node && node.type === 'heading') {
|
|
107
|
+
const heading = node;
|
|
108
|
+
const tpl = heading.templateAnnotation?.template;
|
|
109
|
+
if (tpl === 'leftFeature' || tpl === 'rightFeature') {
|
|
110
|
+
const end = findSectionEnd(children, i);
|
|
111
|
+
const sectionBody = children.slice(i + 1, end);
|
|
112
|
+
out.push(renderFeatureSection(heading, sectionBody, tpl, ctx));
|
|
113
|
+
i = end - 1;
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
out.push(nodeToHtml(node, ctx));
|
|
118
|
+
}
|
|
119
|
+
return out.join('\n');
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Index of the next heading after `from`; otherwise the array length.
|
|
123
|
+
* Feature sections greedily eat the heading's immediate body content
|
|
124
|
+
* (paragraphs, lists, images) up to the next heading of any depth — a
|
|
125
|
+
* nested sub-heading inside a feature would look chaotic in the
|
|
126
|
+
* side-by-side layout, so we keep features short by design.
|
|
127
|
+
*/
|
|
128
|
+
function findSectionEnd(nodes, from) {
|
|
129
|
+
for (let i = from + 1; i < nodes.length; i++) {
|
|
130
|
+
const n = nodes[i];
|
|
131
|
+
if (n && n.type === 'heading')
|
|
132
|
+
return i;
|
|
133
|
+
}
|
|
134
|
+
return nodes.length;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Render a feature section as `<section class="squisq-feature ...">`.
|
|
138
|
+
* The first image found in the body becomes the media column; the
|
|
139
|
+
* heading + remaining content (with the image stripped, so it doesn't
|
|
140
|
+
* appear twice) becomes the text column.
|
|
141
|
+
*/
|
|
142
|
+
function renderFeatureSection(heading, bodyNodes, side, ctx) {
|
|
143
|
+
const headingTag = `h${Math.min(Math.max(heading.depth ?? 2, 1), 6)}`;
|
|
144
|
+
const headingHtml = `<${headingTag}>${childrenToHtml({ children: heading.children }, ctx)}</${headingTag}>`;
|
|
145
|
+
const featured = takeFirstImage(bodyNodes);
|
|
146
|
+
const media = featured.image
|
|
147
|
+
? renderFeatureImage(featured.image, ctx)
|
|
148
|
+
: '<div class="squisq-feature__media squisq-feature__media--empty"></div>';
|
|
149
|
+
const textHtml = [headingHtml, ...featured.remaining.map((n) => nodeToHtml(n, ctx))]
|
|
150
|
+
.filter((s) => s.length > 0)
|
|
151
|
+
.join('\n');
|
|
152
|
+
const sideClass = side === 'leftFeature' ? 'squisq-feature--left' : 'squisq-feature--right';
|
|
153
|
+
return `<section class="squisq-feature ${sideClass}">
|
|
154
|
+
${media}
|
|
155
|
+
<div class="squisq-feature__body">
|
|
156
|
+
${textHtml}
|
|
157
|
+
</div>
|
|
158
|
+
</section>`;
|
|
159
|
+
}
|
|
160
|
+
function renderFeatureImage(img, ctx) {
|
|
161
|
+
const resolved = ctx?.images?.get(img.src) ?? img.src;
|
|
162
|
+
const attrs = [`src="${escapeAttr(resolved)}"`, `alt="${escapeAttr(img.alt)}"`];
|
|
163
|
+
// Emit `width` / `height` attributes only when the source HTML had
|
|
164
|
+
// them. The CSS rules then know to honor those values rather than
|
|
165
|
+
// stretching the image to fill the column.
|
|
166
|
+
if (typeof img.width === 'number')
|
|
167
|
+
attrs.push(`width="${img.width}"`);
|
|
168
|
+
if (typeof img.height === 'number')
|
|
169
|
+
attrs.push(`height="${img.height}"`);
|
|
170
|
+
const sizedClass = typeof img.width === 'number' || typeof img.height === 'number'
|
|
171
|
+
? ' squisq-feature__media--sized'
|
|
172
|
+
: '';
|
|
173
|
+
return `<div class="squisq-feature__media${sizedClass}"><img ${attrs.join(' ')} /></div>`;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Pull the first image reference out of a section's body — either a
|
|
177
|
+
* markdown `image` node (possibly nested inside a paragraph) or a raw
|
|
178
|
+
* HTML `<img>` (the WYSIWYG editor emits these for resized images).
|
|
179
|
+
* Returns the image plus the body with that image removed (so it's not
|
|
180
|
+
* rendered a second time inside the text column).
|
|
181
|
+
*/
|
|
182
|
+
function takeFirstImage(nodes) {
|
|
183
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
184
|
+
const found = extractFirstImageFromBlock(nodes[i]);
|
|
185
|
+
if (!found)
|
|
186
|
+
continue;
|
|
187
|
+
const remaining = [...nodes];
|
|
188
|
+
if (found.replacement === null) {
|
|
189
|
+
remaining.splice(i, 1);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
remaining[i] = found.replacement;
|
|
193
|
+
}
|
|
194
|
+
return { image: found.image, remaining };
|
|
195
|
+
}
|
|
196
|
+
return { image: null, remaining: nodes };
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Look for the first image inside a single block node. If the block is
|
|
200
|
+
* a paragraph that contains only the image (with optional whitespace),
|
|
201
|
+
* we drop the whole paragraph; if there's surrounding text, we strip
|
|
202
|
+
* the image from the paragraph's inline children and keep the rest.
|
|
203
|
+
* For raw `<img>` html blocks we drop the block entirely.
|
|
204
|
+
*/
|
|
205
|
+
function extractFirstImageFromBlock(block) {
|
|
206
|
+
if (!block || typeof block !== 'object')
|
|
207
|
+
return null;
|
|
208
|
+
const b = block;
|
|
209
|
+
if (b.type === 'paragraph' && Array.isArray(b.children)) {
|
|
210
|
+
const kids = b.children;
|
|
211
|
+
const imgIdx = kids.findIndex((k) => k.type === 'image' &&
|
|
212
|
+
typeof k.url === 'string');
|
|
213
|
+
if (imgIdx >= 0) {
|
|
214
|
+
const img = kids[imgIdx];
|
|
215
|
+
const remainingKids = [...kids.slice(0, imgIdx), ...kids.slice(imgIdx + 1)].filter((k) => !isBlankInline(k));
|
|
216
|
+
const replacement = remainingKids.length === 0
|
|
217
|
+
? null
|
|
218
|
+
: { ...b, children: remainingKids };
|
|
219
|
+
return {
|
|
220
|
+
image: { src: img.url, alt: img.alt ?? '' },
|
|
221
|
+
replacement,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (b.type === 'htmlBlock' && Array.isArray(b.htmlChildren)) {
|
|
226
|
+
const hit = findHtmlImg(b.htmlChildren);
|
|
227
|
+
if (hit)
|
|
228
|
+
return { image: hit, replacement: null };
|
|
229
|
+
}
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
function isBlankInline(node) {
|
|
233
|
+
if (!node || typeof node !== 'object')
|
|
234
|
+
return false;
|
|
235
|
+
const n = node;
|
|
236
|
+
return n.type === 'text' && typeof n.value === 'string' && n.value.trim().length === 0;
|
|
237
|
+
}
|
|
238
|
+
function findHtmlImg(nodes) {
|
|
239
|
+
for (const n of nodes) {
|
|
240
|
+
if (n.type !== 'htmlElement')
|
|
241
|
+
continue;
|
|
242
|
+
if (n.tagName.toLowerCase() === 'img') {
|
|
243
|
+
const src = n.attributes.src;
|
|
244
|
+
if (typeof src === 'string' && src) {
|
|
245
|
+
return {
|
|
246
|
+
src,
|
|
247
|
+
alt: typeof n.attributes.alt === 'string' ? n.attributes.alt : '',
|
|
248
|
+
width: parseHtmlDim(n.attributes.width),
|
|
249
|
+
height: parseHtmlDim(n.attributes.height),
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
const nested = findHtmlImg(n.children);
|
|
254
|
+
if (nested)
|
|
255
|
+
return nested;
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
function parseHtmlDim(raw) {
|
|
260
|
+
if (raw === undefined)
|
|
261
|
+
return undefined;
|
|
262
|
+
const n = parseFloat(raw);
|
|
263
|
+
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
264
|
+
}
|
|
265
|
+
const FEATURE_CSS = ` .squisq-feature {
|
|
266
|
+
display: flex;
|
|
267
|
+
flex-wrap: wrap;
|
|
268
|
+
gap: 1.5em;
|
|
269
|
+
align-items: center;
|
|
270
|
+
margin: 1.75em 0;
|
|
271
|
+
}
|
|
272
|
+
.squisq-feature--right { flex-direction: row-reverse; }
|
|
273
|
+
.squisq-feature__media {
|
|
274
|
+
flex: 0 0 42%;
|
|
275
|
+
min-width: 0;
|
|
276
|
+
}
|
|
277
|
+
.squisq-feature__media--empty { display: none; }
|
|
278
|
+
/* Default: image fills the media column. */
|
|
279
|
+
.squisq-feature__media img {
|
|
280
|
+
width: 100%;
|
|
281
|
+
height: auto;
|
|
282
|
+
display: block;
|
|
283
|
+
border-radius: 6px;
|
|
284
|
+
}
|
|
285
|
+
/* "Sized" media: the image carried explicit width/height attrs (the
|
|
286
|
+
WYSIWYG editor wrote them after a resize). Honor the attribute
|
|
287
|
+
values and center the image inside the media column with padding. */
|
|
288
|
+
.squisq-feature__media--sized {
|
|
289
|
+
display: flex;
|
|
290
|
+
align-items: center;
|
|
291
|
+
justify-content: center;
|
|
292
|
+
padding: 1em;
|
|
293
|
+
box-sizing: border-box;
|
|
294
|
+
}
|
|
295
|
+
/* Leave width and height untouched here -- the HTML attributes set
|
|
296
|
+
the intrinsic dimensions, and CSS overrides would silently discard
|
|
297
|
+
the author's sizing. max-width: 100% still keeps the image from
|
|
298
|
+
overflowing the column on narrow viewports; HTML5 derives the
|
|
299
|
+
aspect ratio from the width/height pair so the scale stays right. */
|
|
300
|
+
.squisq-feature__media--sized img {
|
|
301
|
+
max-width: 100%;
|
|
302
|
+
display: block;
|
|
303
|
+
border-radius: 6px;
|
|
304
|
+
}
|
|
305
|
+
.squisq-feature__body {
|
|
306
|
+
flex: 1 1 0;
|
|
307
|
+
min-width: 0;
|
|
308
|
+
}
|
|
309
|
+
.squisq-feature__body > :first-child { margin-top: 0; }
|
|
310
|
+
.squisq-feature__body > :last-child { margin-bottom: 0; }
|
|
311
|
+
@media (max-width: 600px) {
|
|
312
|
+
.squisq-feature, .squisq-feature--right { flex-direction: column; }
|
|
313
|
+
.squisq-feature__media { flex-basis: auto; width: 100%; }
|
|
314
|
+
}`;
|
|
315
|
+
// ── Theme-driven CSS ───────────────────────────────────────────────
|
|
316
|
+
const DEFAULT_CSS = ` body { font-family: system-ui, -apple-system, sans-serif; max-width: 800px; margin: 2em auto; padding: 0 1em; line-height: 1.6; color: #1f2937; }
|
|
317
|
+
h1, h2, h3, h4, h5, h6 { margin-top: 1.5em; margin-bottom: 0.5em; }
|
|
318
|
+
pre { background: #f3f4f6; padding: 1em; border-radius: 4px; overflow-x: auto; }
|
|
319
|
+
code { background: #f3f4f6; padding: 0.15em 0.3em; border-radius: 3px; font-size: 0.9em; }
|
|
320
|
+
pre code { background: none; padding: 0; }
|
|
321
|
+
blockquote { border-left: 3px solid #d1d5db; margin-left: 0; padding-left: 1em; color: #6b7280; }
|
|
322
|
+
/* Images: cap at the container width so nothing overflows, but only
|
|
323
|
+
force aspect-ratio height when the author didn't set explicit
|
|
324
|
+
dimensions on the <img> tag. The WYSIWYG editor writes width/height
|
|
325
|
+
attributes after a resize — overriding them here would silently
|
|
326
|
+
ignore the user's sizing. */
|
|
327
|
+
img { max-width: 100%; }
|
|
328
|
+
img:not([width]):not([height]) { height: auto; }
|
|
329
|
+
a { color: #3b82f6; }
|
|
330
|
+
table { border-collapse: collapse; width: 100%; margin: 1em 0; }
|
|
331
|
+
th, td { border: 1px solid #d1d5db; padding: 6px 10px; text-align: left; }
|
|
332
|
+
th { background: #f3f4f6; font-weight: 600; }
|
|
333
|
+
hr { border: none; border-top: 1px solid #d1d5db; margin: 1.5em 0; }`;
|
|
334
|
+
/**
|
|
335
|
+
* Build the stylesheet for a themed page. We resolve fonts and colors
|
|
336
|
+
* to CSS-ready strings up front (rather than emitting `--squisq-*`
|
|
337
|
+
* custom properties everywhere) so the output works in environments
|
|
338
|
+
* that strip CSS variables.
|
|
339
|
+
*/
|
|
340
|
+
function renderThemedCss(theme) {
|
|
341
|
+
const bodyFamily = resolveFontFamily(theme.typography.bodyFont, 'system-ui, sans-serif');
|
|
342
|
+
const titleFamily = resolveFontFamily(theme.typography.titleFont, 'Georgia, serif');
|
|
343
|
+
const monoFamily = resolveFontFamily(theme.typography.monoFont, 'Consolas, monospace');
|
|
344
|
+
const lineHeight = theme.typography.lineHeight ?? 1.6;
|
|
345
|
+
const titleLineHeight = theme.typography.titleLineHeight ?? 1.25;
|
|
346
|
+
const titleWeight = theme.typography.titleWeight === 'normal' ? 400 : 700;
|
|
347
|
+
const c = theme.colors;
|
|
348
|
+
// A few derived colors so the page doesn't end up unreadable on
|
|
349
|
+
// themes that swing dark (most code/table chrome reads as "dim panel
|
|
350
|
+
// on background"). We do this in CSS, not in JS, by mixing with
|
|
351
|
+
// `color-mix` so older browsers without it still get a sensible look.
|
|
352
|
+
return ` :root {
|
|
353
|
+
--plain-bg: ${c.background};
|
|
354
|
+
--plain-text: ${c.text};
|
|
355
|
+
--plain-muted: ${c.textMuted};
|
|
356
|
+
--plain-primary: ${c.primary};
|
|
357
|
+
--plain-secondary: ${c.secondary};
|
|
358
|
+
--plain-accent: ${c.highlight};
|
|
359
|
+
--plain-bg-light: ${c.backgroundLight};
|
|
360
|
+
--plain-body-font: ${bodyFamily};
|
|
361
|
+
--plain-title-font: ${titleFamily};
|
|
362
|
+
--plain-mono-font: ${monoFamily};
|
|
363
|
+
}
|
|
364
|
+
body {
|
|
365
|
+
font-family: var(--plain-body-font);
|
|
366
|
+
max-width: 800px;
|
|
367
|
+
margin: 2em auto;
|
|
368
|
+
padding: 0 1em;
|
|
369
|
+
line-height: ${lineHeight};
|
|
370
|
+
color: var(--plain-text);
|
|
371
|
+
background: var(--plain-bg);
|
|
372
|
+
}
|
|
373
|
+
h1, h2, h3, h4, h5, h6 {
|
|
374
|
+
font-family: var(--plain-title-font);
|
|
375
|
+
color: var(--plain-text);
|
|
376
|
+
margin-top: 1.5em;
|
|
377
|
+
margin-bottom: 0.5em;
|
|
378
|
+
line-height: ${titleLineHeight};
|
|
379
|
+
font-weight: ${titleWeight};
|
|
380
|
+
}
|
|
381
|
+
p { margin: 0.75em 0; }
|
|
382
|
+
pre {
|
|
383
|
+
background: var(--plain-bg-light);
|
|
384
|
+
padding: 1em;
|
|
385
|
+
border-radius: 4px;
|
|
386
|
+
overflow-x: auto;
|
|
387
|
+
font-family: var(--plain-mono-font);
|
|
388
|
+
}
|
|
389
|
+
code {
|
|
390
|
+
background: var(--plain-bg-light);
|
|
391
|
+
padding: 0.15em 0.3em;
|
|
392
|
+
border-radius: 3px;
|
|
393
|
+
font-size: 0.9em;
|
|
394
|
+
font-family: var(--plain-mono-font);
|
|
395
|
+
}
|
|
396
|
+
pre code { background: none; padding: 0; }
|
|
397
|
+
blockquote {
|
|
398
|
+
border-left: 3px solid var(--plain-primary);
|
|
399
|
+
margin-left: 0;
|
|
400
|
+
padding-left: 1em;
|
|
401
|
+
color: var(--plain-muted);
|
|
402
|
+
}
|
|
403
|
+
/* See DEFAULT_CSS comment: only auto-scale height when the author
|
|
404
|
+
didn't set explicit width/height attributes. */
|
|
405
|
+
img { max-width: 100%; }
|
|
406
|
+
img:not([width]):not([height]) { height: auto; }
|
|
407
|
+
/* Blend the theme primary toward the body text color so links stay
|
|
408
|
+
theme-flavored but read clearly on every theme's background — some
|
|
409
|
+
themes (e.g. Gezellig) pick a mid-tone primary that's almost
|
|
410
|
+
invisible on a dark page when used neat. Underline makes the link
|
|
411
|
+
unambiguous independent of the color contrast. */
|
|
412
|
+
a {
|
|
413
|
+
color: color-mix(in srgb, var(--plain-primary) 65%, var(--plain-text));
|
|
414
|
+
text-decoration: underline;
|
|
415
|
+
text-decoration-thickness: 1px;
|
|
416
|
+
text-underline-offset: 2px;
|
|
417
|
+
}
|
|
418
|
+
a:hover { color: var(--plain-accent); }
|
|
419
|
+
table { border-collapse: collapse; width: 100%; margin: 1em 0; }
|
|
420
|
+
th, td {
|
|
421
|
+
border: 1px solid color-mix(in srgb, var(--plain-muted) 30%, transparent);
|
|
422
|
+
padding: 6px 10px;
|
|
423
|
+
text-align: left;
|
|
424
|
+
}
|
|
425
|
+
th {
|
|
426
|
+
background: var(--plain-bg-light);
|
|
427
|
+
color: var(--plain-text);
|
|
428
|
+
font-family: var(--plain-title-font);
|
|
429
|
+
font-weight: 600;
|
|
430
|
+
}
|
|
431
|
+
hr {
|
|
432
|
+
border: none;
|
|
433
|
+
border-top: 1px solid color-mix(in srgb, var(--plain-muted) 40%, transparent);
|
|
434
|
+
margin: 1.5em 0;
|
|
435
|
+
}`;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Emit the `<link rel="stylesheet">` line(s) needed to load the theme's
|
|
439
|
+
* fonts. Empty string when nothing in the theme is hosted on Google
|
|
440
|
+
* Fonts (system stacks, custom self-hosted faces).
|
|
441
|
+
*/
|
|
442
|
+
function renderFontsLink(theme) {
|
|
443
|
+
const url = buildGoogleFontsUrl([
|
|
444
|
+
theme.typography.bodyFont,
|
|
445
|
+
theme.typography.titleFont,
|
|
446
|
+
theme.typography.monoFont,
|
|
447
|
+
]);
|
|
448
|
+
if (!url)
|
|
449
|
+
return '';
|
|
450
|
+
// Preconnect to Google's CDN to shave a roundtrip off the font load.
|
|
451
|
+
return `<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
452
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
453
|
+
<link rel="stylesheet" href="${escapeAttr(url)}">
|
|
454
|
+
`;
|
|
455
|
+
}
|
|
456
|
+
// ── Node → HTML ────────────────────────────────────────────────────
|
|
457
|
+
function nodeToHtml(node, ctx) {
|
|
458
|
+
if (!node)
|
|
459
|
+
return '';
|
|
460
|
+
switch (node.type) {
|
|
461
|
+
case 'heading': {
|
|
462
|
+
const depth = Math.min(Math.max(node.depth ?? 1, 1), 6);
|
|
463
|
+
return `<h${depth}>${childrenToHtml(node, ctx)}</h${depth}>`;
|
|
464
|
+
}
|
|
465
|
+
case 'paragraph':
|
|
466
|
+
return `<p>${childrenToHtml(node, ctx)}</p>`;
|
|
467
|
+
case 'text':
|
|
468
|
+
return escapeHtml(node.value ?? '');
|
|
469
|
+
case 'strong':
|
|
470
|
+
return `<strong>${childrenToHtml(node, ctx)}</strong>`;
|
|
471
|
+
case 'emphasis':
|
|
472
|
+
return `<em>${childrenToHtml(node, ctx)}</em>`;
|
|
473
|
+
case 'delete':
|
|
474
|
+
return `<del>${childrenToHtml(node, ctx)}</del>`;
|
|
475
|
+
case 'inlineCode':
|
|
476
|
+
return `<code>${escapeHtml(node.value ?? '')}</code>`;
|
|
477
|
+
case 'code': {
|
|
478
|
+
const lang = node.lang ? ` class="language-${escapeAttr(node.lang)}"` : '';
|
|
479
|
+
return `<pre><code${lang}>${escapeHtml(node.value ?? '')}</code></pre>`;
|
|
480
|
+
}
|
|
481
|
+
case 'blockquote':
|
|
482
|
+
return `<blockquote>${childrenToHtml(node, ctx)}</blockquote>`;
|
|
483
|
+
case 'list': {
|
|
484
|
+
const tag = node.ordered ? 'ol' : 'ul';
|
|
485
|
+
const start = node.ordered && typeof node.start === 'number' && node.start !== 1
|
|
486
|
+
? ` start="${node.start}"`
|
|
487
|
+
: '';
|
|
488
|
+
return `<${tag}${start}>${childrenToHtml(node, ctx)}</${tag}>`;
|
|
489
|
+
}
|
|
490
|
+
case 'listItem':
|
|
491
|
+
return `<li>${childrenToHtml(node, ctx)}</li>`;
|
|
492
|
+
case 'link': {
|
|
493
|
+
const original = node.url ?? '';
|
|
494
|
+
const rewritten = ctx?.links?.get(original) ?? original;
|
|
495
|
+
return `<a href="${escapeAttr(rewritten)}">${childrenToHtml(node, ctx)}</a>`;
|
|
496
|
+
}
|
|
497
|
+
case 'image': {
|
|
498
|
+
const original = node.url ?? '';
|
|
499
|
+
const resolved = ctx?.images?.get(original) ?? original;
|
|
500
|
+
return `<img src="${escapeAttr(resolved)}" alt="${escapeAttr(node.alt ?? '')}" />`;
|
|
501
|
+
}
|
|
502
|
+
case 'thematicBreak':
|
|
503
|
+
return '<hr />';
|
|
504
|
+
case 'table':
|
|
505
|
+
return tableToHtml(node, ctx);
|
|
506
|
+
case 'inlineIcon': {
|
|
507
|
+
// Render via FontAwesome's `fa-<family> fa-<name>` class pair.
|
|
508
|
+
// The `<link>` to the FA CSS is injected into <head> by
|
|
509
|
+
// `markdownDocToPlainHtml` when the doc contains any icon.
|
|
510
|
+
const family = escapeAttr(node.family ?? 'solid');
|
|
511
|
+
const name = escapeAttr(node.name ?? '');
|
|
512
|
+
const token = escapeAttr(node.token ?? `${node.family}:${node.name}`);
|
|
513
|
+
return `<i class="fa-${family} fa-${name}" data-icon="${token}" aria-hidden="true"></i>`;
|
|
514
|
+
}
|
|
515
|
+
case 'htmlBlock':
|
|
516
|
+
case 'htmlInline':
|
|
517
|
+
// Resized images and other authored HTML survive the round-trip
|
|
518
|
+
// as parsed `htmlChildren` — rewriting `<img src>` through the
|
|
519
|
+
// image map keeps the preview consistent with the markdown-image
|
|
520
|
+
// path. Other tags pass through unmodified.
|
|
521
|
+
return htmlChildrenToHtml(node.htmlChildren, ctx);
|
|
522
|
+
default: {
|
|
523
|
+
// Unknown / unhandled node — recurse into children if any so we
|
|
524
|
+
// don't drop content (e.g. directives, footnotes).
|
|
525
|
+
const withChildren = node;
|
|
526
|
+
if (Array.isArray(withChildren.children)) {
|
|
527
|
+
return childrenToHtml(node, ctx);
|
|
528
|
+
}
|
|
529
|
+
if (typeof withChildren.value === 'string') {
|
|
530
|
+
return escapeHtml(withChildren.value);
|
|
531
|
+
}
|
|
532
|
+
return '';
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
function childrenToHtml(node, ctx) {
|
|
537
|
+
if (!node.children)
|
|
538
|
+
return node.value ? escapeHtml(node.value) : '';
|
|
539
|
+
return node.children.map((child) => nodeToHtml(child, ctx)).join('');
|
|
540
|
+
}
|
|
541
|
+
function tableToHtml(node, ctx) {
|
|
542
|
+
const [headerRow, ...bodyRows] = node.children;
|
|
543
|
+
const parts = ['<table>'];
|
|
544
|
+
if (headerRow) {
|
|
545
|
+
parts.push('<thead><tr>');
|
|
546
|
+
for (const cell of headerRow.children) {
|
|
547
|
+
parts.push(`<th>${childrenToHtml(cell, ctx)}</th>`);
|
|
548
|
+
}
|
|
549
|
+
parts.push('</tr></thead>');
|
|
550
|
+
}
|
|
551
|
+
if (bodyRows.length > 0) {
|
|
552
|
+
parts.push('<tbody>');
|
|
553
|
+
for (const row of bodyRows) {
|
|
554
|
+
parts.push('<tr>');
|
|
555
|
+
for (const cell of row.children) {
|
|
556
|
+
parts.push(`<td>${childrenToHtml(cell, ctx)}</td>`);
|
|
557
|
+
}
|
|
558
|
+
parts.push('</tr>');
|
|
559
|
+
}
|
|
560
|
+
parts.push('</tbody>');
|
|
561
|
+
}
|
|
562
|
+
parts.push('</table>');
|
|
563
|
+
return parts.join('');
|
|
564
|
+
}
|
|
565
|
+
function htmlChildrenToHtml(nodes, ctx) {
|
|
566
|
+
if (!nodes || nodes.length === 0)
|
|
567
|
+
return '';
|
|
568
|
+
const out = [];
|
|
569
|
+
for (const node of nodes) {
|
|
570
|
+
if (node.type === 'htmlText') {
|
|
571
|
+
// HtmlText already represents authored HTML — emit verbatim so
|
|
572
|
+
// entity references the user wrote (e.g. `&`) survive.
|
|
573
|
+
out.push(node.value);
|
|
574
|
+
continue;
|
|
575
|
+
}
|
|
576
|
+
if (node.type === 'htmlComment') {
|
|
577
|
+
out.push(`<!--${node.value}-->`);
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
// htmlElement
|
|
581
|
+
const tag = node.tagName.toLowerCase();
|
|
582
|
+
const attrs = { ...node.attributes };
|
|
583
|
+
// Route media `src` attrs through the export's `ctx.images` URL
|
|
584
|
+
// map (which is actually a generic media map — see header comment).
|
|
585
|
+
// Without this, raw <video>/<audio> tags inserted by the recorder
|
|
586
|
+
// ship as relative paths that resolve against the export host, not
|
|
587
|
+
// the original ContentContainer.
|
|
588
|
+
if ((tag === 'img' || tag === 'video' || tag === 'audio' || tag === 'source') &&
|
|
589
|
+
typeof attrs.src === 'string') {
|
|
590
|
+
attrs.src = ctx?.images?.get(attrs.src) ?? attrs.src;
|
|
591
|
+
}
|
|
592
|
+
if ((tag === 'video' || tag === 'audio') && typeof attrs.poster === 'string') {
|
|
593
|
+
attrs.poster = ctx?.images?.get(attrs.poster) ?? attrs.poster;
|
|
594
|
+
}
|
|
595
|
+
const attrStr = Object.entries(attrs)
|
|
596
|
+
.map(([k, v]) => ` ${k}="${escapeAttr(v)}"`)
|
|
597
|
+
.join('');
|
|
598
|
+
if (node.selfClosing) {
|
|
599
|
+
out.push(`<${tag}${attrStr} />`);
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
out.push(`<${tag}${attrStr}>${htmlChildrenToHtml(node.children, ctx)}</${tag}>`);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
return out.join('');
|
|
606
|
+
}
|
|
607
|
+
// ── Escaping ───────────────────────────────────────────────────────
|
|
608
|
+
function escapeHtml(s) {
|
|
609
|
+
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
610
|
+
}
|
|
611
|
+
function escapeAttr(s) {
|
|
612
|
+
return escapeHtml(s).replace(/"/g, '"');
|
|
613
|
+
}
|
|
614
|
+
//# sourceMappingURL=plainHtml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plainHtml.js","sourceRoot":"","sources":["../../src/html/plainHtml.ts"],"names":[],"mappings":"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"}
|