mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-11-04 04:30:40 +00:00
book(I2.1): GFM task lists + nested lists in pagination
marked switches to gfm:true everywhere (lexer + parser), unlocking: - Task lists — `- [ ] todo` / `- [x] done` parse as list items with task:true + checked:bool. The pagination engine emits ☐ / ☑ as the marker prefix (replacing the bullet) so paginated and preview output both render the checkbox state. - Nested lists — list items whose tokens contain an inner list recurse with a 3-space-per-level indent. Capped at depth 6 so pathological input can't blow the stack. - Autolinks + strikethrough — parsed by marked into the HTML preview pane (the pagination engine flattens to plain text so strike doesn't visually render in paginated tiles, but the inline preview shows it). Tables get a placeholder row in v1 — "[Table — N cols × M rows: …]" with a warning surfaced through pag.warnings. Full column layout ships in I2.2 once the renderer side (DOM + canvas + PDF emission) gains a per-cell branch. Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
a46d13f189
commit
5caf1d48cd
1 file changed
+34
-12
+34
-12
@@ -9897,7 +9897,7 @@
|
||||
padding,
|
||||
};
|
||||
|
||||
const tokens = window.marked.lexer(md);
|
||||
const tokens = window.marked.lexer(md, { gfm: true, breaks: false });
|
||||
|
||||
// One shared Canvas2D context for text-width measurement.
|
||||
// Sized at 96 px/inch so widths come out in pixels and we
|
||||
@@ -9989,16 +9989,38 @@
|
||||
// no wrapping (the user controls line lengths).
|
||||
lines = String(token.text || '').split('\n');
|
||||
} else if (token.type === 'list') {
|
||||
// Flatten list items into "• text" lines. Each item
|
||||
// wraps using the list style.
|
||||
const items = Array.isArray(token.items) ? token.items : [];
|
||||
const ordered = !!token.ordered;
|
||||
items.forEach((item, i) => {
|
||||
const marker = ordered ? `${i + 1}. ` : '• ';
|
||||
const text = String(item.text || '');
|
||||
const itemLines = wrapTextIntoLines(marker + text, availW);
|
||||
lines = lines.concat(itemLines);
|
||||
});
|
||||
// Flatten list items into prefixed lines. Task items get
|
||||
// ☐ / ☑ instead of the bullet; nested lists recurse with
|
||||
// a 3-space-per-level indent. Cap at 6 levels so a
|
||||
// pathological input can't blow the stack.
|
||||
const renderList = (listToken, depth) => {
|
||||
const items = Array.isArray(listToken.items) ? listToken.items : [];
|
||||
const ordered = !!listToken.ordered;
|
||||
items.forEach((item, i) => {
|
||||
const indent = ' '.repeat(Math.min(depth, 6));
|
||||
const marker = item.task
|
||||
? (item.checked ? '☑ ' : '☐ ')
|
||||
: (ordered ? `${i + 1}. ` : '• ');
|
||||
const text = String(item.text || '');
|
||||
const itemLines = wrapTextIntoLines(indent + marker + text, availW);
|
||||
lines = lines.concat(itemLines);
|
||||
if (depth < 6) {
|
||||
for (const inner of (item.tokens || [])) {
|
||||
if (inner?.type === 'list') renderList(inner, depth + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
renderList(token, 0);
|
||||
} else if (token.type === 'table') {
|
||||
// Tables get a placeholder row in v1 — proper column
|
||||
// layout lands in I2.2.
|
||||
const headerLabels = (token.header || [])
|
||||
.map(c => (c?.text || c?.tokens?.[0]?.text || c?.raw || '')).filter(Boolean);
|
||||
const rowCount = Array.isArray(token.rows) ? token.rows.length : 0;
|
||||
const summary = `[Table — ${headerLabels.length} cols × ${rowCount} rows: ${headerLabels.join(' · ')}]`;
|
||||
lines = wrapTextIntoLines(summary, availW);
|
||||
result.warnings.push(`Tables render as a placeholder in v1 — full layout in I2.2.`);
|
||||
} else if (token.type === 'blockquote') {
|
||||
// marked emits blockquote with inner tokens; concatenate
|
||||
// their plain text + wrap.
|
||||
@@ -11529,7 +11551,7 @@
|
||||
mangle: false,
|
||||
headerIds: false,
|
||||
breaks: false,
|
||||
gfm: false,
|
||||
gfm: true,
|
||||
});
|
||||
// Belt-and-braces: drop any embedded <script> just in case.
|
||||
return String(html).replace(/<script[\s\S]*?<\/script>/gi, '');
|
||||
|
||||
Reference in new issue
Block a user