@jianwen-lang/parser 0.1.1 → 0.1.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 (43) hide show
  1. package/README.md +44 -1
  2. package/dist/cli/render.js +75 -0
  3. package/dist/core/block/rules/attribute-line.d.ts +13 -0
  4. package/dist/core/block/rules/attribute-line.js +227 -0
  5. package/dist/core/block/rules/code-block.d.ts +2 -0
  6. package/dist/core/block/rules/code-block.js +73 -0
  7. package/dist/core/block/rules/code-fence.d.ts +15 -0
  8. package/dist/core/block/rules/code-fence.js +37 -0
  9. package/dist/core/block/rules/content-title.d.ts +12 -0
  10. package/dist/core/block/rules/content-title.js +70 -0
  11. package/dist/core/block/rules/footnotes.d.ts +9 -0
  12. package/dist/core/block/rules/footnotes.js +105 -0
  13. package/dist/core/block/rules/html.d.ts +7 -0
  14. package/dist/core/block/rules/html.js +48 -0
  15. package/dist/core/block/rules/image.d.ts +9 -0
  16. package/dist/core/block/rules/image.js +78 -0
  17. package/dist/core/block/rules/list.d.ts +3 -0
  18. package/dist/core/block/rules/list.js +275 -0
  19. package/dist/core/block/rules/paragraph.d.ts +6 -0
  20. package/dist/core/block/rules/paragraph.js +55 -0
  21. package/dist/core/block/rules/quote.d.ts +13 -0
  22. package/dist/core/block/rules/quote.js +104 -0
  23. package/dist/core/block/rules/table.d.ts +2 -0
  24. package/dist/core/block/rules/table.js +199 -0
  25. package/dist/core/block/runtime.d.ts +25 -0
  26. package/dist/core/block/runtime.js +125 -0
  27. package/dist/core/block/types.d.ts +2 -0
  28. package/dist/core/block-parser.js +186 -1321
  29. package/dist/core/parser.js +1 -1
  30. package/dist/html/convert.d.ts +10 -0
  31. package/dist/html/convert.js +23 -1
  32. package/dist/html/render/blocks.d.ts +15 -0
  33. package/dist/html/render/blocks.js +67 -13
  34. package/dist/html/render/html.d.ts +16 -0
  35. package/dist/html/render/html.js +53 -14
  36. package/dist/html/render/utils.d.ts +1 -0
  37. package/dist/html/theme/base/css.d.ts +1 -1
  38. package/dist/html/theme/base/css.js +50 -22
  39. package/dist/html/theme/dark/css.js +48 -0
  40. package/dist/html/theme/light/css.js +24 -0
  41. package/dist/html/theme/theme.d.ts +23 -1
  42. package/dist/html/theme/theme.js +242 -2
  43. package/package.json +5 -1
@@ -73,7 +73,7 @@ function parseInitializationTemplate(source) {
73
73
  applyMetaKey(meta, key, value);
74
74
  }
75
75
  }
76
- const bodyLines = lines.slice(0, start).concat(lines.slice(end + 1));
76
+ const bodyLines = lines.map((line, index) => index >= start && index <= end ? '' : (line ?? ''));
77
77
  const body = bodyLines.join('\n');
78
78
  if (isMetaEmpty(meta)) {
79
79
  return { body };
@@ -1,7 +1,9 @@
1
1
  import { ParseOptions } from '../core/parser';
2
2
  import { JianwenDocument } from '../core/ast';
3
3
  import { ParseError } from '../core/errors';
4
+ import { RenderedBlockGroup } from './render/html';
4
5
  import { RenderHtmlOptions } from './render/utils';
6
+ import { JianwenThemeConfig } from './theme/theme';
5
7
  export declare const DEFAULT_RUNTIME_SRC = "dist/html/theme/runtime.js";
6
8
  export interface HtmlDocumentOptions {
7
9
  title?: string;
@@ -11,6 +13,7 @@ export interface HtmlDocumentOptions {
11
13
  includeCss?: boolean;
12
14
  cssText?: string;
13
15
  cssHref?: string;
16
+ theme?: JianwenThemeConfig;
14
17
  includeRuntime?: boolean;
15
18
  runtimeSrc?: string;
16
19
  format?: boolean;
@@ -25,5 +28,12 @@ export interface RenderJianwenToHtmlDocumentResult {
25
28
  ast: JianwenDocument;
26
29
  errors: ParseError[];
27
30
  }
31
+ export interface RenderJianwenToHtmlDocumentWithBlockMapResult {
32
+ html: string;
33
+ ast: JianwenDocument;
34
+ errors: ParseError[];
35
+ groups: RenderedBlockGroup[];
36
+ }
28
37
  export declare function buildHtmlDocument(bodyHtml: string, options?: HtmlDocumentOptions): string;
29
38
  export declare function renderJianwenToHtmlDocument(source: string, options?: RenderJianwenToHtmlDocumentOptions): RenderJianwenToHtmlDocumentResult;
39
+ export declare function renderJianwenToHtmlDocumentWithBlockMap(source: string, options?: RenderJianwenToHtmlDocumentOptions): RenderJianwenToHtmlDocumentWithBlockMapResult;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_RUNTIME_SRC = void 0;
4
4
  exports.buildHtmlDocument = buildHtmlDocument;
5
5
  exports.renderJianwenToHtmlDocument = renderJianwenToHtmlDocument;
6
+ exports.renderJianwenToHtmlDocumentWithBlockMap = renderJianwenToHtmlDocumentWithBlockMap;
6
7
  const parser_1 = require("../core/parser");
7
8
  const format_1 = require("./format");
8
9
  const html_1 = require("./render/html");
@@ -22,7 +23,7 @@ function buildHtmlDocument(bodyHtml, options = {}) {
22
23
  headParts.push(`<link rel="stylesheet" href="${(0, utils_1.escapeAttr)(options.cssHref)}">`);
23
24
  }
24
25
  else {
25
- const cssText = options.cssText ?? theme_1.DEFAULT_CSS;
26
+ const cssText = options.cssText ?? (0, theme_1.composeThemeCss)({ preset: 'default', theme: options.theme });
26
27
  headParts.push(`<style>${cssText}</style>`);
27
28
  }
28
29
  }
@@ -59,3 +60,24 @@ function renderJianwenToHtmlDocument(source, options = {}) {
59
60
  });
60
61
  return { html, ast: parseResult.ast, errors: parseResult.errors };
61
62
  }
63
+ function renderJianwenToHtmlDocumentWithBlockMap(source, options = {}) {
64
+ const parseResult = (0, parser_1.parseJianwenWithErrors)(source, options.parse);
65
+ const renderOptions = {
66
+ includeMeta: true,
67
+ includeComments: false,
68
+ emitBlockMeta: true,
69
+ ...options.render,
70
+ };
71
+ const rendered = (0, html_1.renderDocumentToHtmlWithBlockMap)(parseResult.ast, renderOptions);
72
+ const title = options.document?.title ?? parseResult.ast.meta?.title;
73
+ const html = buildHtmlDocument(rendered.html, {
74
+ ...options.document,
75
+ title,
76
+ });
77
+ return {
78
+ html,
79
+ ast: parseResult.ast,
80
+ errors: parseResult.errors,
81
+ groups: rendered.groups,
82
+ };
83
+ }
@@ -1,4 +1,19 @@
1
1
  import { BlockNode } from '../../core/ast';
2
2
  import { RenderHtmlOptions } from './utils';
3
+ export type RenderBlockGroupKind = 'single' | 'sameLine' | 'foldable';
4
+ export interface RenderBlockGroupDraft {
5
+ id: string;
6
+ kind: RenderBlockGroupKind;
7
+ startBlockIndex: number;
8
+ endBlockIndex: number;
9
+ startLine?: number;
10
+ origin?: string;
11
+ readOnly: boolean;
12
+ }
13
+ export interface RenderBlocksResult {
14
+ html: string;
15
+ groups: RenderBlockGroupDraft[];
16
+ }
3
17
  export declare function renderBlocksToHtml(blocks: BlockNode[], options?: RenderHtmlOptions): string;
