@owomark/view 0.1.4 → 0.1.6

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/index.js CHANGED
@@ -1,23 +1,3 @@
1
- import {
2
- Callout,
3
- CodeDemo,
4
- DEFAULT_MDX_COMPONENTS,
5
- FileTree,
6
- Kbd,
7
- Step,
8
- Steps,
9
- THEME_DARK_CLASS,
10
- THEME_LIGHT_CLASS,
11
- Tab,
12
- Tabs,
13
- createOwoMarkProcessor,
14
- getOwoMarkPlugins,
15
- getThemeClassName,
16
- rehypeMathDisplayFix,
17
- rehypeSideAnnotation,
18
- remarkConvertSoftBreaksToHardBreaks,
19
- remarkSideAnnotation
20
- } from "./chunk-DHRAXGIK.js";
21
1
  import {
22
2
  BlockLayoutMap
23
3
  } from "./chunk-3CKPBCIP.js";
@@ -27,10 +7,12 @@ import {
27
7
  import {
28
8
  FALLBACK_BLOCK_HEIGHT,
29
9
  estimateBlockHeight
30
- } from "./chunk-Y72HQJQI.js";
10
+ } from "./chunk-KHKPOH74.js";
31
11
  import {
32
- VirtualViewportManager
33
- } from "./chunk-F3LG7AML.js";
12
+ VirtualViewportManager,
13
+ createSkeletonHtml,
14
+ ensureSkeletonStyles
15
+ } from "./chunk-WA6XHBZS.js";
34
16
 
35
17
  // src/editor.ts
36
18
  import { createDomAdapter } from "@owomark/core/internal/dom-adapter";
@@ -829,17 +811,60 @@ var PreviewDomPatcher = class {
829
811
  };
830
812
 
831
813
  // src/renderer/registry.ts
814
+ var DEFAULT_HEAVY_KINDS = [
815
+ { kind: "mermaid", meta: { mode: "html-worker-safe", priority: "deferred", heavy: true } },
816
+ { kind: "katex", meta: { mode: "html-worker-safe", priority: "deferred", heavy: true } },
817
+ { kind: "math-block", meta: { mode: "html-worker-safe", priority: "deferred", heavy: true } },
818
+ { kind: "chart", meta: { mode: "html-worker-safe", priority: "deferred", heavy: true } },
819
+ { kind: "embed", meta: { mode: "html-worker-safe", priority: "deferred", heavy: true } }
820
+ ];
832
821
  function createRendererRegistry() {
833
822
  const renderers = /* @__PURE__ */ new Map();
823
+ const metadata = /* @__PURE__ */ new Map();
824
+ for (const { kind, meta } of DEFAULT_HEAVY_KINDS) {
825
+ metadata.set(kind, meta);
826
+ }
834
827
  return {
835
828
  get(kind) {
836
829
  return renderers.get(kind) ?? null;
837
830
  },
838
831
  register(kind, renderer) {
839
832
  renderers.set(kind, renderer);
833
+ if (!metadata.has(kind)) {
834
+ metadata.set(kind, {
835
+ mode: renderer.mode,
836
+ priority: renderer.priority
837
+ });
838
+ }
840
839
  },
841
840
  unregister(kind) {
842
841
  renderers.delete(kind);
842
+ },
843
+ registerMetadata(kind, meta) {
844
+ metadata.set(kind, meta);
845
+ },
846
+ isHeavy(kind) {
847
+ const meta = metadata.get(kind);
848
+ if (meta?.heavy) return true;
849
+ const def = renderers.get(kind);
850
+ return def?.priority === "deferred" || false;
851
+ },
852
+ getMode(kind) {
853
+ const def = renderers.get(kind);
854
+ if (def) return def.mode;
855
+ return metadata.get(kind)?.mode ?? null;
856
+ },
857
+ getPriority(kind) {
858
+ const def = renderers.get(kind);
859
+ if (def) return def.priority;
860
+ return metadata.get(kind)?.priority ?? null;
861
+ },
862
+ listRegistered() {
863
+ const kinds = /* @__PURE__ */ new Set([
864
+ ...renderers.keys(),
865
+ ...metadata.keys()
866
+ ]);
867
+ return Array.from(kinds);
843
868
  }
844
869
  };
845
870
  }