18
+ export declare function renderBlocksToHtmlWithGroups(blocks: BlockNode[], options?: RenderHtmlOptions): RenderBlocksResult;
4
19
  export declare function renderBlockToHtml(block: BlockNode, options: RenderHtmlOptions): string;
@@ -1,18 +1,61 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.renderBlocksToHtml = renderBlocksToHtml;
4
+ exports.renderBlocksToHtmlWithGroups = renderBlocksToHtmlWithGroups;
4
5
  exports.renderBlockToHtml = renderBlockToHtml;
5
6
  const utils_1 = require("./utils");
6
7
  const inlines_1 = require("./inlines");
8
+ const location_1 = require("../../core/location");
9
+ function nestedRenderOptions(options) {
10
+ if (!options.emitBlockMeta) {
11
+ return options;
12
+ }
13
+ return {
14
+ ...options,
15
+ emitBlockMeta: false,
16
+ };
17
+ }
7
18
  function renderBlocksToHtml(blocks, options = {}) {
19
+ return renderBlocksToHtmlWithGroups(blocks, options).html;
20
+ }
21
+ function renderBlocksToHtmlWithGroups(blocks, options = {}) {
8
22
  const result = [];
23
+ const groups = [];
9
24
  let i = 0;
10
- function wrapBlock(html) {
25
+ function buildGroupDraft(kind, blockList, startBlockIndex) {
26
+ const endBlockIndex = startBlockIndex + blockList.length - 1;
27
+ let startLine;
28
+ const origins = new Set();
29
+ for (const block of blockList) {
30
+ const location = (0, location_1.getNodeLocation)(block);
31
+ if (location && (startLine === undefined || location.line < startLine)) {
32
+ startLine = location.line;
33
+ }
34
+ const origin = (0, location_1.getNodeOrigin)(block);
35
+ if (origin) {
36
+ origins.add(origin);
37
+ }
38
+ }
39
+ const origin = origins.size === 1 ? Array.from(origins)[0] : undefined;
40
+ const hasIncludeBlock = blockList.some((block) => block.type === 'include');
41
+ const readOnly = origins.size > 0 || hasIncludeBlock;
42
+ return {
43
+ id: `g-${groups.length}`,
44
+ kind,
45
+ startBlockIndex,
46
+ endBlockIndex,
47
+ startLine,
48
+ origin,
49
+ readOnly,
50
+ };
51
+ }
52
+ function wrapBlock(html, group) {
11
53
  if (!html || !html.trim())
12
54
  return '';
13
55
  if (options.suppressBlockWrapper)
14
56
  return html;
15
- return `<div class="jw-block">${html}</div>`;
57
+ const dataAttr = options.emitBlockMeta && group ? ` data-jw-group-id="${(0, utils_1.escapeAttr)(group.id)}"` : '';
58
+ return `<div class="jw-block"${dataAttr}>${html}</div>`;
16
59
  }
17
60
  while (i < blocks.length) {
18
61
  const block = blocks[i];
@@ -41,13 +84,18 @@ function renderBlocksToHtml(blocks, options = {}) {
41
84
  }
42
85
  const detailsContent = foldedBlocks.join('');
43
86
  const detailsHtml = `<details class="jw-foldable-section">${headingHtml}${detailsContent}</details>`;
44
- result.push(wrapBlock(detailsHtml));
87
+ const groupBlocks = blocks.slice(i, j).filter((item) => Boolean(item));
88
+ const group = buildGroupDraft('foldable', groupBlocks, i);
89
+ groups.push(group);
90
+ result.push(wrapBlock(detailsHtml, group));
45
91
  i = j;
46
92
  continue;
47
93
  }
48
94
  const blockAttrs = 'blockAttrs' in block ? block.blockAttrs : undefined;
49
95
  if (!blockAttrs?.sameLine) {
50
- result.push(wrapBlock(renderBlockToHtml(block, options)));
96
+ const group = buildGroupDraft('single', [block], i);
97
+ groups.push(group);
98
+ result.push(wrapBlock(renderBlockToHtml(block, options), group));
51
99
  i++;
52
100
  continue;
53
101
  }
@@ -60,6 +108,7 @@ function renderBlocksToHtml(blocks, options = {}) {
60
108
  if (!prevAttrs?.sameLine) {
61
109
  rowStartIndex = i - 1;
62
110
  result.pop();
111
+ groups.pop();
63
112
  }
64
113
  }
65
114
  }
@@ -81,10 +130,15 @@ function renderBlocksToHtml(blocks, options = {}) {
81
130
  }
82
131
  }
83
132
  const rowHtml = rowBlocks.map((b) => renderBlockToHtml(b, options)).join('');
84
- result.push(wrapBlock(`<div class="jw-same-line-row">${rowHtml}</div>`));
133
+ const group = buildGroupDraft('sameLine', rowBlocks, rowStartIndex);
134
+ groups.push(group);
135
+ result.push(wrapBlock(`<div class="jw-same-line-row">${rowHtml}</div>`, group));
85
136
  i = rowStartIndex + rowBlocks.length;
86
137
  }
87
- return result.join('');
138
+ return {
139
+ html: result.join(''),
140
+ groups,
141
+ };
88
142
  }
89
143
  function renderBlockToHtml(block, options) {
90
144
  switch (block.type) {
@@ -170,7 +224,7 @@ function renderContentTitleBlock(block, options) {
170
224
  return `<div class="jw-content-title">${inner}</div>${spacer}`;
171
225
  }
172
226
  function renderQuoteBlock(block, options) {
173
- const inner = renderBlocksToHtml(block.children, options);
227
+ const inner = renderBlocksToHtml(block.children, nestedRenderOptions(options));
174
228
  const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
175
229
  extraData: { 'data-jw-level': String(block.level) },
176
230
  });
@@ -209,20 +263,20 @@ function renderListItemBlock(block, options) {
209
263
  prefix += `<span class="jw-list-task-marker" data-jw-task-status="${(0, utils_1.escapeAttr)(block.taskStatus)}"></span>`;
210
264
  }
211
265
  const inner = renderBlocksToHtml(block.children, {
212
- ...options,
266
+ ...nestedRenderOptions(options),
213
267
  suppressBlockWrapper: true,
214
268
  });
215
269
  if (block.kind === 'foldable') {
216
270
  const firstChild = block.children[0];
217
271
  if (firstChild && firstChild.type === 'paragraph') {
218
272
  const summaryContent = renderBlockToHtml(firstChild, {
219
- ...options,
273
+ ...nestedRenderOptions(options),
220
274
  suppressBlockWrapper: true,
221
275
  });
222
276
  const remainingChildren = block.children.slice(1);
223
277
  const detailsContent = remainingChildren.length > 0
224
278
  ? renderBlocksToHtml(remainingChildren, {
225
- ...options,
279
+ ...nestedRenderOptions(options),
226
280
  suppressBlockWrapper: true,
227
281
  })
228
282
  : '';
@@ -383,14 +437,14 @@ function renderFootnotesBlock(block, options) {
383
437
  return `<section class="jw-footnotes"${attrs}><ol class="jw-footnote-list">${items}</ol></section>`;
384
438
  }
385
439
  function renderFootnoteDefBlock(block, options) {
386
- const inner = renderBlocksToHtml(block.children, options);
440
+ const inner = renderBlocksToHtml(block.children, nestedRenderOptions(options));
387
441
  const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
388
442
  extraData: { 'data-jw-footnote-id': block.id },
389
443
  });
390
444
  return `<li class="jw-footnote-def"${attrs}>${inner}</li>`;
391
445
  }
392
446
  function renderCommentBlock(block, options) {
393
- const inner = renderBlocksToHtml(block.children, options);
447
+ const inner = renderBlocksToHtml(block.children, nestedRenderOptions(options));
394
448
  const attrs = (0, utils_1.buildBlockAttributes)(block.blockAttrs, {
395
449
  extraData: { 'data-jw-comment': 'true' },
396
450
  });
@@ -423,7 +477,7 @@ function renderTaggedBlock(block, options) {
423
477
  extraData: { 'data-jw-tag': block.name },
424
478
  rawAttrs: [`id="${(0, utils_1.escapeAttr)(id)}"`],
425
479
  });
426
- const inner = renderBlockToHtml(block.child, options);
480
+ const inner = renderBlockToHtml(block.child, nestedRenderOptions(options));
427
481
  return `<div class="jw-tagged-block"${attrs}>${inner}</div>`;
428
482
  }
429
483
  function renderRawBlock(block, _options) {
@@ -3,6 +3,22 @@ import { RenderHtmlOptions } from './utils';
3
3
  export { RenderHtmlOptions } from './utils';
4
4
  export { DocumentTheme } from '../theme/theme';
5
5
  export { renderBlocksToHtml } from './blocks';
6
+ export { renderBlocksToHtmlWithGroups } from './blocks';
6
7
  export { renderInlinesToHtml } from './inlines';
8
+ export interface RenderedBlockGroup {
9
+ id: string;
10
+ kind: 'single' | 'sameLine' | 'foldable';
11
+ startBlockIndex: number;
12
+ endBlockIndex: number;
13
+ startLine?: number;
14
+ endLine?: number;
15
+ origin?: string;
16
+ readOnly: boolean;
17
+ }
18
+ export interface RenderDocumentWithBlockMapResult {
19
+ html: string;
20
+ groups: RenderedBlockGroup[];
21
+ }
7
22
  export declare function createDefaultAssetPathResolver(sourceFilePath: string, outputFilePath: string): (assetPath: string) => string | undefined;
8
23
  export declare function renderDocumentToHtml(doc: JianwenDocument, options?: RenderHtmlOptions): string;
24
+ export declare function renderDocumentToHtmlWithBlockMap(doc: JianwenDocument, options?: RenderHtmlOptions): RenderDocumentWithBlockMapResult;
@@ -33,9 +33,10 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.renderInlinesToHtml = exports.renderBlocksToHtml = void 0;
36
+ exports.renderInlinesToHtml = exports.renderBlocksToHtmlWithGroups = exports.renderBlocksToHtml = void 0;
37
37
  exports.createDefaultAssetPathResolver = createDefaultAssetPathResolver;
38
38
  exports.renderDocumentToHtml = renderDocumentToHtml;
39
+ exports.renderDocumentToHtmlWithBlockMap = renderDocumentToHtmlWithBlockMap;
39
40
  const path = __importStar(require("path"));
40
41
  const format_1 = require("../format");
41
42
  const utils_1 = require("./utils");
@@ -43,6 +44,8 @@ const meta_1 = require("./meta");
43
44
  const blocks_1 = require("./blocks");
44
45
  var blocks_2 = require("./blocks");
45
46
  Object.defineProperty(exports, "renderBlocksToHtml", { enumerable: true, get: function () { return blocks_2.renderBlocksToHtml; } });
47
+ var blocks_3 = require("./blocks");
48
+ Object.defineProperty(exports, "renderBlocksToHtmlWithGroups", { enumerable: true, get: function () { return blocks_3.renderBlocksToHtmlWithGroups; } });
46
49
  var inlines_1 = require("./inlines");
47
50
  Object.defineProperty(exports, "renderInlinesToHtml", { enumerable: true, get: function () { return inlines_1.renderInlinesToHtml; } });
48
51
  function createDefaultAssetPathResolver(sourceFilePath, outputFilePath) {
@@ -58,6 +61,30 @@ function createDefaultAssetPathResolver(sourceFilePath, outputFilePath) {
58
61
  };
59
62
  }
60
63
  function renderDocumentToHtml(doc, options = {}) {
64
+ return renderDocumentToHtmlWithBlockMap(doc, {
65
+ ...options,
66
+ emitBlockMeta: options.emitBlockMeta ?? false,
67
+ }).html;
68
+ }
69
+ function finalizeGroups(groups, sourceLineCount) {
70
+ return groups.map((group, index) => {
71
+ const next = groups[index + 1];
72
+ let endLine;
73
+ if (group.startLine !== undefined) {
74
+ if (next?.startLine !== undefined) {
75
+ endLine = Math.max(group.startLine, 1, next.startLine - 1);
76
+ }
77
+ else if (sourceLineCount !== undefined) {
78
+ endLine = Math.max(group.startLine, 1, sourceLineCount);
79
+ }
80
+ }
81
+ return {
82
+ ...group,
83
+ endLine,
84
+ };
85
+ });
86
+ }
87
+ function renderDocumentToHtmlWithBlockMap(doc, options = {}) {
61
88
  const wrapperTag = options.documentWrapperTag === undefined ? 'article' : options.documentWrapperTag;
62
89
  const finalOptions = { ...options };
63
90
  if (options.sourceFilePath && options.outputFilePath && !options.resolveAssetPath) {
@@ -68,22 +95,34 @@ function renderDocumentToHtml(doc, options = {}) {
68
95
  innerParts.push((0, meta_1.renderMetaToHtml)(doc.meta));
69
96
  }
70
97
  if (!wrapperTag) {
71
- innerParts.push((0, blocks_1.renderBlocksToHtml)(doc.children, {
98
+ const rendered = (0, blocks_1.renderBlocksToHtmlWithGroups)(doc.children, {
72
99
  ...finalOptions,
73
100
  suppressBlockWrapper: true,
74
- }));
101
+ emitBlockMeta: finalOptions.emitBlockMeta ?? true,
102
+ });
103
+ const lineCount = doc.source ? doc.source.split('\n').length : undefined;
104
+ innerParts.push(rendered.html);
105
+ return {
106
+ html: innerParts.join(''),
107
+ groups: finalizeGroups(rendered.groups, lineCount),
108
+ };
75
109
  }
76
110
  else {
77
- innerParts.push((0, blocks_1.renderBlocksToHtml)(doc.children, finalOptions));
78
- }
79
- const innerHtml = innerParts.join('');
80
- if (!wrapperTag) {
81
- return innerHtml;
111
+ const rendered = (0, blocks_1.renderBlocksToHtmlWithGroups)(doc.children, {
112
+ ...finalOptions,
113
+ emitBlockMeta: finalOptions.emitBlockMeta ?? true,
114
+ });
115
+ innerParts.push(rendered.html);
116
+ const innerHtml = innerParts.join('');
117
+ const wrapperAttrs = (0, meta_1.buildDocumentWrapperAttributes)(doc.meta);
118
+ const themeAttr = finalOptions.documentTheme
119
+ ? ` data-jw-theme="${(0, utils_1.escapeAttr)(finalOptions.documentTheme)}"`
120
+ : '';
121
+ const html = `<${wrapperTag} class="jw-root"${wrapperAttrs}${themeAttr}>${innerHtml}</${wrapperTag}>`;
122
+ const lineCount = doc.source ? doc.source.split('\n').length : undefined;
123
+ return {
124
+ html: finalOptions.format ? (0, format_1.formatHtml)(html) : html,
125
+ groups: finalizeGroups(rendered.groups, lineCount),
126
+ };
82
127
  }
83
- const wrapperAttrs = (0, meta_1.buildDocumentWrapperAttributes)(doc.meta);
84
- const themeAttr = finalOptions.documentTheme
85
- ? ` data-jw-theme="${(0, utils_1.escapeAttr)(finalOptions.documentTheme)}"`
86
- : '';
87
- const html = `<${wrapperTag} class="jw-root"${wrapperAttrs}${themeAttr}>${innerHtml}</${wrapperTag}>`;
88
- return finalOptions.format ? (0, format_1.formatHtml)(html) : html;
89
128
  }
@@ -3,6 +3,7 @@ import { DocumentTheme } from '../theme/theme';
3
3
  export interface RenderHtmlOptions {
4
4
  includeMeta?: boolean;
5
5
  includeComments?: boolean;
6
+ emitBlockMeta?: boolean;
6
7
  resolveHtmlSource?: (source: string) => string | undefined;
7
8
  resolveInclude?: (mode: 'file' | 'tag', target: string) => string | undefined;
8
9
  resolveAssetPath?: (assetPath: string) => string | undefined;
@@ -1,2 +1,2 @@
1
1
  export = BASE_CSS;
2
- declare const BASE_CSS: "\nhtml,\nbody {\n margin: 0;\n padding: 0;\n}\n.jw-root {\n background-color: var(--jw-bg-color, transparent);\n color: var(--jw-text-color, inherit);\n display: flow-root;\n min-height: 100vh;\n}\n.jw-root > .jw-block + .jw-block { margin-top: var(--jw-block-spacing); }\n.jw-root > .jw-block { margin: 0; }\n.jw-table { border-collapse: collapse; }\n.jw-table-cell { border: 1px solid var(--jw-border-color); padding: 0.5em; }\n.jw-link { text-decoration: none; color: var(--jw-link-color, currentColor); }\n.jw-link:visited { color: var(--jw-link-color, currentColor); }\n.jw-link:hover { text-decoration: underline; }\n.jw-underline { text-decoration: underline; }\n.jw-strike { text-decoration: line-through; }\n.jw-wave { text-decoration: underline; text-decoration-style: wavy; }\n.jw-heading { font-weight: bold; margin: 0; }\n.jw-heading.level-1 { font-size: 2.5em; }\n.jw-heading.level-2 { font-size: 2em; }\n.jw-heading.level-3 { font-size: 1.75em; }\n.jw-heading.level-4 { font-size: 1.5em; }\n.jw-heading.level-5 { font-size: 1.25em; }\n.jw-foldable-section { margin: 1em 0; }\n.jw-foldable-section > summary {\n cursor: pointer;\n user-select: none;\n list-style: none;\n display: flex;\n align-items: center;\n}\n.jw-foldable-section > summary::-webkit-details-marker {\n display: none;\n}\n.jw-foldable-section > summary::before {\n content: '';\n display: block;\n width: 0.5em;\n height: 0.5em;\n margin-right: 0.4em;\n flex: 0 0 auto;\n background: currentColor;\n clip-path: polygon(0 0, 100% 50%, 0 100%);\n transform: rotate(0deg);\n opacity: 0.74;\n transition: transform 0.2s ease, opacity 0.2s ease;\n}\n.jw-foldable-section[open] > summary::before {\n transform: rotate(90deg);\n opacity: 0.85;\n}\n.jw-foldable-section > summary .jw-heading {\n display: inline;\n margin: 0;\n min-width: 0;\n}\n\n.jw-content-title {\n margin-top: 0.1em;\n margin-bottom: 0;\n font-size: 0.85em;\n color: var(--jw-text-muted);\n}\n.jw-content-title-gap {\n display: block;\n height: 0.8em;\n min-height: 8px;\n}\n.jw-quote {\n margin: 0;\n border-left: 4px solid var(--jw-quote-border-color);\n padding: 0 1em;\n background: var(--jw-quote-background);\n color: var(--jw-quote-text);\n}\n.jw-quote > .jw-paragraph { margin: var(--jw-quote-gap) 0; }\n.jw-quote > .jw-quote { margin: var(--jw-quote-gap) 0; }\n[data-jw-level=\"2\"].jw-quote { border-left-color: var(--jw-quote-border-color-2); }\n[data-jw-level=\"3\"].jw-quote { border-left-color: var(--jw-quote-border-color-3); }\n.jw-paragraph { white-space: pre-wrap; line-height: var(--jw-line-height-base); }\n.jw-paragraph-block { white-space: normal; }\n.jw-list { padding-left: 1.25em; }\n.jw-list[data-jw-list-kind=\"bullet\"] { list-style-type: disc; }\n.jw-hr { border: none; border-top: 1px solid currentColor; color: var(--jw-border-color); height: 0; background: none; padding: 0; margin: 0; }\n.jw-hr[data-jw-position=\"L\"] { width: 100%; }\n.jw-hr[data-jw-position=\"C\"] { width: 66.67%; }\n.jw-hr[data-jw-position=\"R\"] { width: 33.34%; }\n.jw-hr[data-jw-hr-style=\"dashed\"] { border-top-style: dashed; }\n.jw-hr[data-jw-hr-style=\"bold\"] { border-top-width: 4px; }\n.jw-hr[data-jw-hr-style=\"wavy\"] {\n border: none;\n height: 8px;\n color: var(--jw-border-color);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 8' preserveAspectRatio='none'%3E%3Cpath d='M0 4 Q 8 0 16 4 T 32 4' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E\");\n background-size: 32px 8px;\n background-repeat: repeat-x;\n background-position: center bottom;\n background-color: transparent;\n}\n.jw-highlight-marker { background-color: var(--jw-highlight-marker); padding: 0; }\n.jw-highlight-frame { border: 1px solid var(--jw-border-color); padding: 0; border-radius: 3px; }\n.jw-highlight-block {\n display: block;\n padding: 0.75em 1em;\n white-space: normal;\n}\n.jw-list[data-jw-list-kind=\"task\"] { list-style: none; padding-left: 0; }\n.jw-list-item[data-jw-list-kind=\"task\"] { list-style: none; }\n.jw-list-item[data-jw-list-kind=\"task\"][data-jw-task-status] {\n position: relative;\n padding-left: 0;\n margin: 0.25em 0;\n}\n.jw-list-item {\n display: flex;\n flex-flow: row wrap;\n align-items: flex-start;\n}\n.jw-list-item[data-jw-list-kind=\"bullet\"] {\n display: list-item;\n}\n.jw-list-ordinal {\n margin-right: 0.5em;\n line-height: var(--jw-line-height-base);\n flex-shrink: 0;\n color: var(--jw-text-strong);\n font-variant-numeric: tabular-nums;\n}\n.jw-list-task-marker {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.25em;\n height: 1.25em;\n border: 1px solid var(--jw-border-color-strong);\n background: var(--jw-surface-task);\n border-radius: 2px;\n font-size: 0.85em;\n color: transparent;\n transition: all 0.2s ease;\n box-sizing: border-box;\n margin-right: 0.5em;\n flex-shrink: 0;\n margin-top: 0.375em;\n position: relative;\n line-height: 1;\n}\n.jw-list-task-marker::before,\n.jw-list-task-marker::after {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n content: '';\n}\n.jw-list-task-marker[data-jw-task-status=\"done\"] {\n content: '\u2714';\n}\n.jw-list-task-marker[data-jw-task-status=\"done\"]::before {\n content: '\u2714';\n color: var(--jw-task-done-text);\n}\n.jw-list-task-marker[data-jw-task-status=\"done\"] {\n background: var(--jw-task-done-bg);\n border-color: var(--jw-task-done-bg);\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::before,\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::after {\n width: 0.85em;\n height: 0.12em;\n background: var(--jw-task-not-done-cross);\n border-radius: 999px;\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::before {\n transform: translate(-50%, -50%) rotate(45deg);\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::after {\n transform: translate(-50%, -50%) rotate(-45deg);\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"] {\n background: var(--jw-border-color-strong);\n border-color: var(--jw-border-color-strong);\n}\n.jw-list-task-marker[data-jw-task-status=\"in_progress\"]::before {\n width: 0.7em;\n height: 0.7em;\n border: 0.12em solid var(--jw-task-in-progress);\n border-radius: 50%;\n}\n.jw-list-task-marker[data-jw-task-status=\"unknown\"] {\n /* Empty box */\n}\n.jw-list-item > .jw-paragraph {\n flex: 1 1 auto;\n margin: 0;\n min-width: 0;\n line-height: var(--jw-line-height-base);\n}\n.jw-list-item > .jw-list {\n flex-basis: 100%;\n width: 100%;\n padding-left: 2em;\n margin: var(--jw-nested-list-gap) 0 0 0;\n}\n.jw-list-item + .jw-list-item {\n margin-top: var(--jw-nested-list-gap);\n}\n.jw-list-item > .jw-code-block {\n flex-basis: 100%;\n width: 100%;\n margin-top: var(--jw-nested-list-gap);\n}\n.jw-list-item[data-jw-task-status=\"done\"] > .jw-paragraph {\n text-decoration: line-through;\n color: var(--jw-text-faint);\n}\n.jw-list-item[data-jw-list-kind=\"ordered\"] {\n list-style: none;\n}\n.jw-list-item[data-jw-list-kind=\"ordered\"]::marker {\n content: none;\n}\n\n.jw-list-item[data-jw-list-kind=\"foldable\"] { list-style: none; }\n.jw-foldable-list-item {\n display: block;\n}\n.jw-foldable-list-item > summary {\n cursor: pointer;\n user-select: none;\n list-style: none;\n position: relative;\n padding-left: 1.2em;\n}\n.jw-foldable-list-item > summary::-webkit-details-marker {\n display: none;\n}\n.jw-foldable-list-item > summary::before {\n content: '';\n position: absolute;\n left: 0;\n top: 50%;\n width: 0.45em;\n height: 0.45em;\n background: currentColor;\n clip-path: polygon(0 0, 100% 50%, 0 100%);\n transform: translateY(-50%) rotate(0deg);\n opacity: 0.68;\n transition: transform 0.2s ease, opacity 0.2s ease;\n}\n.jw-foldable-list-item[open] > summary::before {\n transform: translateY(-50%) rotate(90deg);\n opacity: 0.85;\n}\n.jw-foldable-list-item > summary .jw-paragraph {\n display: inline;\n}\n\n.jw-image-figure { }\n.jw-image { max-width: 100%; max-height: 600px; width: auto; height: auto; object-fit: contain; }\n.jw-image-caption { margin-top: 0.5em; font-size: 0.9em; color: var(--jw-text-subtle); }\n.jw-image-figure[data-jw-shape=\"rounded\"] .jw-image { border-radius: 8px; }\n.jw-code-block {\n position: relative;\n display: flex;\n flex-direction: column;\n padding: 0;\n background: var(--jw-surface-code);\n border: 1px solid var(--jw-border-color-subtle);\n border-radius: 4px;\n font-family: \"JetBrains Mono\", \"Fira Code\", Consolas, Menlo, monospace;\n font-size: 0.9em;\n line-height: 1.5;\n margin: 0;\n}\n.jw-code-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.5em 0.75em;\n border-bottom: 1px solid var(--jw-border-color-subtle);\n background: var(--jw-surface-overlay-1);\n}\n.jw-code-lang {\n padding: 0.1em 0.4em;\n background: var(--jw-surface-overlay-2);\n color: var(--jw-text-subtle);\n font-size: 0.75em;\n border-radius: 3px;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n.jw-code-copy {\n padding: 0.25em 0.5em;\n background: transparent;\n border: 1px solid var(--jw-border-color);\n border-radius: 3px;\n cursor: pointer;\n font-size: 0.75em;\n color: var(--jw-text-subtle);\n transition: background 0.2s, border-color 0.2s;\n}\n.jw-code-copy:hover {\n background: var(--jw-surface-overlay-2);\n border-color: var(--jw-border-color-strong);\n}\n.jw-code-copy:active {\n background: var(--jw-surface-overlay-3);\n}\n.jw-code-content {\n display: flex;\n padding: 1em 1em 1em 0;\n}\n.jw-line-numbers {\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n padding: 0 0.75em;\n border-right: 1px solid var(--jw-border-color-subtle);\n text-align: right;\n user-select: none;\n color: var(--jw-text-faint);\n font-variant-numeric: tabular-nums;\n}\n.jw-line-number {\n display: block;\n min-height: 1.5em;\n}\n.jw-code {\n flex: 1;\n display: block;\n overflow-x: auto;\n padding: 0 1em;\n background: transparent;\n font-family: inherit;\n white-space: pre;\n}\n.jw-code-line {\n display: block;\n white-space: pre;\n min-height: 1.5em;\n}\n.jw-disabled-block { font-family: inherit; white-space: pre-wrap; line-height: var(--jw-line-height-base); margin: 0; }\n[data-jw-position=\"C\"] { margin-left: 33.33%; }\n[data-jw-position=\"R\"] { margin-left: 66.66%; }\n[data-jw-truncate-left=\"true\"] { margin-left: 0; }\n[data-jw-truncate-right=\"true\"] { max-width: 33.33%; word-wrap: break-word; overflow-wrap: break-word; }\n[data-jw-position=\"C\"][data-jw-truncate-right=\"true\"] { max-width: 33.33%; }\n[data-jw-position=\"R\"][data-jw-truncate-right=\"true\"] { max-width: 33.33%; }\n.jw-hr[data-jw-truncate-right=\"true\"] { width: 33.33%; max-width: none; }\n[data-jw-align=\"center\"] { text-align: center; }\n[data-jw-align=\"right\"] { text-align: right; }\n.jw-same-line-row { display: flex; flex-wrap: nowrap; gap: 0; align-items: flex-start; max-width: 100%; overflow: hidden; }\n.jw-same-line-row > * { flex-shrink: 1; word-wrap: break-word; overflow-wrap: break-word; min-width: 0; }\n.jw-same-line-row > [data-jw-position=\"L\"]:not(:last-child),\n.jw-same-line-row > [data-jw-position=\"C\"]:not(:last-child),\n.jw-same-line-row > [data-jw-position=\"R\"]:not(:last-child) { flex-basis: 33.33%; max-width: 33.33%; }\n.jw-same-line-row > [data-jw-position=\"L\"]:last-child,\n.jw-same-line-row > [data-jw-position=\"C\"]:last-child,\n.jw-same-line-row > [data-jw-position=\"R\"]:last-child { flex-grow: 1; flex-basis: 0; }\n.jw-same-line-row > [data-jw-position] { margin-left: 0; }\n.jw-same-line-row > [data-jw-position=\"C\"]:first-child { margin-left: 33.33%; }\n.jw-same-line-row > [data-jw-position=\"R\"]:first-child { margin-left: 66.66%; }\n.jw-meta { margin: 0 0 var(--jw-block-spacing); }\n.jw-meta-time,\n.jw-meta-add-info,\n.jw-meta-tags,\n.jw-meta-author {\n color: var(--jw-quote-text);\n}\n.jw-meta-author-link { text-decoration: none; color: inherit; }\n.jw-meta-author-link:hover { text-decoration: underline; }\n.jw-comment-inline { display: none; }\n.jw-comment-block { display: none; }\n";
2
+ declare const BASE_CSS: "\n.jw-root {\n background-color: var(--jw-bg-color, transparent);\n color: var(--jw-text-color, inherit);\n display: flow-root;\n min-height: 100vh;\n}\n.jw-root > .jw-block + .jw-block { margin-top: var(--jw-block-spacing); }\n.jw-root > .jw-block { margin: 0; }\n.jw-table { border-collapse: collapse; width: 100%; }\n.jw-table-cell {\n border: 1px solid var(--jw-table-border-color, var(--jw-border-color));\n padding: 0.5em;\n}\n.jw-table thead .jw-table-cell {\n background: var(--jw-table-header-bg, var(--jw-surface-overlay-1));\n color: var(--jw-table-header-text, var(--jw-text-strong));\n font-weight: 600;\n}\n.jw-table tbody .jw-table-row:nth-child(odd) .jw-table-cell {\n background: var(--jw-table-row-bg, transparent);\n}\n.jw-table tbody .jw-table-row:nth-child(even) .jw-table-cell {\n background: var(--jw-table-row-alt-bg, transparent);\n}\n.jw-link { text-decoration: none; color: var(--jw-link-color, currentColor); }\n.jw-link:visited { color: var(--jw-link-color, currentColor); }\n.jw-link:hover { text-decoration: underline; }\n.jw-root strong {\n color: var(--jw-strong-color, currentColor);\n font-weight: var(--jw-strong-weight, 700);\n}\n.jw-underline {\n text-decoration: underline;\n text-decoration-color: var(--jw-underline-color, currentColor);\n text-decoration-thickness: var(--jw-underline-thickness, from-font);\n text-underline-offset: var(--jw-underline-offset, auto);\n}\n.jw-strike {\n text-decoration: line-through;\n text-decoration-color: var(--jw-strike-color, currentColor);\n}\n.jw-wave {\n text-decoration: underline;\n text-decoration-style: wavy;\n text-decoration-color: var(--jw-wave-color, currentColor);\n text-decoration-thickness: var(--jw-underline-thickness, from-font);\n text-underline-offset: var(--jw-underline-offset, auto);\n}\n.jw-heading { font-weight: bold; margin: 0; }\n.jw-heading.level-1 { font-size: 2.5em; }\n.jw-heading.level-2 { font-size: 2em; }\n.jw-heading.level-3 { font-size: 1.75em; }\n.jw-heading.level-4 { font-size: 1.5em; }\n.jw-heading.level-5 { font-size: 1.25em; }\n.jw-foldable-section { margin: 1em 0; }\n.jw-foldable-section > summary {\n cursor: pointer;\n user-select: none;\n list-style: none;\n display: flex;\n align-items: center;\n}\n.jw-foldable-section > summary::-webkit-details-marker {\n display: none;\n}\n.jw-foldable-section > summary::before {\n content: '';\n display: block;\n width: 0.5em;\n height: 0.5em;\n margin-right: 0.4em;\n flex: 0 0 auto;\n background: currentColor;\n clip-path: polygon(0 0, 100% 50%, 0 100%);\n transform: rotate(0deg);\n opacity: 0.74;\n transition: transform 0.2s ease, opacity 0.2s ease;\n}\n.jw-foldable-section[open] > summary::before {\n transform: rotate(90deg);\n opacity: 0.85;\n}\n.jw-foldable-section > summary .jw-heading {\n display: inline;\n margin: 0;\n min-width: 0;\n}\n\n.jw-content-title {\n margin-top: 0.1em;\n margin-bottom: 0;\n font-size: 0.85em;\n color: var(--jw-text-muted);\n}\n.jw-content-title-gap {\n display: block;\n height: 0.8em;\n min-height: 8px;\n}\n.jw-quote {\n margin: 0;\n border-left: 4px solid var(--jw-quote-border-color);\n padding: 0 1em;\n background: var(--jw-quote-background);\n color: var(--jw-quote-text);\n}\n.jw-quote > .jw-paragraph { margin: var(--jw-quote-gap) 0; }\n.jw-quote > .jw-quote { margin: var(--jw-quote-gap) 0; }\n[data-jw-level=\"2\"].jw-quote { border-left-color: var(--jw-quote-border-color-2); }\n[data-jw-level=\"3\"].jw-quote { border-left-color: var(--jw-quote-border-color-3); }\n.jw-paragraph { white-space: pre-wrap; line-height: var(--jw-line-height-base); }\n.jw-paragraph-block { white-space: normal; }\n.jw-list { padding-left: 1.25em; }\n.jw-list[data-jw-list-kind=\"bullet\"] { list-style-type: disc; }\n.jw-hr { border: none; border-top: 1px solid currentColor; color: var(--jw-border-color); height: 0; background: none; padding: 0; margin: 0; }\n.jw-hr[data-jw-position=\"L\"] { width: 100%; }\n.jw-hr[data-jw-position=\"C\"] { width: 66.67%; }\n.jw-hr[data-jw-position=\"R\"] { width: 33.34%; }\n.jw-hr[data-jw-hr-style=\"dashed\"] { border-top-style: dashed; }\n.jw-hr[data-jw-hr-style=\"bold\"] { border-top-width: 4px; }\n.jw-hr[data-jw-hr-style=\"wavy\"] {\n border: none;\n height: 8px;\n color: var(--jw-border-color);\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 8' preserveAspectRatio='none'%3E%3Cpath d='M0 4 Q 8 0 16 4 T 32 4' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E\");\n background-size: 32px 8px;\n background-repeat: repeat-x;\n background-position: center bottom;\n background-color: transparent;\n}\n.jw-highlight-marker { background-color: var(--jw-highlight-marker); padding: 0; }\n.jw-highlight-frame { border: 1px solid var(--jw-border-color); padding: 0; border-radius: 3px; }\n.jw-highlight-block {\n display: block;\n padding: 0.75em 1em;\n white-space: normal;\n}\n.jw-list[data-jw-list-kind=\"task\"] { list-style: none; padding-left: 0; }\n.jw-list-item[data-jw-list-kind=\"task\"] { list-style: none; }\n.jw-list-item[data-jw-list-kind=\"task\"][data-jw-task-status] {\n position: relative;\n padding-left: 0;\n margin: 0.25em 0;\n}\n.jw-list-item {\n display: flex;\n flex-flow: row wrap;\n align-items: flex-start;\n}\n.jw-list-item[data-jw-list-kind=\"bullet\"] {\n display: list-item;\n}\n.jw-list-ordinal {\n margin-right: 0.5em;\n line-height: var(--jw-line-height-base);\n flex-shrink: 0;\n color: var(--jw-text-strong);\n font-variant-numeric: tabular-nums;\n}\n.jw-list-task-marker {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 1.25em;\n height: 1.25em;\n border: 1px solid var(--jw-border-color-strong);\n background: var(--jw-surface-task);\n border-radius: 2px;\n font-size: 0.85em;\n color: transparent;\n transition: all 0.2s ease;\n box-sizing: border-box;\n margin-right: 0.5em;\n flex-shrink: 0;\n margin-top: 0.375em;\n position: relative;\n line-height: 1;\n}\n.jw-list-task-marker::before,\n.jw-list-task-marker::after {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n content: '';\n}\n.jw-list-task-marker[data-jw-task-status=\"done\"] {\n content: '\u2714';\n}\n.jw-list-task-marker[data-jw-task-status=\"done\"]::before {\n content: '\u2714';\n color: var(--jw-task-done-text);\n}\n.jw-list-task-marker[data-jw-task-status=\"done\"] {\n background: var(--jw-task-done-bg);\n border-color: var(--jw-task-done-bg);\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::before,\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::after {\n width: 0.85em;\n height: 0.12em;\n background: var(--jw-task-not-done-cross);\n border-radius: 999px;\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::before {\n transform: translate(-50%, -50%) rotate(45deg);\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"]::after {\n transform: translate(-50%, -50%) rotate(-45deg);\n}\n.jw-list-task-marker[data-jw-task-status=\"not_done\"] {\n background: var(--jw-border-color-strong);\n border-color: var(--jw-border-color-strong);\n}\n.jw-list-task-marker[data-jw-task-status=\"in_progress\"]::before {\n width: 0.7em;\n height: 0.7em;\n border: 0.12em solid var(--jw-task-in-progress);\n border-radius: 50%;\n}\n.jw-list-task-marker[data-jw-task-status=\"unknown\"] {\n /* Empty box */\n}\n.jw-list-item > .jw-paragraph {\n flex: 1 1 auto;\n margin: 0;\n min-width: 0;\n line-height: var(--jw-line-height-base);\n}\n.jw-list-item > .jw-list {\n flex-basis: 100%;\n width: 100%;\n padding-left: 2em;\n margin: var(--jw-nested-list-gap) 0 0 0;\n}\n.jw-list-item + .jw-list-item {\n margin-top: var(--jw-nested-list-gap);\n}\n.jw-list-item > .jw-code-block {\n flex-basis: 100%;\n width: 100%;\n margin-top: var(--jw-nested-list-gap);\n}\n.jw-list-item[data-jw-task-status=\"done\"] > .jw-paragraph {\n text-decoration: line-through;\n color: var(--jw-text-faint);\n}\n.jw-list-item[data-jw-list-kind=\"ordered\"] {\n list-style: none;\n}\n.jw-list-item[data-jw-list-kind=\"ordered\"]::marker {\n content: none;\n}\n\n.jw-list-item[data-jw-list-kind=\"foldable\"] { list-style: none; }\n.jw-foldable-list-item {\n display: block;\n}\n.jw-foldable-list-item > summary {\n cursor: pointer;\n user-select: none;\n list-style: none;\n position: relative;\n padding-left: 1.2em;\n}\n.jw-foldable-list-item > summary::-webkit-details-marker {\n display: none;\n}\n.jw-foldable-list-item > summary::before {\n content: '';\n position: absolute;\n left: 0;\n top: 50%;\n width: 0.45em;\n height: 0.45em;\n background: currentColor;\n clip-path: polygon(0 0, 100% 50%, 0 100%);\n transform: translateY(-50%) rotate(0deg);\n opacity: 0.68;\n transition: transform 0.2s ease, opacity 0.2s ease;\n}\n.jw-foldable-list-item[open] > summary::before {\n transform: translateY(-50%) rotate(90deg);\n opacity: 0.85;\n}\n.jw-foldable-list-item > summary .jw-paragraph {\n display: inline;\n}\n\n.jw-image-figure { }\n.jw-image { max-width: 100%; max-height: 600px; width: auto; height: auto; object-fit: contain; }\n.jw-image-caption { margin-top: 0.5em; font-size: 0.9em; color: var(--jw-text-subtle); }\n.jw-image-figure[data-jw-shape=\"rounded\"] .jw-image { border-radius: 8px; }\n.jw-code-block {\n position: relative;\n display: flex;\n flex-direction: column;\n padding: 0;\n background: var(--jw-code-block-bg, var(--jw-surface-code));\n border: 1px solid var(--jw-code-border-color, var(--jw-border-color-subtle));\n border-radius: 4px;\n font-family: \"JetBrains Mono\", \"Fira Code\", Consolas, Menlo, monospace;\n font-size: 0.9em;\n line-height: 1.5;\n margin: 0;\n}\n.jw-code-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0.5em 0.75em;\n border-bottom: 1px solid var(--jw-code-border-color, var(--jw-border-color-subtle));\n background: var(--jw-code-header-bg, var(--jw-surface-overlay-1));\n color: var(--jw-code-header-text, var(--jw-text-subtle));\n}\n.jw-code-lang {\n padding: 0.1em 0.4em;\n background: var(--jw-code-lang-bg, var(--jw-surface-overlay-2));\n color: var(--jw-code-lang-text, var(--jw-text-subtle));\n font-size: 0.75em;\n border-radius: 3px;\n font-weight: 500;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\n.jw-code-copy {\n padding: 0.25em 0.5em;\n background: transparent;\n border: 1px solid var(--jw-code-copy-border, var(--jw-border-color));\n border-radius: 3px;\n cursor: pointer;\n font-size: 0.75em;\n color: var(--jw-code-header-text, var(--jw-text-subtle));\n transition: background 0.2s, border-color 0.2s;\n}\n.jw-code-copy:hover {\n background: var(--jw-code-copy-hover-bg, var(--jw-surface-overlay-2));\n border-color: var(--jw-code-copy-border, var(--jw-border-color-strong));\n}\n.jw-code-copy:active {\n background: var(--jw-surface-overlay-3);\n}\n.jw-code-content {\n display: flex;\n padding: 1em 1em 1em 0;\n}\n.jw-line-numbers {\n flex-shrink: 0;\n display: flex;\n flex-direction: column;\n padding: 0 0.75em;\n border-right: 1px solid var(--jw-code-border-color, var(--jw-border-color-subtle));\n text-align: right;\n user-select: none;\n color: var(--jw-code-line-number-color, var(--jw-text-faint));\n font-variant-numeric: tabular-nums;\n}\n.jw-line-number {\n display: block;\n min-height: 1.5em;\n}\n.jw-code {\n flex: 1;\n display: block;\n overflow-x: auto;\n padding: 0 1em;\n background: transparent;\n font-family: inherit;\n white-space: pre;\n}\n.jw-code-line {\n display: block;\n white-space: pre;\n min-height: 1.5em;\n}\n.jw-disabled-block { font-family: inherit; white-space: pre-wrap; line-height: var(--jw-line-height-base); margin: 0; }\n[data-jw-position=\"C\"] { margin-left: 33.33%; }\n[data-jw-position=\"R\"] { margin-left: 66.66%; }\n[data-jw-truncate-left=\"true\"] { margin-left: 0; }\n[data-jw-truncate-right=\"true\"] { max-width: 33.33%; word-wrap: break-word; overflow-wrap: break-word; }\n[data-jw-position=\"C\"][data-jw-truncate-right=\"true\"] { max-width: 33.33%; }\n[data-jw-position=\"R\"][data-jw-truncate-right=\"true\"] { max-width: 33.33%; }\n.jw-hr[data-jw-truncate-right=\"true\"] { width: 33.33%; max-width: none; }\n[data-jw-align=\"center\"] { text-align: center; }\n[data-jw-align=\"right\"] { text-align: right; }\n.jw-same-line-row { display: flex; flex-wrap: nowrap; gap: 0; align-items: flex-start; max-width: 100%; overflow: hidden; }\n.jw-same-line-row > * { flex-shrink: 1; word-wrap: break-word; overflow-wrap: break-word; min-width: 0; }\n.jw-same-line-row > [data-jw-position=\"L\"]:not(:last-child),\n.jw-same-line-row > [data-jw-position=\"C\"]:not(:last-child),\n.jw-same-line-row > [data-jw-position=\"R\"]:not(:last-child) { flex-basis: 33.33%; max-width: 33.33%; }\n.jw-same-line-row > [data-jw-position=\"L\"]:last-child,\n.jw-same-line-row > [data-jw-position=\"C\"]:last-child,\n.jw-same-line-row > [data-jw-position=\"R\"]:last-child { flex-grow: 1; flex-basis: 0; }\n.jw-same-line-row > [data-jw-position] { margin-left: 0; }\n.jw-same-line-row > [data-jw-position=\"C\"]:first-child { margin-left: 33.33%; }\n.jw-same-line-row > [data-jw-position=\"R\"]:first-child { margin-left: 66.66%; }\n.jw-meta { margin: 0 0 var(--jw-block-spacing); }\n.jw-meta-time,\n.jw-meta-add-info,\n.jw-meta-tags,\n.jw-meta-author {\n color: var(--jw-quote-text);\n}\n.jw-meta-author-link { text-decoration: none; color: inherit; }\n.jw-meta-author-link:hover { text-decoration: underline; }\n.jw-comment-inline { display: none; }\n.jw-comment-block { display: none; }\n";
@@ -1,10 +1,5 @@
1
1
  "use strict";
2
2
  const BASE_CSS = `
3
- html,
4
- body {
5
- margin: 0;
6
- padding: 0;
7
- }
8
3
  .jw-root {
9
4
  background-color: var(--jw-bg-color, transparent);
10
5
  color: var(--jw-text-color, inherit);
@@ -13,14 +8,46 @@ body {
13
8
  }
14
9
  .jw-root > .jw-block + .jw-block { margin-top: var(--jw-block-spacing); }
15
10
  .jw-root > .jw-block { margin: 0; }
16
- .jw-table { border-collapse: collapse; }
17
- .jw-table-cell { border: 1px solid var(--jw-border-color); padding: 0.5em; }
11
+ .jw-table { border-collapse: collapse; width: 100%; }
12
+ .jw-table-cell {
13
+ border: 1px solid var(--jw-table-border-color, var(--jw-border-color));
14
+ padding: 0.5em;
15
+ }
16
+ .jw-table thead .jw-table-cell {
17
+ background: var(--jw-table-header-bg, var(--jw-surface-overlay-1));
18
+ color: var(--jw-table-header-text, var(--jw-text-strong));
19
+ font-weight: 600;
20
+ }
21
+ .jw-table tbody .jw-table-row:nth-child(odd) .jw-table-cell {
22
+ background: var(--jw-table-row-bg, transparent);
23
+ }
24
+ .jw-table tbody .jw-table-row:nth-child(even) .jw-table-cell {
25
+ background: var(--jw-table-row-alt-bg, transparent);
26
+ }
18
27
  .jw-link { text-decoration: none; color: var(--jw-link-color, currentColor); }
19
28
  .jw-link:visited { color: var(--jw-link-color, currentColor); }
20
29
  .jw-link:hover { text-decoration: underline; }
21
- .jw-underline { text-decoration: underline; }
22
- .jw-strike { text-decoration: line-through; }
23
- .jw-wave { text-decoration: underline; text-decoration-style: wavy; }
30
+ .jw-root strong {
31
+ color: var(--jw-strong-color, currentColor);
32
+ font-weight: var(--jw-strong-weight, 700);
33
+ }
34
+ .jw-underline {
35
+ text-decoration: underline;
36
+ text-decoration-color: var(--jw-underline-color, currentColor);
37
+ text-decoration-thickness: var(--jw-underline-thickness, from-font);
38
+ text-underline-offset: var(--jw-underline-offset, auto);
39
+ }
40
+ .jw-strike {
41
+ text-decoration: line-through;
42
+ text-decoration-color: var(--jw-strike-color, currentColor);
43
+ }
44
+ .jw-wave {
45
+ text-decoration: underline;
46
+ text-decoration-style: wavy;
47
+ text-decoration-color: var(--jw-wave-color, currentColor);
48
+ text-decoration-thickness: var(--jw-underline-thickness, from-font);
49
+ text-underline-offset: var(--jw-underline-offset, auto);
50
+ }
24
51
  .jw-heading { font-weight: bold; margin: 0; }
25
52
  .jw-heading.level-1 { font-size: 2.5em; }
26
53
  .jw-heading.level-2 { font-size: 2em; }
@@ -271,8 +298,8 @@ body {
271
298
  display: flex;
272
299
  flex-direction: column;
273
300
  padding: 0;
274
- background: var(--jw-surface-code);
275
- border: 1px solid var(--jw-border-color-subtle);
301
+ background: var(--jw-code-block-bg, var(--jw-surface-code));
302
+ border: 1px solid var(--jw-code-border-color, var(--jw-border-color-subtle));
276
303
  border-radius: 4px;
277
304
  font-family: "JetBrains Mono", "Fira Code", Consolas, Menlo, monospace;
278
305
  font-size: 0.9em;
@@ -284,13 +311,14 @@ body {
284
311
  justify-content: space-between;
285
312
  align-items: center;
286
313
  padding: 0.5em 0.75em;
287
- border-bottom: 1px solid var(--jw-border-color-subtle);
288
- background: var(--jw-surface-overlay-1);
314
+ border-bottom: 1px solid var(--jw-code-border-color, var(--jw-border-color-subtle));
315
+ background: var(--jw-code-header-bg, var(--jw-surface-overlay-1));
316
+ color: var(--jw-code-header-text, var(--jw-text-subtle));
289
317
  }
290
318
  .jw-code-lang {
291
319
  padding: 0.1em 0.4em;
292
- background: var(--jw-surface-overlay-2);
293
- color: var(--jw-text-subtle);
320
+ background: var(--jw-code-lang-bg, var(--jw-surface-overlay-2));
321
+ color: var(--jw-code-lang-text, var(--jw-text-subtle));
294
322
  font-size: 0.75em;
295
323
  border-radius: 3px;
296
324
  font-weight: 500;
@@ -300,16 +328,16 @@ body {
300
328
  .jw-code-copy {
301
329
  padding: 0.25em 0.5em;
302
330
  background: transparent;
303
- border: 1px solid var(--jw-border-color);
331
+ border: 1px solid var(--jw-code-copy-border, var(--jw-border-color));
304
332
  border-radius: 3px;
305
333
  cursor: pointer;
306
334
  font-size: 0.75em;
307
- color: var(--jw-text-subtle);
335
+ color: var(--jw-code-header-text, var(--jw-text-subtle));
308
336
  transition: background 0.2s, border-color 0.2s;
309
337
  }
310
338
  .jw-code-copy:hover {
311
- background: var(--jw-surface-overlay-2);
312
- border-color: var(--jw-border-color-strong);
339
+ background: var(--jw-code-copy-hover-bg, var(--jw-surface-overlay-2));
340
+ border-color: var(--jw-code-copy-border, var(--jw-border-color-strong));
313
341
  }
314
342
  .jw-code-copy:active {
315
343
  background: var(--jw-surface-overlay-3);
@@ -323,10 +351,10 @@ body {
323
351
  display: flex;
324
352
  flex-direction: column;
325
353
  padding: 0 0.75em;
326
- border-right: 1px solid var(--jw-border-color-subtle);
354
+ border-right: 1px solid var(--jw-code-border-color, var(--jw-border-color-subtle));
327
355
  text-align: right;
328
356
  user-select: none;
329
- color: var(--jw-text-faint);
357
+ color: var(--jw-code-line-number-color, var(--jw-text-faint));
330
358
  font-variant-numeric: tabular-nums;
331
359
  }
332
360
  .jw-line-number {
@@ -40,6 +40,30 @@ const DARK_CSS = `
40
40
  --jw-task-not-done-cross: #eef1f7;
41
41
  --jw-task-in-progress: #b7bdca;
42
42
 
43
+ --jw-strong-color: #f3f5f8;
44
+ --jw-strong-weight: 700;
45
+ --jw-underline-color: #8ab4f8;
46
+ --jw-underline-thickness: 0.08em;
47
+ --jw-underline-offset: 0.12em;
48
+ --jw-wave-color: #8ab4f8;
49
+ --jw-strike-color: #98a2b3;
50
+
51
+ --jw-table-border-color: #374151;
52
+ --jw-table-header-bg: #1f2937;
53
+ --jw-table-header-text: #d1d5db;
54
+ --jw-table-row-bg: #141922;
55
+ --jw-table-row-alt-bg: #171d28;
56
+
57
+ --jw-code-block-bg: #1c1f26;
58
+ --jw-code-border-color: #313846;
59
+ --jw-code-header-bg: rgba(255, 255, 255, 0.05);
60
+ --jw-code-header-text: #b8c2d3;
61
+ --jw-code-lang-bg: rgba(255, 255, 255, 0.08);
62
+ --jw-code-lang-text: #d1d8e3;
63
+ --jw-code-copy-border: #4b5563;
64
+ --jw-code-copy-hover-bg: rgba(255, 255, 255, 0.12);
65
+ --jw-code-line-number-color: #8b95a7;
66
+
43
67
  --jw-color-red: ${PRESET_COLORS.red};
44
68
  --jw-color-orange: ${PRESET_COLORS.orange};
45
69
  --jw-color-yellow: ${PRESET_COLORS.yellow};
@@ -92,6 +116,30 @@ const DARK_CSS = `
92
116
  --jw-task-not-done-cross: #eef1f7;
93
117
  --jw-task-in-progress: #b7bdca;
94
118
 
119
+ --jw-strong-color: #f3f5f8;
120
+ --jw-strong-weight: 700;
121
+ --jw-underline-color: #8ab4f8;
122
+ --jw-underline-thickness: 0.08em;
123
+ --jw-underline-offset: 0.12em;
124
+ --jw-wave-color: #8ab4f8;
125
+ --jw-strike-color: #98a2b3;
126
+
127
+ --jw-table-border-color: #374151;
128
+ --jw-table-header-bg: #1f2937;
129
+ --jw-table-header-text: #d1d5db;
130
+ --jw-table-row-bg: #141922;
131
+ --jw-table-row-alt-bg: #171d28;
132
+
133
+ --jw-code-block-bg: #1c1f26;
134
+ --jw-code-border-color: #313846;
135
+ --jw-code-header-bg: rgba(255, 255, 255, 0.05);
136
+ --jw-code-header-text: #b8c2d3;
137
+ --jw-code-lang-bg: rgba(255, 255, 255, 0.08);
138
+ --jw-code-lang-text: #d1d8e3;
139
+ --jw-code-copy-border: #4b5563;
140
+ --jw-code-copy-hover-bg: rgba(255, 255, 255, 0.12);
141
+ --jw-code-line-number-color: #8b95a7;
142
+
95
143
  --jw-color-red: ${PRESET_COLORS.red};
96
144
  --jw-color-orange: ${PRESET_COLORS.orange};
97
145
  --jw-color-yellow: ${PRESET_COLORS.yellow};