@@ -948,7 +973,7 @@ function isDeferred(block, registry) {
948
973
  const def = registry.get(block.kind);
949
974
  return def?.priority === "deferred";
950
975
  }
951
- function createRenderBlockFull(registry, renderCache, externalRenderBlock) {
976
+ function createRenderBlockFull(registry, renderCache, externalRenderBlock, scheduler) {
952
977
  return async function renderBlockFull(block, baseContext) {
953
978
  const context = {
954
979
  ...baseContext,
@@ -956,6 +981,14 @@ function createRenderBlockFull(registry, renderCache, externalRenderBlock) {
956
981
  };
957
982
  const customRenderer = registry.get(block.kind);
958
983
  if (customRenderer) {
984
+ if (customRenderer.mode === "html-worker-safe" && customRenderer.workerModuleUrl && scheduler) {
985
+ try {
986
+ const html2 = await scheduler.submitWorkerTask(block, customRenderer, context);
987
+ renderCache.set(block.renderKey, html2);
988
+ return { kind: "html", html: html2 };
989
+ } catch {
990
+ }
991
+ }
959
992
  const result = await customRenderer.render(block, context);
960
993
  if (result.kind === "html") {
961
994
  renderCache.set(block.renderKey, result.html);
@@ -982,6 +1015,7 @@ function createIncrementalEngine(options) {
982
1015
  const themeKey = options?.themeKey ?? "";
983
1016
  const viewportFirst = options?.viewportFirst ?? false;
984
1017
  const registry = options?.registry ?? createRendererRegistry();
1018
+ const scheduler = options?.scheduler;
985
1019
  const externalRenderBlock = options?.renderBlock;
986
1020
  const onContentUpdate = options?.onContentUpdate;
987
1021
  const patcher = new PreviewDomPatcher();
@@ -992,7 +1026,7 @@ function createIncrementalEngine(options) {
992
1026
  let pendingAbort = null;
993
1027
  let pendingIdleIds = [];
994
1028
  let pendingBackfill = /* @__PURE__ */ new Set();
995
- const renderBlockFull = createRenderBlockFull(registry, renderCache, externalRenderBlock);
1029
+ const renderBlockFull = createRenderBlockFull(registry, renderCache, externalRenderBlock, scheduler);
996
1030
  function applyResult(blockId, result) {
997
1031
  if (result.kind === "html") {
998
1032
  patcher.patchBlockHtml(blockId, result.html);
@@ -1038,12 +1072,14 @@ function createIncrementalEngine(options) {
1038
1072
  return {
1039
1073
  mount(root) {
1040
1074
  patcher.mount(root);
1075
+ ensureSkeletonStyles(root.ownerDocument);
1041
1076
  mounted = true;
1042
1077
  },
1043
1078
  destroy() {
1044
1079
  pendingAbort?.abort();
1045
1080
  pendingAbort = null;
1046
1081
  cancelAllIdle(pendingIdleIds);
1082
+ scheduler?.release();
1047
1083
  patcher.destroy();
1048
1084
  renderCache.clear();
1049
1085
  pendingBackfill.clear();
@@ -1121,18 +1157,26 @@ function createIncrementalEngine(options) {
1121
1157
  }
1122
1158
  }
1123
1159
  if (signal.aborted) return;
1160
+ pendingBackfill = /* @__PURE__ */ new Set();
1161
+ for (const block of realtimeOffscreen) {
1162
+ const height = estimateBlockHeight(block, registry);
1163
+ htmlMap.set(block.blockId, createSkeletonHtml({ height }));
1164
+ pendingBackfill.add(block.blockId);
1165
+ }
1166
+ for (const block of deferredAll) {
1167
+ const height = estimateBlockHeight(block, registry);
1168
+ htmlMap.set(block.blockId, createSkeletonHtml({ height }));
1169
+ pendingBackfill.add(block.blockId);
1170
+ }
1124
1171
  patcher.fullRender(blocks, htmlMap);
1125
1172
  for (const { blockId, result } of domMounts) {
1126
1173
  if (signal.aborted) return;
1127
1174
  applyResult(blockId, result);
1128
1175
  }
1129
- pendingBackfill = /* @__PURE__ */ new Set();
1130
1176
  for (const block of realtimeOffscreen) {
1131
- pendingBackfill.add(block.blockId);
1132
1177
  scheduleBlockRender(block, baseContext, signal, state.version);
1133
1178
  }
1134
1179
  for (const block of deferredAll) {
1135
- pendingBackfill.add(block.blockId);
1136
1180
  scheduleBlockRender(block, baseContext, signal, state.version);
1137
1181
  }
1138
1182
  }
@@ -1249,6 +1293,7 @@ var OffscreenMeasurer = class {
1249
1293
  function createVirtualEngine(options) {
1250
1294
  const themeKey = options?.themeKey ?? "";
1251
1295
  const registry = options?.registry ?? createRendererRegistry();
1296
+ const scheduler = options?.scheduler;
1252
1297
  const externalRenderBlock = options?.renderBlock;
1253
1298
  const onContentUpdate = options?.onContentUpdate;
1254
1299
  const layoutMap = new BlockLayoutMap();
@@ -1256,7 +1301,7 @@ function createVirtualEngine(options) {
1256
1301
  const measurer = new OffscreenMeasurer();
1257
1302
  const viewport = new VirtualViewportManager();
1258
1303
  const renderCache = /* @__PURE__ */ new Map();
1259
- const renderBlockFull = createRenderBlockFull(registry, renderCache, externalRenderBlock);
1304
+ const renderBlockFull = createRenderBlockFull(registry, renderCache, externalRenderBlock, scheduler);
1260
1305
  let renderedVersion = 0;
1261
1306
  let lastBlocks = [];
1262
1307
  let blockMap = /* @__PURE__ */ new Map();
@@ -1273,7 +1318,7 @@ function createVirtualEngine(options) {
1273
1318
  function getInitialHeight(block) {
1274
1319
  const cached = heightCache.get(block.renderKey);
1275
1320
  if (cached !== void 0) return cached;
1276
- return estimateBlockHeight(block);
1321
+ return estimateBlockHeight(block, registry);
1277
1322
  }
1278
1323
  async function renderAndMountBlock(block, baseContext, signal) {
1279
1324
  if (signal.aborted) return;
@@ -1385,7 +1430,7 @@ function createVirtualEngine(options) {
1385
1430
  heightCache.clear();
1386
1431
  layoutMap.invalidateAll((blockId) => {
1387
1432
  const block = blockMap.get(blockId);
1388
- return block ? estimateBlockHeight(block) : FALLBACK_BLOCK_HEIGHT;
1433
+ return block ? estimateBlockHeight(block, registry) : FALLBACK_BLOCK_HEIGHT;
1389
1434
  });
1390
1435
  return true;
1391
1436
  }
@@ -1420,6 +1465,7 @@ function createVirtualEngine(options) {
1420
1465
  blockResizeObserver?.disconnect();
1421
1466
  blockResizeObserver = null;
1422
1467
  observedWrappers.clear();
1468
+ scheduler?.release();
1423
1469
  viewport.destroy();
1424
1470
  measurer.destroy();
1425
1471
  renderCache.clear();
@@ -1545,11 +1591,185 @@ function createOwoMarkPreviewEngine(options) {
1545
1591
  return createIncrementalEngine(options);
1546
1592
  case "virtual":
1547
1593
  return createVirtualEngine(options);
1594
+ case "mdx":
1595
+ throw new Error(
1596
+ 'The "mdx" strategy is implemented by @owomark/react OwoMarkPreview, not by @owomark/view createOwoMarkPreviewEngine().'
1597
+ );
1548
1598
  default:
1549
1599
  throw new Error(`Unknown preview strategy: ${strategy}`);
1550
1600
  }
1551
1601
  }
1552
1602
 
1603
+ // src/worker/preview-task-scheduler.ts
1604
+ var MAX_CONSECUTIVE_CRASHES = 3;
1605
+ var CRASH_WINDOW_MS = 3e4;
1606
+ function serializeBlock(block) {
1607
+ return {
1608
+ kind: block.kind,
1609
+ raw: block.raw,
1610
+ blockId: block.blockId,
1611
+ renderKey: block.renderKey,
1612
+ startLine: block.startLine,
1613
+ endLine: block.endLine
1614
+ };
1615
+ }
1616
+ function createPreviewTaskScheduler(options) {
1617
+ const poolSize = options?.poolSize ?? Math.max(1, (typeof navigator !== "undefined" ? navigator.hardwareConcurrency ?? 4 : 4) - 1);
1618
+ let refCount = 1;
1619
+ let taskCounter = 0;
1620
+ let permanentlyFailed = false;
1621
+ const crashTimestamps = [];
1622
+ const pendingTasks = /* @__PURE__ */ new Map();
1623
+ const workers = [];
1624
+ let nextWorkerIndex = 0;
1625
+ function createWorkerSlot() {
1626
+ try {
1627
+ if (typeof Worker === "undefined") return null;
1628
+ const worker = new Worker(
1629
+ new URL("./preview-render.worker.js", import.meta.url),
1630
+ { type: "module" }
1631
+ );
1632
+ const slot = { worker, pendingCount: 0, dead: false };
1633
+ worker.onmessage = (e) => {
1634
+ const resp = e.data;
1635
+ slot.pendingCount--;
1636
+ const pending = pendingTasks.get(resp.taskId);
1637
+ if (!pending) return;
1638
+ pendingTasks.delete(resp.taskId);
1639
+ if (resp.ok) {
1640
+ pending.resolve(resp.html);
1641
+ } else {
1642
+ pending.reject(new Error(resp.error));
1643
+ }
1644
+ };
1645
+ worker.onerror = () => {
1646
+ slot.dead = true;
1647
+ slot.pendingCount = 0;
1648
+ worker.terminate();
1649
+ recordCrash();
1650
+ options?.onCrash?.();
1651
+ };
1652
+ return slot;
1653
+ } catch {
1654
+ return null;
1655
+ }
1656
+ }
1657
+ function recordCrash() {
1658
+ const now = Date.now();
1659
+ crashTimestamps.push(now);
1660
+ while (crashTimestamps.length > 0 && now - crashTimestamps[0] > CRASH_WINDOW_MS) {
1661
+ crashTimestamps.shift();
1662
+ }
1663
+ if (crashTimestamps.length >= MAX_CONSECUTIVE_CRASHES) {
1664
+ permanentlyFailed = true;
1665
+ terminateAll();
1666
+ }
1667
+ }
1668
+ function getLeastBusySlot() {
1669
+ if (permanentlyFailed) return null;
1670
+ let best = null;
1671
+ for (const slot of workers) {
1672
+ if (slot.dead) continue;
1673
+ if (!best || slot.pendingCount < best.pendingCount) {
1674
+ best = slot;
1675
+ }
1676
+ }
1677
+ if (best) return best;
1678
+ if (workers.length < poolSize) {
1679
+ const slot = createWorkerSlot();
1680
+ if (slot) {
1681
+ workers.push(slot);
1682
+ return slot;
1683
+ }
1684
+ }
1685
+ for (let i = 0; i < workers.length; i++) {
1686
+ if (workers[i].dead) {
1687
+ const slot = createWorkerSlot();
1688
+ if (slot) {
1689
+ workers[i] = slot;
1690
+ return slot;
1691
+ }
1692
+ }
1693
+ }
1694
+ return null;
1695
+ }
1696
+ function terminateAll() {
1697
+ for (const slot of workers) {
1698
+ if (!slot.dead) {
1699
+ slot.dead = true;
1700
+ slot.worker.terminate();
1701
+ }
1702
+ }
1703
+ workers.length = 0;
1704
+ for (const [, pending] of pendingTasks) {
1705
+ pending.reject(new Error("Scheduler terminated"));
1706
+ }
1707
+ pendingTasks.clear();
1708
+ }
1709
+ const scheduler = {
1710
+ submitWorkerTask(block, rendererDef, context) {
1711
+ if (permanentlyFailed || !rendererDef.workerModuleUrl) {
1712
+ return Promise.reject(new Error("Worker unavailable"));
1713
+ }
1714
+ const slot = getLeastBusySlot();
1715
+ if (!slot) {
1716
+ return Promise.reject(new Error("No worker available"));
1717
+ }
1718
+ const taskId = ++taskCounter;
1719
+ return new Promise((resolve, reject) => {
1720
+ pendingTasks.set(taskId, { resolve, reject });
1721
+ slot.pendingCount++;
1722
+ slot.worker.postMessage({
1723
+ type: "render",
1724
+ taskId,
1725
+ block: serializeBlock(block),
1726
+ rendererModuleUrl: rendererDef.workerModuleUrl,
1727
+ context: {
1728
+ version: context.version,
1729
+ themeKey: context.themeKey,
1730
+ sourceLineOffset: context.sourceLineOffset
1731
+ }
1732
+ });
1733
+ });
1734
+ },
1735
+ cancel(taskId) {
1736
+ const pending = pendingTasks.get(taskId);
1737
+ if (pending) {
1738
+ pendingTasks.delete(taskId);
1739
+ pending.reject(new Error("Task cancelled"));
1740
+ }
1741
+ const msg = { type: "cancel", taskId };
1742
+ for (const slot of workers) {
1743
+ if (!slot.dead) slot.worker.postMessage(msg);
1744
+ }
1745
+ },
1746
+ cancelAll() {
1747
+ for (const [, pending] of pendingTasks) {
1748
+ pending.reject(new Error("All tasks cancelled"));
1749
+ }
1750
+ pendingTasks.clear();
1751
+ const msg = { type: "cancel-all" };
1752
+ for (const slot of workers) {
1753
+ if (!slot.dead) {
1754
+ slot.pendingCount = 0;
1755
+ slot.worker.postMessage(msg);
1756
+ }
1757
+ }
1758
+ },
1759
+ acquire() {
1760
+ refCount++;
1761
+ return scheduler;
1762
+ },
1763
+ release() {
1764
+ if (--refCount <= 0) {
1765
+ refCount = 0;
1766
+ terminateAll();
1767
+ }
1768
+ }
1769
+ };
1770
+ return scheduler;
1771
+ }
1772
+
1553
1773
  // src/dom/side-annotation-positioner.ts
1554
1774
  var SideAnnotationPositioner = class {
1555
1775
  container;
@@ -1639,31 +1859,33 @@ var SideAnnotationPositioner = class {
1639
1859
  }
1640
1860
  }
1641
1861
  };
1862
+
1863
+ // src/theme.ts
1864
+ var THEME_LIGHT_CLASS = "owo-theme-light";
1865
+ var THEME_DARK_CLASS = "owo-theme-dark";
1866
+ function getThemeClassName(theme) {
1867
+ switch (theme) {
1868
+ case "light":
1869
+ return THEME_LIGHT_CLASS;
1870
+ case "dark":
1871
+ return THEME_DARK_CLASS;
1872
+ default:
1873
+ return theme;
1874
+ }
1875
+ }
1642
1876
  export {
1643
- Callout,
1644
- CodeDemo,
1645
- DEFAULT_MDX_COMPONENTS,
1646
- FileTree,
1647
- Kbd,
1648
1877
  PreviewDomPatcher,
1649
1878
  SideAnnotationPositioner,
1650
- Step,
1651
- Steps,
1652
1879
  THEME_DARK_CLASS,
1653
1880
  THEME_LIGHT_CLASS,
1654
- Tab,
1655
- Tabs,
1656
1881
  createOwoMarkPreviewEngine,
1657
- createOwoMarkProcessor,
1658
1882
  createOwoMarkVanillaEditor,
1659
1883
  createOwoMarkView,
1884
+ createPreviewTaskScheduler,
1660
1885
  createRendererRegistry,
1886
+ createSkeletonHtml,
1661
1887
  createViewEngine,
1662
- getOwoMarkPlugins,
1888
+ ensureSkeletonStyles,
1663
1889
  getThemeClassName,
1664
- rehypeMathDisplayFix,
1665
- rehypeSideAnnotation,
1666
- remarkConvertSoftBreaksToHardBreaks,
1667
- remarkSideAnnotation,
1668
1890
  renderBlockDefault
1669
1891
  };
@@ -1,13 +1,6 @@
1
1
  import { PreviewBlock } from '@owomark/core';
2
+ import { P as PreviewRendererRegistry } from '../../types-DsL_4tUb.js';
2
3
 
3
- /**
4
- * Heuristic height estimation for blocks before measurement.
5
- *
6
- * Uses block kind and source line count to produce a rough height estimate.
7
- * These estimates are used as initial placeholder heights in the coordinate
8
- * table until real measurement completes.
9
- */
10
-
11
- declare function estimateBlockHeight(block: PreviewBlock): number;
4
+ declare function estimateBlockHeight(block: PreviewBlock, registry?: PreviewRendererRegistry): number;
12
5
 
13
6
  export { estimateBlockHeight };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  estimateBlockHeight
3
- } from "../../chunk-Y72HQJQI.js";
3
+ } from "../../chunk-KHKPOH74.js";
4
4
  export {
5
5
  estimateBlockHeight
6
6
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  VirtualViewportManager
3
- } from "../../chunk-F3LG7AML.js";
3
+ } from "../../chunk-WA6XHBZS.js";
4
4
  export {
5
5
  VirtualViewportManager
6
6
  };
@@ -0,0 +1,93 @@
1
+ import { OwoMarkSharedState, PreviewBlockKind, PreviewBlock } from '@owomark/core';
2
+
3
+ type PreviewRenderPhase = 'idle' | 'rendering' | 'highlighting' | 'ready' | 'error';
4
+ type PreviewCacheEntry = {
5
+ blockId: string;
6
+ renderKey: string;
7
+ html: string;
8
+ highlighted: boolean;
9
+ themeKey: string;
10
+ updatedAt: number;
11
+ };
12
+ type PreviewRenderContext = {
13
+ version: number;
14
+ themeKey: string;
15
+ abortSignal?: AbortSignal;
16
+ /**
17
+ * Line offset to add to source-line attributes in the rendered HTML.
18
+ * When a block starts at line N in the document, the renderer processes
19
+ * its raw content starting from line 1; this offset (N - 1) must be
20
+ * added to `data-source-line-start/end` so scroll sync anchors map
21
+ * to the correct document lines.
22
+ */
23
+ sourceLineOffset: number;
24
+ };
25
+ type PreviewRenderResult = {
26
+ kind: 'html';
27
+ html: string;
28
+ } | {
29
+ kind: 'dom';
30
+ mount: (container: HTMLElement) => void;
31
+ unmount?: () => void;
32
+ };
33
+ type PreviewRendererMode = 'html-worker-safe' | 'dom-main-thread';
34
+ type PreviewTaskPriority = 'realtime' | 'deferred';
35
+ type PreviewRendererDefinition = {
36
+ mode: PreviewRendererMode;
37
+ priority: PreviewTaskPriority;
38
+ render: PreviewBlockRenderer;
39
+ version: string;
40
+ workerModuleUrl?: string;
41
+ };
42
+ type PreviewBlockRenderer = (block: PreviewBlock, context: PreviewRenderContext) => Promise<PreviewRenderResult> | PreviewRenderResult;
43
+ type PreviewBlockMetadata = {
44
+ mode: PreviewRendererMode;
45
+ priority: PreviewTaskPriority;
46
+ heavy?: boolean;
47
+ };
48
+ type PreviewRendererRegistry = {
49
+ get(kind: PreviewBlockKind): PreviewRendererDefinition | null;
50
+ register(kind: PreviewBlockKind, renderer: PreviewRendererDefinition): void;
51
+ unregister(kind: PreviewBlockKind): void;
52
+ registerMetadata(kind: PreviewBlockKind, meta: PreviewBlockMetadata): void;
53
+ isHeavy(kind: PreviewBlockKind): boolean;
54
+ getMode(kind: PreviewBlockKind): PreviewRendererMode | null;
55
+ getPriority(kind: PreviewBlockKind): PreviewTaskPriority | null;
56
+ listRegistered(): PreviewBlockKind[];
57
+ };
58
+ type PreviewTaskScheduler = {
59
+ submitWorkerTask(block: PreviewBlock, rendererDef: PreviewRendererDefinition, context: PreviewRenderContext): Promise<string>;
60
+ cancel(taskId: number): void;
61
+ cancelAll(): void;
62
+ acquire(): PreviewTaskScheduler;
63
+ release(): void;
64
+ };
65
+ type PreviewStrategy = 'incremental' | 'virtual' | 'mdx';
66
+ type OwoMarkPreviewEngineOptions = {
67
+ strategy?: PreviewStrategy;
68
+ themeKey?: string;
69
+ registry?: PreviewRendererRegistry;
70
+ scheduler?: PreviewTaskScheduler;
71
+ viewportFirst?: boolean;
72
+ /**
73
+ * External block renderer function. When provided, the engine uses this
74
+ * instead of the built-in default renderer. This allows the host to supply
75
+ * its own Markdown pipeline (unified, remark, rehype, Shiki, etc.) without
76
+ * the preview package bundling those heavy dependencies.
77
+ */
78
+ renderBlock?: (block: PreviewBlock, context: PreviewRenderContext) => Promise<string>;
79
+ /**
80
+ * Called after every DOM mutation — including idle-backfilled and deferred
81
+ * block renders — not just after the synchronous update() return.
82
+ * Use for scroll sync or other post-DOM-update side effects.
83
+ */
84
+ onContentUpdate?: () => void;
85
+ };
86
+ type OwoMarkPreviewEngine = {
87
+ mount(root: HTMLElement): void;
88
+ destroy(): void;
89
+ update(state: OwoMarkSharedState): void;
90
+ getRenderedVersion(): number;
91
+ };
92
+
93
+ export type { OwoMarkPreviewEngineOptions as O, PreviewRendererRegistry as P, OwoMarkPreviewEngine as a, PreviewTaskScheduler as b, PreviewBlockMetadata as c, PreviewBlockRenderer as d, PreviewCacheEntry as e, PreviewRenderContext as f, PreviewRenderPhase as g, PreviewRenderResult as h, PreviewRendererDefinition as i, PreviewRendererMode as j, PreviewStrategy as k, PreviewTaskPriority as l };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owomark/view",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Rendering engine, preview engine, DOM view layer, and official base theme for OwoMark.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -21,10 +21,6 @@
21
21
  "types": "./dist/index.d.ts",
22
22
  "import": "./dist/index.js"
23
23
  },
24
- "./static": {
25
- "types": "./dist/static.d.ts",
26
- "import": "./dist/static.js"
27
- },
28
24
  "./internal/virtual/block-layout-map": {
29
25
  "types": "./dist/internal/virtual/block-layout-map.d.ts",
30
26
  "import": "./dist/internal/virtual/block-layout-map.js"
@@ -42,7 +38,6 @@
42
38
  "import": "./dist/internal/virtual/viewport-manager.js"
43
39
  },
44
40
  "./style.css": "./src/style.css",
45
- "./mdx-components.css": "./src/mdx-components/mdx-components.css",
46
41
  "./owomark.css": "./src/theme/owomark.css",
47
42
  "./preview.css": "./src/theme/preview.css",
48
43
  "./light.css": "./src/theme/light.css",
@@ -53,12 +48,10 @@
53
48
  "files": [
54
49
  "dist",
55
50
  "src/style.css",
56
- "src/mdx-components/mdx-components.css",
57
51
  "src/theme"
58
52
  ],
59
53
  "sideEffects": [
60
54
  "./src/style.css",
61
- "./src/mdx-components/mdx-components.css",
62
55
  "./src/theme/*.css"
63
56
  ],
64
57
  "scripts": {
@@ -69,38 +62,9 @@
69
62
  "access": "public"
70
63
  },
71
64
  "dependencies": {
72
- "@owomark/core": "^0.1.4",
73
- "rehype-katex": "^6.0.3",
74
- "rehype-pretty-code": "^0.14.1",
75
- "rehype-slug": "^6.0.0",
76
- "rehype-stringify": "^10.0.1",
77
- "remark-directive": "^4.0.0",
78
- "remark-gfm": "^4.0.1",
79
- "remark-math": "^6.0.0",
80
- "remark-mdx": "^3.1.0",
81
- "remark-parse": "^11.0.0",
82
- "remark-rehype": "^11.1.2",
83
- "shiki": "^3.23.0",
84
- "unified": "^11.0.5"
85
- },
86
- "peerDependencies": {
87
- "@mdx-js/mdx": "^3.0.0",
88
- "react": "^18.0.0 || ^19.0.0",
89
- "react-dom": "^18.0.0 || ^19.0.0"
90
- },
91
- "peerDependenciesMeta": {
92
- "@mdx-js/mdx": {
93
- "optional": true
94
- },
95
- "react": {
96
- "optional": true
97
- },
98
- "react-dom": {
99
- "optional": true
100
- }
65
+ "@owomark/core": "^0.1.6"
101
66
  },
102
67
  "devDependencies": {
103
- "@types/react": "^19.0.0",
104
68
  "tsup": "^8.5.1"
105
69
  }
106
70
  }
package/src/style.css CHANGED
@@ -2,9 +2,6 @@
2
2
  * Aggregates structural CSS and official base theme (light + dark presets).
3
3
  * Users who want fine-grained control can import each layer individually. */
4
4
 
5
- /* Structural: component skeletons with --owo-* token slots */
6
- @import './mdx-components/mdx-components.css';
7
-
8
5
  /* Structural: editor base styles consuming --owo-editor-* tokens */
9
6
  @import './theme/owomark.css';
10
7
  @import './theme/side-annotation.css';
@@ -59,8 +59,14 @@
59
59
  --owo-syntax-code-fence: #7f849c;
60
60
  --owo-syntax-code-lang: #fab387;
61
61
  --owo-syntax-list-marker: #fab387;
62
+ --owo-syntax-task-marker: #f9c74f;
63
+ --owo-syntax-task-marker-checked: #a6e3a1;
64
+ --owo-syntax-table-separator: #6c7086;
65
+ --owo-syntax-strikethrough: #cdd6f4;
62
66
  --owo-syntax-blockquote-marker: #585b70;
63
67
  --owo-syntax-hr: #45475a;
68
+ --owo-syntax-html: #cba6f7;
69
+ --owo-syntax-math: #94e2d5;
64
70
 
65
71
  /* Toolbar */
66
72
  --owo-toolbar-bg: #252536;