@owomark/react 0.1.5 → 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/README.md +49 -0
- package/dist/index.d.ts +26 -21
- package/dist/index.js +795 -99
- package/dist/mdx.worker.js +97 -0
- package/package.json +5 -4
- package/dist/index.css +0 -32
package/README.md
CHANGED
|
@@ -135,6 +135,8 @@ For hosts that still need `onChange` callbacks (e.g. for local draft persistence
|
|
|
135
135
|
/>
|
|
136
136
|
```
|
|
137
137
|
|
|
138
|
+
When `OwoMarkPreview` runs in `strategy="mdx"`, syntax detection may use internal probe-only masking. The MDX compile path may also apply a private compatibility normalization for indented code blocks, but compile errors and `data-source-line-*` anchors are remapped back to the original editor lines.
|
|
139
|
+
|
|
138
140
|
### Custom Block Renderer
|
|
139
141
|
|
|
140
142
|
Provide a host-side rendering function for full Markdown fidelity (GFM, math, syntax highlighting):
|
|
@@ -272,6 +274,53 @@ import '@owomark/view/style.css'; // includes owomark.css + side-annotation.css
|
|
|
272
274
|
import '@owomark/processor/mdx-components.css'; // built-in MDX component styles
|
|
273
275
|
```
|
|
274
276
|
|
|
277
|
+
Built-in MDX components currently include `Callout`, `Note`, `CodeDemo`, `Steps`, `Tabs`, `FileTree`, and `Kbd`.
|
|
278
|
+
|
|
279
|
+
Use `Note` for supplemental explanation, editor notes, and neutral guidance. Keep `Callout` for stronger feedback semantics such as `info`, `warn`, `error`, or `success`.
|
|
280
|
+
|
|
281
|
+
| Component | Use for | Example |
|
|
282
|
+
|---|---|---|
|
|
283
|
+
| `Callout` | Strong feedback blocks with explicit severity | `<Callout type="warn">Read this first.</Callout>` |
|
|
284
|
+
| `Note` | Neutral explanation, editor notes, low-emphasis guidance | `<Note title="Editor note">Background context.</Note>` |
|
|
285
|
+
| `CodeDemo` | Code sample + optional title wrapper | `<CodeDemo title="demo" code={"const x = 1;"} />` |
|
|
286
|
+
| `Steps` + `Step` | Ordered task or tutorial flows | `<Steps><Step title="Install">...</Step></Steps>` |
|
|
287
|
+
| `Tabs` + `Tab` | Small tabbed content groups | `<Tabs><Tab label="React">...</Tab></Tabs>` |
|
|
288
|
+
| `FileTree` | File/folder structure snippets | `<FileTree>{"src/\\n app.ts"}</FileTree>` |
|
|
289
|
+
| `Kbd` | Keyboard keycaps in inline prose | `Press <Kbd>Cmd</Kbd> + <Kbd>K</Kbd>` |
|
|
290
|
+
|
|
291
|
+
Complete example matrix:
|
|
292
|
+
|
|
293
|
+
```mdx
|
|
294
|
+
<Note title="Editor note">
|
|
295
|
+
This paragraph is background context, not a warning or status message.
|
|
296
|
+
</Note>
|
|
297
|
+
|
|
298
|
+
<Callout type="info">
|
|
299
|
+
MDX components ship in the default registry.
|
|
300
|
+
</Callout>
|
|
301
|
+
|
|
302
|
+
<CodeDemo title="Minimal example" code={`const x = 1;`} />
|
|
303
|
+
|
|
304
|
+
<Steps>
|
|
305
|
+
<Step title="Install">Add the package.</Step>
|
|
306
|
+
<Step title="Render">Mount the preview.</Step>
|
|
307
|
+
</Steps>
|
|
308
|
+
|
|
309
|
+
<Tabs>
|
|
310
|
+
<Tab label="React">Use the React bindings.</Tab>
|
|
311
|
+
<Tab label="Core">Use the framework-agnostic core.</Tab>
|
|
312
|
+
</Tabs>
|
|
313
|
+
|
|
314
|
+
<FileTree>
|
|
315
|
+
{`src/
|
|
316
|
+
app.tsx
|
|
317
|
+
routes/
|
|
318
|
+
mdx-preview.tsx`}
|
|
319
|
+
</FileTree>
|
|
320
|
+
|
|
321
|
+
Press <Kbd>Cmd</Kbd> + <Kbd>K</Kbd>.
|
|
322
|
+
```
|
|
323
|
+
|
|
275
324
|
### Selective imports
|
|
276
325
|
|
|
277
326
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,8 @@ import { IndentMode, OwoMarkSelection, OwoMarkCommands, OwoMarkCore, OwoMarkShar
|
|
|
4
4
|
export { BlockContext, BlockContextType, BlockInsertType, CommandDefinition, OwoMarkCommands, OwoMarkCore, OwoMarkEditorInstance, OwoMarkSelection, OwoMarkSharedState, OwoMarkSharedStateController, OwoMarkSharedStateStore, PreviewBlock, PreviewBlockKind, SlashState } from '@owomark/core';
|
|
5
5
|
import { OwoMarkThemeName, PreviewStrategy, PreviewRendererRegistry, PreviewRenderContext } from '@owomark/view';
|
|
6
6
|
export { OwoMarkThemeName, PreviewRenderContext, PreviewRenderResult, PreviewRendererDefinition, PreviewRendererRegistry, THEME_DARK_CLASS, THEME_LIGHT_CLASS, getThemeClassName } from '@owomark/view';
|
|
7
|
-
import { OwoMarkProcessorOptions } from '@owomark/processor';
|
|
7
|
+
import { OwoMarkProcessorOptions, PluginDescriptor, PluginEntry, MdxComponentMap } from '@owomark/processor';
|
|
8
|
+
export { registerPlugin } from '@owomark/processor';
|
|
8
9
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
9
10
|
|
|
10
11
|
type OwoMarkEditorConfig = {
|
|
@@ -57,6 +58,18 @@ type OwoMarkEditorProps = {
|
|
|
57
58
|
};
|
|
58
59
|
declare const OwoMarkEditor: react.ForwardRefExoticComponent<OwoMarkEditorProps & react.RefAttributes<HTMLDivElement>>;
|
|
59
60
|
|
|
61
|
+
type OwoMarkMdxOptions = {
|
|
62
|
+
enableMath?: boolean;
|
|
63
|
+
enableSideAnnotation?: boolean;
|
|
64
|
+
enableCodeHighlight?: boolean;
|
|
65
|
+
sourceAnchors?: boolean;
|
|
66
|
+
extraRemarkDescriptors?: PluginDescriptor[];
|
|
67
|
+
extraRehypeDescriptors?: PluginDescriptor[];
|
|
68
|
+
extraRemarkPlugins?: PluginEntry[];
|
|
69
|
+
extraRehypePlugins?: PluginEntry[];
|
|
70
|
+
components?: MdxComponentMap;
|
|
71
|
+
};
|
|
72
|
+
|
|
60
73
|
type OwoMarkPreviewProps = {
|
|
61
74
|
state: OwoMarkSharedStateStore;
|
|
62
75
|
className?: string;
|
|
@@ -75,6 +88,8 @@ type OwoMarkPreviewProps = {
|
|
|
75
88
|
* the latest reference is always used via a stable ref.
|
|
76
89
|
*/
|
|
77
90
|
renderBlock?: (block: PreviewBlock, context: PreviewRenderContext) => Promise<string>;
|
|
91
|
+
/** MDX runtime configuration used by `strategy="mdx"`. */
|
|
92
|
+
mdx?: OwoMarkMdxOptions;
|
|
78
93
|
/** Called after each successful DOM update. Use to trigger scroll sync. */
|
|
79
94
|
onContentUpdate?: () => void;
|
|
80
95
|
};
|
|
@@ -211,38 +226,28 @@ declare function computeMenuPosition(caret: CaretRect, menuHeight: number, menuW
|
|
|
211
226
|
};
|
|
212
227
|
|
|
213
228
|
type MdxSkeletonProps = {
|
|
214
|
-
/** Height in pixels for the skeleton placeholder. */
|
|
215
229
|
height?: number;
|
|
216
|
-
/** Number of shimmer lines to show. Default: 3. */
|
|
217
230
|
lines?: number;
|
|
218
231
|
className?: string;
|
|
219
232
|
style?: CSSProperties;
|
|
220
233
|
};
|
|
221
|
-
/**
|
|
222
|
-
* Lightweight skeleton loading indicator for MDX component placeholders.
|
|
223
|
-
* Pure CSS animation — no external UI library dependency.
|
|
224
|
-
*/
|
|
225
234
|
declare function MdxSkeleton({ height, lines, className, style }: MdxSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
226
235
|
|
|
227
236
|
type MdxComponentShellProps = {
|
|
228
|
-
/** Component display name, used as cache key for height estimation. */
|
|
229
237
|
name: string;
|
|
238
|
+
propsFingerprint?: string;
|
|
230
239
|
children: ReactNode;
|
|
231
240
|
};
|
|
232
|
-
|
|
233
|
-
* Wraps an MDX component to provide:
|
|
234
|
-
* 1. Skeleton placeholder with estimated height before first paint
|
|
235
|
-
* 2. Real-height measurement after mount via ResizeObserver
|
|
236
|
-
* 3. Height caching so subsequent renders of the same component type
|
|
237
|
-
* use a better estimate, reducing layout shift.
|
|
238
|
-
*/
|
|
239
|
-
declare function MdxComponentShell({ name, children }: MdxComponentShellProps): react_jsx_runtime.JSX.Element;
|
|
240
|
-
/**
|
|
241
|
-
* Create a wrapped version of an MDX component that renders inside
|
|
242
|
-
* MdxComponentShell for skeleton loading + height management.
|
|
243
|
-
*/
|
|
241
|
+
declare function MdxComponentShell({ name, propsFingerprint, children }: MdxComponentShellProps): react_jsx_runtime.JSX.Element;
|
|
244
242
|
declare function wrapWithShell<P extends Record<string, any>>(name: string, Component: ComponentType<P>): ComponentType<P>;
|
|
245
243
|
/** Clear the height cache (useful for testing or theme changes). */
|
|
246
244
|
declare function clearComponentHeightCache(): void;
|
|
247
245
|
|
|
248
|
-
|
|
246
|
+
type CancellableCompile = {
|
|
247
|
+
promise: Promise<string>;
|
|
248
|
+
cancel: () => void;
|
|
249
|
+
};
|
|
250
|
+
declare function acquireMdxWorker(): void;
|
|
251
|
+
declare function releaseMdxWorker(): void;
|
|
252
|
+
|
|
253
|
+
export { type CancellableCompile, type CaretRect, DEFAULT_EDITOR_CONFIG, EditorBlock, type EditorBlockProps, EditorDecorator, type EditorDecoratorProps, EditorLeaf, type EditorLeafProps, MdxComponentShell, type MdxComponentShellProps, MdxSkeleton, type MdxSkeletonProps, OwoMarkEditor, type OwoMarkEditorConfig, type OwoMarkEditorProps, type OwoMarkMdxOptions, OwoMarkPreview, type OwoMarkPreviewProps, SlashMenu, type SlashMenuProps, type UseOwoMarkCoreOptions, type UseOwoMarkCoreReturn, type UseOwoMarkSharedStateOptions, type UseVirtualListOptions, type UseVirtualListResult, acquireMdxWorker, clearComponentHeightCache, computeMenuPosition, deriveProcessorOptions, getCaretRect, releaseMdxWorker, resolveEditorConfig, useBlockContext, useOwoMarkCore, useOwoMarkSharedState, useSharedStateSnapshot, useVirtualList, wrapWithShell };
|
package/dist/index.js
CHANGED
|
@@ -588,11 +588,754 @@ var OwoMarkEditor = forwardRef(
|
|
|
588
588
|
);
|
|
589
589
|
|
|
590
590
|
// src/OwoMarkPreview.tsx
|
|
591
|
-
import { useRef as
|
|
591
|
+
import { useRef as useRef8, useEffect as useEffect6 } from "react";
|
|
592
592
|
import {
|
|
593
593
|
createOwoMarkPreviewEngine
|
|
594
594
|
} from "@owomark/view";
|
|
595
|
+
|
|
596
|
+
// src/MdxPreview.tsx
|
|
597
|
+
import {
|
|
598
|
+
Component,
|
|
599
|
+
useEffect as useEffect5,
|
|
600
|
+
useMemo as useMemo4,
|
|
601
|
+
useRef as useRef7,
|
|
602
|
+
useState as useState5,
|
|
603
|
+
useSyncExternalStore
|
|
604
|
+
} from "react";
|
|
605
|
+
import {
|
|
606
|
+
DEFAULT_MDX_COMPONENTS
|
|
607
|
+
} from "@owomark/processor";
|
|
608
|
+
|
|
609
|
+
// src/MdxSkeleton.tsx
|
|
610
|
+
import { useMemo as useMemo2, useRef as useRef4 } from "react";
|
|
611
|
+
import { createSkeletonHtml, ensureSkeletonStyles } from "@owomark/view";
|
|
595
612
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
613
|
+
function MdxSkeleton({ height, lines, className, style }) {
|
|
614
|
+
const injected = useRef4(false);
|
|
615
|
+
if (!injected.current && typeof document !== "undefined") {
|
|
616
|
+
ensureSkeletonStyles(document);
|
|
617
|
+
injected.current = true;
|
|
618
|
+
}
|
|
619
|
+
const html = useMemo2(
|
|
620
|
+
() => createSkeletonHtml({ height, lines: lines ?? (height == null ? 3 : void 0) }),
|
|
621
|
+
[height, lines]
|
|
622
|
+
);
|
|
623
|
+
return /* @__PURE__ */ jsx6(
|
|
624
|
+
"div",
|
|
625
|
+
{
|
|
626
|
+
className: className ?? void 0,
|
|
627
|
+
style,
|
|
628
|
+
dangerouslySetInnerHTML: { __html: html }
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// src/MdxComponentShell.tsx
|
|
634
|
+
import {
|
|
635
|
+
useRef as useRef5,
|
|
636
|
+
useState as useState3,
|
|
637
|
+
useEffect as useEffect3,
|
|
638
|
+
useLayoutEffect as useLayoutEffect3,
|
|
639
|
+
useCallback as useCallback2
|
|
640
|
+
} from "react";
|
|
641
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
642
|
+
var componentHeightCache = /* @__PURE__ */ new Map();
|
|
643
|
+
var DEFAULT_ESTIMATED_HEIGHT = 80;
|
|
644
|
+
function shallowPropsFingerprint(props) {
|
|
645
|
+
const keys = Object.keys(props).sort();
|
|
646
|
+
const parts = [];
|
|
647
|
+
for (const key of keys) {
|
|
648
|
+
const val = props[key];
|
|
649
|
+
if (typeof val === "function" || typeof val === "object") continue;
|
|
650
|
+
parts.push(`${key}=${String(val)}`);
|
|
651
|
+
}
|
|
652
|
+
return parts.join("&");
|
|
653
|
+
}
|
|
654
|
+
function MdxComponentShell({ name, propsFingerprint, children }) {
|
|
655
|
+
const containerRef = useRef5(null);
|
|
656
|
+
const [status, setStatus] = useState3("skeleton");
|
|
657
|
+
const cacheKey = propsFingerprint ? `${name}:${propsFingerprint}` : name;
|
|
658
|
+
const estimatedHeight = componentHeightCache.get(cacheKey) ?? DEFAULT_ESTIMATED_HEIGHT;
|
|
659
|
+
useEffect3(() => {
|
|
660
|
+
const id = requestAnimationFrame(() => setStatus("mounting"));
|
|
661
|
+
return () => cancelAnimationFrame(id);
|
|
662
|
+
}, []);
|
|
663
|
+
useLayoutEffect3(() => {
|
|
664
|
+
if (status !== "mounting") return;
|
|
665
|
+
const id = requestAnimationFrame(() => setStatus("ready"));
|
|
666
|
+
return () => cancelAnimationFrame(id);
|
|
667
|
+
}, [status]);
|
|
668
|
+
const measureHeight = useCallback2(() => {
|
|
669
|
+
const el = containerRef.current;
|
|
670
|
+
if (!el) return;
|
|
671
|
+
const h = el.getBoundingClientRect().height;
|
|
672
|
+
if (h > 0) {
|
|
673
|
+
componentHeightCache.set(cacheKey, h);
|
|
674
|
+
}
|
|
675
|
+
}, [cacheKey]);
|
|
676
|
+
useEffect3(() => {
|
|
677
|
+
const el = containerRef.current;
|
|
678
|
+
if (!el || status !== "ready") return;
|
|
679
|
+
measureHeight();
|
|
680
|
+
const ro = new ResizeObserver(() => measureHeight());
|
|
681
|
+
ro.observe(el);
|
|
682
|
+
return () => ro.disconnect();
|
|
683
|
+
}, [status, measureHeight]);
|
|
684
|
+
if (status === "skeleton") {
|
|
685
|
+
return /* @__PURE__ */ jsx7(MdxSkeleton, { height: estimatedHeight });
|
|
686
|
+
}
|
|
687
|
+
return /* @__PURE__ */ jsx7("div", { ref: containerRef, children });
|
|
688
|
+
}
|
|
689
|
+
function wrapWithShell(name, Component2) {
|
|
690
|
+
function ShellWrapped(props) {
|
|
691
|
+
const fingerprint = shallowPropsFingerprint(props);
|
|
692
|
+
return /* @__PURE__ */ jsx7(MdxComponentShell, { name, propsFingerprint: fingerprint, children: /* @__PURE__ */ jsx7(Component2, { ...props }) });
|
|
693
|
+
}
|
|
694
|
+
ShellWrapped.displayName = `MdxShell(${name})`;
|
|
695
|
+
return ShellWrapped;
|
|
696
|
+
}
|
|
697
|
+
function clearComponentHeightCache() {
|
|
698
|
+
componentHeightCache.clear();
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// src/mdx-error.ts
|
|
702
|
+
function parseMdxErrorDetails(error) {
|
|
703
|
+
if (error && typeof error === "object") {
|
|
704
|
+
const value = error;
|
|
705
|
+
if (typeof value.line === "number") {
|
|
706
|
+
return {
|
|
707
|
+
message: value.message ?? String(error),
|
|
708
|
+
line: value.line,
|
|
709
|
+
column: typeof value.column === "number" ? value.column : void 0
|
|
710
|
+
};
|
|
711
|
+
}
|
|
712
|
+
const text = value.message ?? String(error);
|
|
713
|
+
const match = text.match(/\((\d+):(\d+)/);
|
|
714
|
+
if (match) {
|
|
715
|
+
return {
|
|
716
|
+
message: text,
|
|
717
|
+
line: Number(match[1]),
|
|
718
|
+
column: Number(match[2])
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
return { message: text };
|
|
722
|
+
}
|
|
723
|
+
return { message: String(error) };
|
|
724
|
+
}
|
|
725
|
+
function parseCompileError(error, kind) {
|
|
726
|
+
return {
|
|
727
|
+
...parseMdxErrorDetails(error),
|
|
728
|
+
kind
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
// src/useMdxPreviewCompilation.ts
|
|
733
|
+
import { useEffect as useEffect4, useMemo as useMemo3, useRef as useRef6, useState as useState4 } from "react";
|
|
734
|
+
import { deriveRenderKey } from "@owomark/core";
|
|
735
|
+
|
|
736
|
+
// src/mdx-runtime.ts
|
|
737
|
+
import { compile, run } from "@mdx-js/mdx";
|
|
738
|
+
import * as jsxRuntime from "react/jsx-runtime";
|
|
739
|
+
import {
|
|
740
|
+
getOwoMarkPlugins,
|
|
741
|
+
allBuiltinDescriptors,
|
|
742
|
+
inspectMdxSource,
|
|
743
|
+
remapMdxErrorDetails
|
|
744
|
+
} from "@owomark/processor";
|
|
745
|
+
var workerInstance = null;
|
|
746
|
+
var workerRefCount = 0;
|
|
747
|
+
var requestCounter = 0;
|
|
748
|
+
var MAX_CRASHES = 3;
|
|
749
|
+
var CRASH_COOLDOWN_MS = 5e3;
|
|
750
|
+
var CRASH_WINDOW_MS = 3e4;
|
|
751
|
+
var permanentlyFailed = false;
|
|
752
|
+
var crashTimestamps = [];
|
|
753
|
+
var pendingRequests = /* @__PURE__ */ new Map();
|
|
754
|
+
function recordCrash() {
|
|
755
|
+
const now = Date.now();
|
|
756
|
+
crashTimestamps.push(now);
|
|
757
|
+
while (crashTimestamps.length > 0 && now - crashTimestamps[0] > CRASH_WINDOW_MS) {
|
|
758
|
+
crashTimestamps.shift();
|
|
759
|
+
}
|
|
760
|
+
if (crashTimestamps.length >= MAX_CRASHES) {
|
|
761
|
+
permanentlyFailed = true;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
function canCreateWorker() {
|
|
765
|
+
if (permanentlyFailed) return false;
|
|
766
|
+
if (crashTimestamps.length === 0) return true;
|
|
767
|
+
return Date.now() - crashTimestamps[crashTimestamps.length - 1] >= CRASH_COOLDOWN_MS;
|
|
768
|
+
}
|
|
769
|
+
function tryCreateWorker() {
|
|
770
|
+
if (workerInstance) return workerInstance;
|
|
771
|
+
if (!canCreateWorker()) return null;
|
|
772
|
+
try {
|
|
773
|
+
if (typeof Worker === "undefined") {
|
|
774
|
+
permanentlyFailed = true;
|
|
775
|
+
return null;
|
|
776
|
+
}
|
|
777
|
+
const worker = new Worker(
|
|
778
|
+
new URL("./mdx.worker.js", import.meta.url),
|
|
779
|
+
{ type: "module" }
|
|
780
|
+
);
|
|
781
|
+
worker.onmessage = (e) => {
|
|
782
|
+
const response = e.data;
|
|
783
|
+
const pending = pendingRequests.get(response.id);
|
|
784
|
+
if (!pending) return;
|
|
785
|
+
pendingRequests.delete(response.id);
|
|
786
|
+
if (response.ok) {
|
|
787
|
+
pending.resolve(response.code);
|
|
788
|
+
} else {
|
|
789
|
+
pending.reject({ ...response.error, kind: "compile" });
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
worker.onerror = () => {
|
|
793
|
+
recordCrash();
|
|
794
|
+
worker.terminate();
|
|
795
|
+
workerInstance = null;
|
|
796
|
+
for (const [id, pending] of pendingRequests) {
|
|
797
|
+
pendingRequests.delete(id);
|
|
798
|
+
pending.reject({ message: "MDX compile worker crashed", kind: "compile" });
|
|
799
|
+
}
|
|
800
|
+
};
|
|
801
|
+
workerInstance = worker;
|
|
802
|
+
return worker;
|
|
803
|
+
} catch {
|
|
804
|
+
recordCrash();
|
|
805
|
+
return null;
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
function acquireMdxWorker() {
|
|
809
|
+
workerRefCount++;
|
|
810
|
+
}
|
|
811
|
+
function releaseMdxWorker() {
|
|
812
|
+
if (--workerRefCount <= 0) {
|
|
813
|
+
workerRefCount = 0;
|
|
814
|
+
if (workerInstance) {
|
|
815
|
+
workerInstance.terminate();
|
|
816
|
+
workerInstance = null;
|
|
817
|
+
}
|
|
818
|
+
for (const [, pending] of pendingRequests) {
|
|
819
|
+
pending.reject({ message: "Worker released", kind: "compile" });
|
|
820
|
+
}
|
|
821
|
+
pendingRequests.clear();
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
function compileInWorker(markdown, options, inspection) {
|
|
825
|
+
const maybeWorker = tryCreateWorker();
|
|
826
|
+
if (!maybeWorker) {
|
|
827
|
+
return {
|
|
828
|
+
promise: Promise.reject(new Error("Worker unavailable")),
|
|
829
|
+
cancel: () => {
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
}
|
|
833
|
+
const workerRef = maybeWorker;
|
|
834
|
+
const id = ++requestCounter;
|
|
835
|
+
let cancelled = false;
|
|
836
|
+
const promise = new Promise((resolve, reject) => {
|
|
837
|
+
pendingRequests.set(id, { resolve, reject });
|
|
838
|
+
workerRef.postMessage({
|
|
839
|
+
type: "compile",
|
|
840
|
+
id,
|
|
841
|
+
markdown,
|
|
842
|
+
options: {
|
|
843
|
+
enableMath: options.enableMath,
|
|
844
|
+
enableSideAnnotation: options.enableSideAnnotation,
|
|
845
|
+
enableCodeHighlight: options.enableCodeHighlight,
|
|
846
|
+
sourceAnchors: options.sourceAnchors,
|
|
847
|
+
extraRemarkDescriptors: options.extraRemarkDescriptors,
|
|
848
|
+
extraRehypeDescriptors: options.extraRehypeDescriptors,
|
|
849
|
+
preparedSource: inspection?.compileSource,
|
|
850
|
+
sourceMap: inspection?.sourceMap
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
});
|
|
854
|
+
function cancel() {
|
|
855
|
+
if (cancelled) return;
|
|
856
|
+
cancelled = true;
|
|
857
|
+
const pending = pendingRequests.get(id);
|
|
858
|
+
if (pending) {
|
|
859
|
+
pendingRequests.delete(id);
|
|
860
|
+
pending.reject({ message: "Compilation cancelled", kind: "compile" });
|
|
861
|
+
}
|
|
862
|
+
workerRef.postMessage({ type: "cancel", id });
|
|
863
|
+
}
|
|
864
|
+
return { promise, cancel };
|
|
865
|
+
}
|
|
866
|
+
async function compileOnMainThread(markdown, options, inspection) {
|
|
867
|
+
const resolvedInspection = inspection ?? inspectMdxSource(markdown, {
|
|
868
|
+
enableMath: options.enableMath,
|
|
869
|
+
enableSideAnnotation: options.enableSideAnnotation,
|
|
870
|
+
extraRemarkDescriptors: options.extraRemarkDescriptors,
|
|
871
|
+
extraRemarkPlugins: options.extraRemarkPlugins
|
|
872
|
+
});
|
|
873
|
+
const { remarkPlugins, rehypePlugins } = getOwoMarkPlugins({
|
|
874
|
+
mode: "production",
|
|
875
|
+
enableMath: options.enableMath,
|
|
876
|
+
enableSideAnnotation: options.enableSideAnnotation,
|
|
877
|
+
enableCodeHighlight: options.enableCodeHighlight,
|
|
878
|
+
sourceAnchors: options.sourceAnchors,
|
|
879
|
+
extraRemarkDescriptors: options.extraRemarkDescriptors,
|
|
880
|
+
extraRehypeDescriptors: options.extraRehypeDescriptors,
|
|
881
|
+
extraRemarkPlugins: options.extraRemarkPlugins,
|
|
882
|
+
extraRehypePlugins: options.extraRehypePlugins,
|
|
883
|
+
mdxSourceMap: resolvedInspection.sourceMap
|
|
884
|
+
});
|
|
885
|
+
try {
|
|
886
|
+
const result = await compile(resolvedInspection.compileSource, {
|
|
887
|
+
outputFormat: "function-body",
|
|
888
|
+
remarkPlugins,
|
|
889
|
+
rehypePlugins
|
|
890
|
+
});
|
|
891
|
+
return String(result);
|
|
892
|
+
} catch (error) {
|
|
893
|
+
throw remapMdxErrorDetails(error, resolvedInspection.sourceMap);
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
function requiresMainThread(options) {
|
|
897
|
+
if (options.extraRemarkPlugins?.length || options.extraRehypePlugins?.length) return true;
|
|
898
|
+
if (options.extraRemarkDescriptors?.length && !allBuiltinDescriptors(options.extraRemarkDescriptors)) return true;
|
|
899
|
+
if (options.extraRehypeDescriptors?.length && !allBuiltinDescriptors(options.extraRehypeDescriptors)) return true;
|
|
900
|
+
return false;
|
|
901
|
+
}
|
|
902
|
+
function compileMdx(markdown, options, inspection) {
|
|
903
|
+
if (requiresMainThread(options)) {
|
|
904
|
+
return {
|
|
905
|
+
promise: compileOnMainThread(markdown, options, inspection),
|
|
906
|
+
cancel: () => {
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
const workerCompile = compileInWorker(markdown, options, inspection);
|
|
911
|
+
let settled = false;
|
|
912
|
+
const promise = workerCompile.promise.catch(() => {
|
|
913
|
+
if (settled) throw new Error("Compilation cancelled");
|
|
914
|
+
return compileOnMainThread(markdown, options, inspection);
|
|
915
|
+
});
|
|
916
|
+
return {
|
|
917
|
+
promise,
|
|
918
|
+
cancel: () => {
|
|
919
|
+
settled = true;
|
|
920
|
+
workerCompile.cancel();
|
|
921
|
+
}
|
|
922
|
+
};
|
|
923
|
+
}
|
|
924
|
+
async function runMdxCode(code) {
|
|
925
|
+
const module = await run(code, {
|
|
926
|
+
...jsxRuntime,
|
|
927
|
+
baseUrl: import.meta.url
|
|
928
|
+
});
|
|
929
|
+
return {
|
|
930
|
+
Content: module.default
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// src/mdx-preview-utils.tsx
|
|
935
|
+
import { renderBlockDefault } from "@owomark/view";
|
|
936
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
937
|
+
var objectIdentityMap = /* @__PURE__ */ new WeakMap();
|
|
938
|
+
var nextObjectIdentity = 1;
|
|
939
|
+
function getObjectIdentity(value) {
|
|
940
|
+
if (!value) return "0";
|
|
941
|
+
const existing = objectIdentityMap.get(value);
|
|
942
|
+
if (existing) return String(existing);
|
|
943
|
+
const id = nextObjectIdentity++;
|
|
944
|
+
objectIdentityMap.set(value, id);
|
|
945
|
+
return String(id);
|
|
946
|
+
}
|
|
947
|
+
function buildRuntimeComponents(mdxAnalysis, baseComponents) {
|
|
948
|
+
const components = { ...baseComponents };
|
|
949
|
+
function registerMissingComponentPath(componentName) {
|
|
950
|
+
const parts = componentName.split(".");
|
|
951
|
+
let cursor = components;
|
|
952
|
+
for (let index = 0; index < parts.length; index += 1) {
|
|
953
|
+
const part = parts[index];
|
|
954
|
+
const isLeaf = index === parts.length - 1;
|
|
955
|
+
const existing = cursor[part];
|
|
956
|
+
if (isLeaf) {
|
|
957
|
+
if (existing === void 0) {
|
|
958
|
+
cursor[part] = function MissingComponent(props) {
|
|
959
|
+
const { children, ...restProps } = props;
|
|
960
|
+
return /* @__PURE__ */ jsx8("div", { "data-mdx-missing": componentName, ...restProps, children });
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
if (existing == null) {
|
|
966
|
+
const nested = {};
|
|
967
|
+
cursor[part] = nested;
|
|
968
|
+
cursor = nested;
|
|
969
|
+
continue;
|
|
970
|
+
}
|
|
971
|
+
if (typeof existing === "function") {
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
cursor = existing;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
for (const name of mdxAnalysis.componentNames) {
|
|
978
|
+
registerMissingComponentPath(name);
|
|
979
|
+
}
|
|
980
|
+
return components;
|
|
981
|
+
}
|
|
982
|
+
async function renderMarkdownBlocksCached(blocks, themeKey, cache, renderBlock) {
|
|
983
|
+
const nextCache = /* @__PURE__ */ new Map();
|
|
984
|
+
const results = await Promise.all(blocks.map(async (block) => {
|
|
985
|
+
const cached = cache.get(block.renderKey);
|
|
986
|
+
if (cached !== void 0) {
|
|
987
|
+
nextCache.set(block.renderKey, cached);
|
|
988
|
+
return { blockId: block.blockId, html: cached };
|
|
989
|
+
}
|
|
990
|
+
const context = {
|
|
991
|
+
version: 0,
|
|
992
|
+
themeKey,
|
|
993
|
+
sourceLineOffset: block.startLine - 1
|
|
994
|
+
};
|
|
995
|
+
const html = renderBlock ? await renderBlock(block, context) : await renderBlockDefault(block);
|
|
996
|
+
nextCache.set(block.renderKey, html);
|
|
997
|
+
return { blockId: block.blockId, html };
|
|
998
|
+
}));
|
|
999
|
+
cache.clear();
|
|
1000
|
+
for (const [k, v] of nextCache) cache.set(k, v);
|
|
1001
|
+
return results;
|
|
1002
|
+
}
|
|
1003
|
+
|
|
1004
|
+
// src/useMdxPreviewCompilation.ts
|
|
1005
|
+
import { inspectMdxSource as inspectMdxSource2 } from "@owomark/processor";
|
|
1006
|
+
function useMdxPreviewCompilation({
|
|
1007
|
+
snapshot,
|
|
1008
|
+
themeKey,
|
|
1009
|
+
renderBlock,
|
|
1010
|
+
mdx,
|
|
1011
|
+
wrappedComponents
|
|
1012
|
+
}) {
|
|
1013
|
+
const requestIdRef = useRef6(0);
|
|
1014
|
+
const cancelRef = useRef6(null);
|
|
1015
|
+
const blockCacheRef = useRef6(/* @__PURE__ */ new Map());
|
|
1016
|
+
const [mdxDisplay, setMdxDisplay] = useState4({
|
|
1017
|
+
code: null,
|
|
1018
|
+
Content: null,
|
|
1019
|
+
runtimeComponents: null,
|
|
1020
|
+
compileKey: null,
|
|
1021
|
+
renderKey: null,
|
|
1022
|
+
pending: false,
|
|
1023
|
+
error: null
|
|
1024
|
+
});
|
|
1025
|
+
const [markdownHtml, setMarkdownHtml] = useState4(null);
|
|
1026
|
+
useEffect4(() => {
|
|
1027
|
+
acquireMdxWorker();
|
|
1028
|
+
return () => {
|
|
1029
|
+
cancelRef.current?.();
|
|
1030
|
+
cancelRef.current = null;
|
|
1031
|
+
releaseMdxWorker();
|
|
1032
|
+
};
|
|
1033
|
+
}, []);
|
|
1034
|
+
const mdxInspection = useMemo3(
|
|
1035
|
+
() => inspectMdxSource2(snapshot.markdown, {
|
|
1036
|
+
enableMath: mdx?.enableMath,
|
|
1037
|
+
enableSideAnnotation: mdx?.enableSideAnnotation,
|
|
1038
|
+
extraRemarkDescriptors: mdx?.extraRemarkDescriptors,
|
|
1039
|
+
extraRemarkPlugins: mdx?.extraRemarkPlugins
|
|
1040
|
+
}),
|
|
1041
|
+
[
|
|
1042
|
+
mdx?.enableMath,
|
|
1043
|
+
mdx?.enableSideAnnotation,
|
|
1044
|
+
mdx?.extraRemarkDescriptors,
|
|
1045
|
+
mdx?.extraRemarkPlugins,
|
|
1046
|
+
snapshot.markdown
|
|
1047
|
+
]
|
|
1048
|
+
);
|
|
1049
|
+
const hasMdx = mdxInspection.hasMdxSyntax;
|
|
1050
|
+
const optionsFingerprint = useMemo3(() => {
|
|
1051
|
+
const b = (v) => v === true ? "1" : v === false ? "0" : "_";
|
|
1052
|
+
const ds = (arr) => arr?.length ? arr.map((d) => d.options ? `${d.name}(${JSON.stringify(d.options)})` : d.name).join(",") : "";
|
|
1053
|
+
return [
|
|
1054
|
+
b(mdx?.enableMath),
|
|
1055
|
+
b(mdx?.enableSideAnnotation),
|
|
1056
|
+
b(mdx?.enableCodeHighlight),
|
|
1057
|
+
b(mdx?.sourceAnchors),
|
|
1058
|
+
ds(mdx?.extraRemarkDescriptors),
|
|
1059
|
+
ds(mdx?.extraRehypeDescriptors),
|
|
1060
|
+
`rp${getObjectIdentity(mdx?.extraRemarkPlugins)}`,
|
|
1061
|
+
`hp${getObjectIdentity(mdx?.extraRehypePlugins)}`
|
|
1062
|
+
].join("|");
|
|
1063
|
+
}, [
|
|
1064
|
+
mdx?.enableMath,
|
|
1065
|
+
mdx?.enableSideAnnotation,
|
|
1066
|
+
mdx?.enableCodeHighlight,
|
|
1067
|
+
mdx?.sourceAnchors,
|
|
1068
|
+
mdx?.extraRemarkDescriptors,
|
|
1069
|
+
mdx?.extraRehypeDescriptors,
|
|
1070
|
+
mdx?.extraRemarkPlugins,
|
|
1071
|
+
mdx?.extraRehypePlugins
|
|
1072
|
+
]);
|
|
1073
|
+
const compileKey = useMemo3(
|
|
1074
|
+
() => deriveRenderKey(`${snapshot.markdown}:${optionsFingerprint}`, "custom", ""),
|
|
1075
|
+
[snapshot.markdown, optionsFingerprint]
|
|
1076
|
+
);
|
|
1077
|
+
const componentFingerprint = useMemo3(
|
|
1078
|
+
() => `cp${getObjectIdentity(mdx?.components)}`,
|
|
1079
|
+
[mdx?.components]
|
|
1080
|
+
);
|
|
1081
|
+
const renderKey = useMemo3(
|
|
1082
|
+
() => `${compileKey}:${componentFingerprint}`,
|
|
1083
|
+
[compileKey, componentFingerprint]
|
|
1084
|
+
);
|
|
1085
|
+
useEffect4(() => {
|
|
1086
|
+
if (!snapshot.markdown.trim()) {
|
|
1087
|
+
cancelRef.current?.();
|
|
1088
|
+
cancelRef.current = null;
|
|
1089
|
+
setMarkdownHtml(null);
|
|
1090
|
+
setMdxDisplay({
|
|
1091
|
+
code: null,
|
|
1092
|
+
Content: null,
|
|
1093
|
+
runtimeComponents: null,
|
|
1094
|
+
compileKey: null,
|
|
1095
|
+
renderKey: null,
|
|
1096
|
+
pending: false,
|
|
1097
|
+
error: null
|
|
1098
|
+
});
|
|
1099
|
+
return;
|
|
1100
|
+
}
|
|
1101
|
+
const requestId = ++requestIdRef.current;
|
|
1102
|
+
if (!hasMdx) {
|
|
1103
|
+
cancelRef.current?.();
|
|
1104
|
+
cancelRef.current = null;
|
|
1105
|
+
void renderMarkdownBlocksCached(snapshot.previewBlocks, themeKey, blockCacheRef.current, renderBlock).then((blocks) => {
|
|
1106
|
+
if (requestIdRef.current !== requestId) return;
|
|
1107
|
+
setMarkdownHtml(blocks);
|
|
1108
|
+
setMdxDisplay({
|
|
1109
|
+
code: null,
|
|
1110
|
+
Content: null,
|
|
1111
|
+
runtimeComponents: null,
|
|
1112
|
+
compileKey: null,
|
|
1113
|
+
renderKey: null,
|
|
1114
|
+
pending: false,
|
|
1115
|
+
error: null
|
|
1116
|
+
});
|
|
1117
|
+
});
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
1120
|
+
if (mdxDisplay.compileKey === compileKey && mdxDisplay.code) {
|
|
1121
|
+
if (mdxDisplay.renderKey !== renderKey) {
|
|
1122
|
+
const rerunId = ++requestIdRef.current;
|
|
1123
|
+
const cachedCode = mdxDisplay.code;
|
|
1124
|
+
setMdxDisplay((prev) => ({ ...prev, pending: true, error: null }));
|
|
1125
|
+
void (async () => {
|
|
1126
|
+
try {
|
|
1127
|
+
const { Content } = await runMdxCode(cachedCode);
|
|
1128
|
+
if (requestIdRef.current !== rerunId) return;
|
|
1129
|
+
setMdxDisplay((prev) => {
|
|
1130
|
+
if (prev.compileKey !== compileKey || prev.code !== cachedCode) return prev;
|
|
1131
|
+
return {
|
|
1132
|
+
...prev,
|
|
1133
|
+
Content,
|
|
1134
|
+
runtimeComponents: buildRuntimeComponents(mdxInspection, wrappedComponents),
|
|
1135
|
+
renderKey,
|
|
1136
|
+
pending: false,
|
|
1137
|
+
error: null
|
|
1138
|
+
};
|
|
1139
|
+
});
|
|
1140
|
+
} catch (error) {
|
|
1141
|
+
if (requestIdRef.current !== rerunId) return;
|
|
1142
|
+
setMdxDisplay((prev) => ({
|
|
1143
|
+
...prev,
|
|
1144
|
+
pending: false,
|
|
1145
|
+
error: parseCompileError(error, "runtime")
|
|
1146
|
+
}));
|
|
1147
|
+
}
|
|
1148
|
+
})();
|
|
1149
|
+
}
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
setMdxDisplay((prev) => ({ ...prev, pending: true, error: null }));
|
|
1153
|
+
setMarkdownHtml(null);
|
|
1154
|
+
cancelRef.current?.();
|
|
1155
|
+
cancelRef.current = null;
|
|
1156
|
+
const timer = setTimeout(() => {
|
|
1157
|
+
const { promise, cancel } = compileMdx(snapshot.markdown, {
|
|
1158
|
+
enableMath: mdx?.enableMath,
|
|
1159
|
+
enableSideAnnotation: mdx?.enableSideAnnotation,
|
|
1160
|
+
enableCodeHighlight: mdx?.enableCodeHighlight,
|
|
1161
|
+
sourceAnchors: mdx?.sourceAnchors,
|
|
1162
|
+
extraRemarkDescriptors: mdx?.extraRemarkDescriptors,
|
|
1163
|
+
extraRehypeDescriptors: mdx?.extraRehypeDescriptors,
|
|
1164
|
+
extraRemarkPlugins: mdx?.extraRemarkPlugins,
|
|
1165
|
+
extraRehypePlugins: mdx?.extraRehypePlugins
|
|
1166
|
+
}, mdxInspection);
|
|
1167
|
+
cancelRef.current = cancel;
|
|
1168
|
+
void (async () => {
|
|
1169
|
+
try {
|
|
1170
|
+
const code = await promise;
|
|
1171
|
+
if (requestIdRef.current !== requestId) return;
|
|
1172
|
+
const { Content } = await runMdxCode(code);
|
|
1173
|
+
if (requestIdRef.current !== requestId) return;
|
|
1174
|
+
setMdxDisplay({
|
|
1175
|
+
code,
|
|
1176
|
+
Content,
|
|
1177
|
+
runtimeComponents: buildRuntimeComponents(mdxInspection, wrappedComponents),
|
|
1178
|
+
compileKey,
|
|
1179
|
+
renderKey,
|
|
1180
|
+
pending: false,
|
|
1181
|
+
error: null
|
|
1182
|
+
});
|
|
1183
|
+
} catch (error) {
|
|
1184
|
+
if (requestIdRef.current !== requestId) return;
|
|
1185
|
+
setMdxDisplay((prev) => ({
|
|
1186
|
+
...prev,
|
|
1187
|
+
pending: false,
|
|
1188
|
+
error: parseCompileError(error, "compile")
|
|
1189
|
+
}));
|
|
1190
|
+
}
|
|
1191
|
+
})();
|
|
1192
|
+
}, 200);
|
|
1193
|
+
return () => {
|
|
1194
|
+
clearTimeout(timer);
|
|
1195
|
+
cancelRef.current?.();
|
|
1196
|
+
cancelRef.current = null;
|
|
1197
|
+
};
|
|
1198
|
+
}, [
|
|
1199
|
+
compileKey,
|
|
1200
|
+
hasMdx,
|
|
1201
|
+
mdx?.enableCodeHighlight,
|
|
1202
|
+
mdx?.enableMath,
|
|
1203
|
+
mdx?.enableSideAnnotation,
|
|
1204
|
+
mdx?.extraRehypeDescriptors,
|
|
1205
|
+
mdx?.extraRehypePlugins,
|
|
1206
|
+
mdx?.extraRemarkDescriptors,
|
|
1207
|
+
mdx?.extraRemarkPlugins,
|
|
1208
|
+
mdxInspection,
|
|
1209
|
+
mdx?.sourceAnchors,
|
|
1210
|
+
mdxDisplay.compileKey,
|
|
1211
|
+
mdxDisplay.Content,
|
|
1212
|
+
mdxDisplay.renderKey,
|
|
1213
|
+
renderBlock,
|
|
1214
|
+
renderKey,
|
|
1215
|
+
snapshot.markdown,
|
|
1216
|
+
snapshot.previewBlocks,
|
|
1217
|
+
themeKey,
|
|
1218
|
+
wrappedComponents
|
|
1219
|
+
]);
|
|
1220
|
+
return {
|
|
1221
|
+
hasMdx,
|
|
1222
|
+
markdownHtml,
|
|
1223
|
+
mdxDisplay
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
// src/MdxPreview.tsx
|
|
1228
|
+
import { jsx as jsx9, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1229
|
+
function locationText(error) {
|
|
1230
|
+
if (error.line == null) return null;
|
|
1231
|
+
if (error.column == null) return `\u884C ${error.line}`;
|
|
1232
|
+
return `\u884C ${error.line}:${error.column}`;
|
|
1233
|
+
}
|
|
1234
|
+
function ErrorNotice({ error }) {
|
|
1235
|
+
const location = locationText(error);
|
|
1236
|
+
const label = error.kind === "compile" ? "MDX Compile" : "MDX Runtime";
|
|
1237
|
+
return /* @__PURE__ */ jsx9("div", { className: "sticky top-0 z-10 mb-4 rounded-md border border-[var(--owo-cmp-danger-border)] bg-[var(--owo-cmp-danger-bg)] px-4 py-3 text-sm text-[var(--owo-cmp-danger-text)]", children: /* @__PURE__ */ jsxs3("div", { className: "flex items-start gap-2", children: [
|
|
1238
|
+
/* @__PURE__ */ jsx9("span", { className: "mt-0.5 shrink-0 font-mono text-[11px] font-bold uppercase", children: label }),
|
|
1239
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
1240
|
+
location && /* @__PURE__ */ jsx9("span", { className: "mr-2 rounded bg-[var(--owo-cmp-danger-border)] px-1.5 py-0.5 font-mono text-xs", children: location }),
|
|
1241
|
+
/* @__PURE__ */ jsx9("span", { className: "break-words", children: error.message })
|
|
1242
|
+
] })
|
|
1243
|
+
] }) });
|
|
1244
|
+
}
|
|
1245
|
+
var RuntimeErrorBoundary = class extends Component {
|
|
1246
|
+
state = { error: null };
|
|
1247
|
+
static getDerivedStateFromError(error) {
|
|
1248
|
+
return { error: parseCompileError(error, "runtime") };
|
|
1249
|
+
}
|
|
1250
|
+
componentDidCatch(error) {
|
|
1251
|
+
this.props.onError(parseCompileError(error, "runtime"));
|
|
1252
|
+
}
|
|
1253
|
+
render() {
|
|
1254
|
+
if (this.state.error) {
|
|
1255
|
+
return /* @__PURE__ */ jsx9(ErrorNotice, { error: this.state.error });
|
|
1256
|
+
}
|
|
1257
|
+
return this.props.children;
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1260
|
+
function useStoreSnapshot(store) {
|
|
1261
|
+
return useSyncExternalStore(store.subscribe, store.getState, store.getState);
|
|
1262
|
+
}
|
|
1263
|
+
function MdxPreview(props) {
|
|
1264
|
+
const {
|
|
1265
|
+
state,
|
|
1266
|
+
className,
|
|
1267
|
+
themeKey = "",
|
|
1268
|
+
ariaLabel,
|
|
1269
|
+
renderBlock,
|
|
1270
|
+
mdx,
|
|
1271
|
+
onContentUpdate
|
|
1272
|
+
} = props;
|
|
1273
|
+
const snapshot = useStoreSnapshot(state);
|
|
1274
|
+
const rootRef = useRef7(null);
|
|
1275
|
+
const [runtimeError, setRuntimeError] = useState5(null);
|
|
1276
|
+
const wrappedComponents = useMemo4(() => {
|
|
1277
|
+
const wrapComponentMap = (componentMap) => {
|
|
1278
|
+
const wrapped = {};
|
|
1279
|
+
for (const [name, component] of Object.entries(componentMap)) {
|
|
1280
|
+
if (typeof component === "function") {
|
|
1281
|
+
wrapped[name] = wrapWithShell(name, component);
|
|
1282
|
+
continue;
|
|
1283
|
+
}
|
|
1284
|
+
wrapped[name] = wrapComponentMap(component);
|
|
1285
|
+
}
|
|
1286
|
+
return wrapped;
|
|
1287
|
+
};
|
|
1288
|
+
const merged = {
|
|
1289
|
+
...DEFAULT_MDX_COMPONENTS,
|
|
1290
|
+
...mdx?.components ?? {}
|
|
1291
|
+
};
|
|
1292
|
+
return wrapComponentMap(merged);
|
|
1293
|
+
}, [mdx?.components]);
|
|
1294
|
+
const { markdownHtml, mdxDisplay } = useMdxPreviewCompilation({
|
|
1295
|
+
snapshot,
|
|
1296
|
+
themeKey,
|
|
1297
|
+
renderBlock,
|
|
1298
|
+
mdx,
|
|
1299
|
+
wrappedComponents
|
|
1300
|
+
});
|
|
1301
|
+
useEffect5(() => {
|
|
1302
|
+
setRuntimeError(null);
|
|
1303
|
+
}, [mdxDisplay.renderKey]);
|
|
1304
|
+
useEffect5(() => {
|
|
1305
|
+
const root = rootRef.current;
|
|
1306
|
+
if (!root || !onContentUpdate) return;
|
|
1307
|
+
const observer = new ResizeObserver(() => onContentUpdate());
|
|
1308
|
+
observer.observe(root);
|
|
1309
|
+
return () => observer.disconnect();
|
|
1310
|
+
}, [onContentUpdate]);
|
|
1311
|
+
useEffect5(() => {
|
|
1312
|
+
if (!onContentUpdate) return;
|
|
1313
|
+
const id = requestAnimationFrame(() => onContentUpdate());
|
|
1314
|
+
return () => cancelAnimationFrame(id);
|
|
1315
|
+
}, [mdxDisplay, markdownHtml, runtimeError, onContentUpdate]);
|
|
1316
|
+
const hasContent = mdxDisplay.Content !== null || markdownHtml !== null;
|
|
1317
|
+
return /* @__PURE__ */ jsxs3(
|
|
1318
|
+
"div",
|
|
1319
|
+
{
|
|
1320
|
+
ref: rootRef,
|
|
1321
|
+
className,
|
|
1322
|
+
role: "document",
|
|
1323
|
+
"aria-label": ariaLabel ?? "Preview",
|
|
1324
|
+
"aria-live": "polite",
|
|
1325
|
+
children: [
|
|
1326
|
+
mdxDisplay.pending && hasContent && /* @__PURE__ */ jsx9("div", { className: "pointer-events-none sticky top-0 z-10 mb-3 h-0.5 w-full animate-pulse rounded-full bg-p400" }),
|
|
1327
|
+
mdxDisplay.error && /* @__PURE__ */ jsx9(ErrorNotice, { error: mdxDisplay.error }),
|
|
1328
|
+
runtimeError && /* @__PURE__ */ jsx9(ErrorNotice, { error: runtimeError }),
|
|
1329
|
+
!hasContent && mdxDisplay.pending && /* @__PURE__ */ jsx9(MdxSkeleton, { lines: 8 }),
|
|
1330
|
+
markdownHtml !== null && markdownHtml.map(({ blockId, html }) => /* @__PURE__ */ jsx9("div", { dangerouslySetInnerHTML: { __html: html } }, blockId)),
|
|
1331
|
+
mdxDisplay.Content && mdxDisplay.runtimeComponents && /* @__PURE__ */ jsx9(RuntimeErrorBoundary, { onError: setRuntimeError, children: /* @__PURE__ */ jsx9(mdxDisplay.Content, { components: mdxDisplay.runtimeComponents }) }, mdxDisplay.renderKey)
|
|
1332
|
+
]
|
|
1333
|
+
}
|
|
1334
|
+
);
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
// src/OwoMarkPreview.tsx
|
|
1338
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
596
1339
|
function isController(store) {
|
|
597
1340
|
return typeof store.updateVisibleBlockIds === "function";
|
|
598
1341
|
}
|
|
@@ -606,16 +1349,31 @@ var OwoMarkPreview = function OwoMarkPreview2(props) {
|
|
|
606
1349
|
viewportFirst,
|
|
607
1350
|
ariaLabel,
|
|
608
1351
|
renderBlock,
|
|
1352
|
+
mdx,
|
|
609
1353
|
onContentUpdate
|
|
610
1354
|
} = props;
|
|
611
|
-
|
|
1355
|
+
if (strategy === "mdx") {
|
|
1356
|
+
return /* @__PURE__ */ jsx10(
|
|
1357
|
+
MdxPreview,
|
|
1358
|
+
{
|
|
1359
|
+
state,
|
|
1360
|
+
className,
|
|
1361
|
+
themeKey,
|
|
1362
|
+
ariaLabel,
|
|
1363
|
+
renderBlock,
|
|
1364
|
+
mdx,
|
|
1365
|
+
onContentUpdate
|
|
1366
|
+
}
|
|
1367
|
+
);
|
|
1368
|
+
}
|
|
1369
|
+
const onContentUpdateRef = useRef8(onContentUpdate);
|
|
612
1370
|
onContentUpdateRef.current = onContentUpdate;
|
|
613
|
-
const renderBlockRef =
|
|
1371
|
+
const renderBlockRef = useRef8(renderBlock);
|
|
614
1372
|
renderBlockRef.current = renderBlock;
|
|
615
1373
|
const hasRenderBlock = !!renderBlock;
|
|
616
|
-
const containerRef =
|
|
617
|
-
const engineRef =
|
|
618
|
-
|
|
1374
|
+
const containerRef = useRef8(null);
|
|
1375
|
+
const engineRef = useRef8(null);
|
|
1376
|
+
useEffect6(() => {
|
|
619
1377
|
if (!containerRef.current) return;
|
|
620
1378
|
const engineOptions = {
|
|
621
1379
|
strategy,
|
|
@@ -635,7 +1393,7 @@ var OwoMarkPreview = function OwoMarkPreview2(props) {
|
|
|
635
1393
|
engineRef.current = null;
|
|
636
1394
|
};
|
|
637
1395
|
}, [strategy, themeKey, registry, viewportFirst, hasRenderBlock]);
|
|
638
|
-
|
|
1396
|
+
useEffect6(() => {
|
|
639
1397
|
const unsub = state.subscribe((newState) => {
|
|
640
1398
|
const engine = engineRef.current;
|
|
641
1399
|
if (engine) {
|
|
@@ -644,7 +1402,7 @@ var OwoMarkPreview = function OwoMarkPreview2(props) {
|
|
|
644
1402
|
});
|
|
645
1403
|
return unsub;
|
|
646
1404
|
}, [state]);
|
|
647
|
-
|
|
1405
|
+
useEffect6(() => {
|
|
648
1406
|
const container = containerRef.current;
|
|
649
1407
|
if (!viewportFirst || !container || !isController(state)) return;
|
|
650
1408
|
const controller = state;
|
|
@@ -686,7 +1444,7 @@ var OwoMarkPreview = function OwoMarkPreview2(props) {
|
|
|
686
1444
|
mutation.disconnect();
|
|
687
1445
|
};
|
|
688
1446
|
}, [viewportFirst, state]);
|
|
689
|
-
return /* @__PURE__ */
|
|
1447
|
+
return /* @__PURE__ */ jsx10(
|
|
690
1448
|
"div",
|
|
691
1449
|
{
|
|
692
1450
|
ref: containerRef,
|
|
@@ -699,33 +1457,33 @@ var OwoMarkPreview = function OwoMarkPreview2(props) {
|
|
|
699
1457
|
};
|
|
700
1458
|
|
|
701
1459
|
// src/useOwoMarkSharedState.ts
|
|
702
|
-
import { useRef as
|
|
1460
|
+
import { useRef as useRef9, useSyncExternalStore as useSyncExternalStore2, useCallback as useCallback3 } from "react";
|
|
703
1461
|
import {
|
|
704
1462
|
createSharedStateStore
|
|
705
1463
|
} from "@owomark/core";
|
|
706
1464
|
function useOwoMarkSharedState(options) {
|
|
707
|
-
const controllerRef =
|
|
1465
|
+
const controllerRef = useRef9(null);
|
|
708
1466
|
if (!controllerRef.current) {
|
|
709
1467
|
controllerRef.current = createSharedStateStore(options);
|
|
710
1468
|
}
|
|
711
1469
|
return controllerRef.current;
|
|
712
1470
|
}
|
|
713
1471
|
function useSharedStateSnapshot(controller) {
|
|
714
|
-
const subscribe =
|
|
1472
|
+
const subscribe = useCallback3(
|
|
715
1473
|
(onStoreChange) => controller.subscribe(onStoreChange),
|
|
716
1474
|
[controller]
|
|
717
1475
|
);
|
|
718
|
-
const getSnapshot =
|
|
719
|
-
return
|
|
1476
|
+
const getSnapshot = useCallback3(() => controller.getState(), [controller]);
|
|
1477
|
+
return useSyncExternalStore2(subscribe, getSnapshot, getSnapshot);
|
|
720
1478
|
}
|
|
721
1479
|
|
|
722
1480
|
// src/useBlockContext.ts
|
|
723
|
-
import { useState as
|
|
1481
|
+
import { useState as useState6, useEffect as useEffect8 } from "react";
|
|
724
1482
|
function useBlockContext(core) {
|
|
725
|
-
const [blockContext, setBlockContext] =
|
|
1483
|
+
const [blockContext, setBlockContext] = useState6(
|
|
726
1484
|
() => core.getBlockContext()
|
|
727
1485
|
);
|
|
728
|
-
|
|
1486
|
+
useEffect8(() => {
|
|
729
1487
|
setBlockContext(core.getBlockContext());
|
|
730
1488
|
return core.onBlockContextChange((ctx) => {
|
|
731
1489
|
setBlockContext(ctx);
|
|
@@ -738,23 +1496,23 @@ function useBlockContext(core) {
|
|
|
738
1496
|
import { getThemeClassName as getThemeClassName2, THEME_LIGHT_CLASS, THEME_DARK_CLASS } from "@owomark/view";
|
|
739
1497
|
|
|
740
1498
|
// src/useVirtualList.ts
|
|
741
|
-
import { useState as
|
|
1499
|
+
import { useState as useState7, useCallback as useCallback4, useRef as useRef10, useEffect as useEffect9, useMemo as useMemo5 } from "react";
|
|
742
1500
|
import {
|
|
743
1501
|
buildVirtualRows,
|
|
744
1502
|
computeVisibleRange
|
|
745
1503
|
} from "@owomark/core";
|
|
746
1504
|
function useVirtualList(options) {
|
|
747
1505
|
const { blocks, containerRef, overscan = 5, charsPerLine = 80 } = options;
|
|
748
|
-
const heightCacheRef =
|
|
749
|
-
const [scrollTop, setScrollTop] =
|
|
750
|
-
const [viewportHeight, setViewportHeight] =
|
|
751
|
-
const [heightCacheVersion, setHeightCacheVersion] =
|
|
752
|
-
const rafRef =
|
|
753
|
-
const [container, setContainer] =
|
|
754
|
-
|
|
1506
|
+
const heightCacheRef = useRef10(/* @__PURE__ */ new Map());
|
|
1507
|
+
const [scrollTop, setScrollTop] = useState7(0);
|
|
1508
|
+
const [viewportHeight, setViewportHeight] = useState7(0);
|
|
1509
|
+
const [heightCacheVersion, setHeightCacheVersion] = useState7(0);
|
|
1510
|
+
const rafRef = useRef10(0);
|
|
1511
|
+
const [container, setContainer] = useState7(null);
|
|
1512
|
+
useEffect9(() => {
|
|
755
1513
|
setContainer(containerRef.current);
|
|
756
1514
|
});
|
|
757
|
-
|
|
1515
|
+
useEffect9(() => {
|
|
758
1516
|
if (!container) return;
|
|
759
1517
|
setViewportHeight(container.clientHeight);
|
|
760
1518
|
const ro = new ResizeObserver((entries) => {
|
|
@@ -765,7 +1523,7 @@ function useVirtualList(options) {
|
|
|
765
1523
|
ro.observe(container);
|
|
766
1524
|
return () => ro.disconnect();
|
|
767
1525
|
}, [container]);
|
|
768
|
-
|
|
1526
|
+
useEffect9(() => {
|
|
769
1527
|
if (!container) return;
|
|
770
1528
|
const onScroll = () => {
|
|
771
1529
|
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
@@ -779,27 +1537,27 @@ function useVirtualList(options) {
|
|
|
779
1537
|
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
780
1538
|
};
|
|
781
1539
|
}, [container]);
|
|
782
|
-
const rows =
|
|
1540
|
+
const rows = useMemo5(
|
|
783
1541
|
() => buildVirtualRows(blocks, heightCacheRef.current, charsPerLine),
|
|
784
1542
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
785
1543
|
[blocks, charsPerLine, heightCacheVersion]
|
|
786
1544
|
);
|
|
787
|
-
const visibleRange =
|
|
1545
|
+
const visibleRange = useMemo5(
|
|
788
1546
|
() => computeVisibleRange(rows, scrollTop, viewportHeight, overscan),
|
|
789
1547
|
[rows, scrollTop, viewportHeight, overscan]
|
|
790
1548
|
);
|
|
791
|
-
const updateBlockHeight =
|
|
1549
|
+
const updateBlockHeight = useCallback4((blockId, height) => {
|
|
792
1550
|
const cache = heightCacheRef.current;
|
|
793
1551
|
if (cache.get(blockId) !== height) {
|
|
794
1552
|
cache.set(blockId, height);
|
|
795
1553
|
setHeightCacheVersion((v) => v + 1);
|
|
796
1554
|
}
|
|
797
1555
|
}, []);
|
|
798
|
-
const isBlockVisible =
|
|
1556
|
+
const isBlockVisible = useCallback4(
|
|
799
1557
|
(blockIndex) => blockIndex >= visibleRange.startIndex && blockIndex <= visibleRange.endIndex,
|
|
800
1558
|
[visibleRange]
|
|
801
1559
|
);
|
|
802
|
-
const invalidateAllHeights =
|
|
1560
|
+
const invalidateAllHeights = useCallback4(() => {
|
|
803
1561
|
heightCacheRef.current.clear();
|
|
804
1562
|
setHeightCacheVersion((v) => v + 1);
|
|
805
1563
|
}, []);
|
|
@@ -813,73 +1571,8 @@ function useVirtualList(options) {
|
|
|
813
1571
|
};
|
|
814
1572
|
}
|
|
815
1573
|
|
|
816
|
-
// src/
|
|
817
|
-
import {
|
|
818
|
-
function MdxSkeleton({ height, lines = 3, className, style }) {
|
|
819
|
-
const combinedStyle = {
|
|
820
|
-
...style,
|
|
821
|
-
...height != null ? { height, minHeight: height } : {}
|
|
822
|
-
};
|
|
823
|
-
return /* @__PURE__ */ jsx7(
|
|
824
|
-
"div",
|
|
825
|
-
{
|
|
826
|
-
className: `owo-mdx-skeleton-block ${className ?? ""}`,
|
|
827
|
-
style: combinedStyle,
|
|
828
|
-
"aria-hidden": "true",
|
|
829
|
-
children: Array.from({ length: lines }, (_, i) => /* @__PURE__ */ jsx7("div", { className: "owo-mdx-skeleton owo-mdx-skeleton-line" }, i))
|
|
830
|
-
}
|
|
831
|
-
);
|
|
832
|
-
}
|
|
833
|
-
|
|
834
|
-
// src/MdxComponentShell.tsx
|
|
835
|
-
import {
|
|
836
|
-
useRef as useRef7,
|
|
837
|
-
useState as useState5,
|
|
838
|
-
useEffect as useEffect7,
|
|
839
|
-
useCallback as useCallback4
|
|
840
|
-
} from "react";
|
|
841
|
-
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
842
|
-
var componentHeightCache = /* @__PURE__ */ new Map();
|
|
843
|
-
var DEFAULT_ESTIMATED_HEIGHT = 80;
|
|
844
|
-
function MdxComponentShell({ name, children }) {
|
|
845
|
-
const containerRef = useRef7(null);
|
|
846
|
-
const [ready, setReady] = useState5(false);
|
|
847
|
-
const estimatedHeight = componentHeightCache.get(name) ?? DEFAULT_ESTIMATED_HEIGHT;
|
|
848
|
-
useEffect7(() => {
|
|
849
|
-
const id = requestAnimationFrame(() => setReady(true));
|
|
850
|
-
return () => cancelAnimationFrame(id);
|
|
851
|
-
}, []);
|
|
852
|
-
const measureHeight = useCallback4(() => {
|
|
853
|
-
const el = containerRef.current;
|
|
854
|
-
if (!el) return;
|
|
855
|
-
const h = el.getBoundingClientRect().height;
|
|
856
|
-
if (h > 0) {
|
|
857
|
-
componentHeightCache.set(name, h);
|
|
858
|
-
}
|
|
859
|
-
}, [name]);
|
|
860
|
-
useEffect7(() => {
|
|
861
|
-
const el = containerRef.current;
|
|
862
|
-
if (!el || !ready) return;
|
|
863
|
-
measureHeight();
|
|
864
|
-
const ro = new ResizeObserver(() => measureHeight());
|
|
865
|
-
ro.observe(el);
|
|
866
|
-
return () => ro.disconnect();
|
|
867
|
-
}, [ready, measureHeight]);
|
|
868
|
-
if (!ready) {
|
|
869
|
-
return /* @__PURE__ */ jsx8(MdxSkeleton, { height: estimatedHeight });
|
|
870
|
-
}
|
|
871
|
-
return /* @__PURE__ */ jsx8("div", { ref: containerRef, children });
|
|
872
|
-
}
|
|
873
|
-
function wrapWithShell(name, Component) {
|
|
874
|
-
function ShellWrapped(props) {
|
|
875
|
-
return /* @__PURE__ */ jsx8(MdxComponentShell, { name, children: /* @__PURE__ */ jsx8(Component, { ...props }) });
|
|
876
|
-
}
|
|
877
|
-
ShellWrapped.displayName = `MdxShell(${name})`;
|
|
878
|
-
return ShellWrapped;
|
|
879
|
-
}
|
|
880
|
-
function clearComponentHeightCache() {
|
|
881
|
-
componentHeightCache.clear();
|
|
882
|
-
}
|
|
1574
|
+
// src/index.ts
|
|
1575
|
+
import { registerPlugin } from "@owomark/processor";
|
|
883
1576
|
export {
|
|
884
1577
|
DEFAULT_EDITOR_CONFIG,
|
|
885
1578
|
EditorBlock,
|
|
@@ -892,11 +1585,14 @@ export {
|
|
|
892
1585
|
SlashMenu,
|
|
893
1586
|
THEME_DARK_CLASS,
|
|
894
1587
|
THEME_LIGHT_CLASS,
|
|
1588
|
+
acquireMdxWorker,
|
|
895
1589
|
clearComponentHeightCache,
|
|
896
1590
|
computeMenuPosition,
|
|
897
1591
|
deriveProcessorOptions,
|
|
898
1592
|
getCaretRect,
|
|
899
1593
|
getThemeClassName2 as getThemeClassName,
|
|
1594
|
+
registerPlugin,
|
|
1595
|
+
releaseMdxWorker,
|
|
900
1596
|
resolveEditorConfig,
|
|
901
1597
|
useBlockContext,
|
|
902
1598
|
useOwoMarkCore,
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// src/mdx.worker.ts
|
|
2
|
+
import { compile } from "@mdx-js/mdx";
|
|
3
|
+
import {
|
|
4
|
+
getOwoMarkPlugins,
|
|
5
|
+
inspectMdxSource,
|
|
6
|
+
remapMdxErrorDetails
|
|
7
|
+
} from "@owomark/processor";
|
|
8
|
+
|
|
9
|
+
// src/mdx-error.ts
|
|
10
|
+
function parseMdxErrorDetails(error) {
|
|
11
|
+
if (error && typeof error === "object") {
|
|
12
|
+
const value = error;
|
|
13
|
+
if (typeof value.line === "number") {
|
|
14
|
+
return {
|
|
15
|
+
message: value.message ?? String(error),
|
|
16
|
+
line: value.line,
|
|
17
|
+
column: typeof value.column === "number" ? value.column : void 0
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
const text = value.message ?? String(error);
|
|
21
|
+
const match = text.match(/\((\d+):(\d+)/);
|
|
22
|
+
if (match) {
|
|
23
|
+
return {
|
|
24
|
+
message: text,
|
|
25
|
+
line: Number(match[1]),
|
|
26
|
+
column: Number(match[2])
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { message: text };
|
|
30
|
+
}
|
|
31
|
+
return { message: String(error) };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/mdx.worker.ts
|
|
35
|
+
var cancelledIds = /* @__PURE__ */ new Set();
|
|
36
|
+
self.onmessage = (e) => {
|
|
37
|
+
const msg = e.data;
|
|
38
|
+
if (msg.type === "cancel") {
|
|
39
|
+
cancelledIds.add(msg.id);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
void handleCompile(msg);
|
|
43
|
+
};
|
|
44
|
+
async function handleCompile(data) {
|
|
45
|
+
const { id, markdown, options } = data;
|
|
46
|
+
const inspection = options.preparedSource && options.sourceMap ? null : inspectMdxSource(markdown, {
|
|
47
|
+
enableMath: options.enableMath,
|
|
48
|
+
enableSideAnnotation: options.enableSideAnnotation,
|
|
49
|
+
extraRemarkDescriptors: options.extraRemarkDescriptors
|
|
50
|
+
});
|
|
51
|
+
const preparedSource = options.preparedSource ?? inspection.compileSource;
|
|
52
|
+
const sourceMap = options.sourceMap ?? inspection.sourceMap;
|
|
53
|
+
try {
|
|
54
|
+
if (cancelledIds.has(id)) {
|
|
55
|
+
cancelledIds.delete(id);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const { remarkPlugins, rehypePlugins } = getOwoMarkPlugins({
|
|
59
|
+
mode: "production",
|
|
60
|
+
enableMath: options.enableMath,
|
|
61
|
+
enableSideAnnotation: options.enableSideAnnotation,
|
|
62
|
+
enableCodeHighlight: options.enableCodeHighlight,
|
|
63
|
+
sourceAnchors: options.sourceAnchors,
|
|
64
|
+
extraRemarkDescriptors: options.extraRemarkDescriptors,
|
|
65
|
+
extraRehypeDescriptors: options.extraRehypeDescriptors,
|
|
66
|
+
mdxSourceMap: sourceMap
|
|
67
|
+
});
|
|
68
|
+
if (cancelledIds.has(id)) {
|
|
69
|
+
cancelledIds.delete(id);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const result = await compile(preparedSource, {
|
|
73
|
+
outputFormat: "function-body",
|
|
74
|
+
remarkPlugins,
|
|
75
|
+
rehypePlugins
|
|
76
|
+
});
|
|
77
|
+
if (cancelledIds.has(id)) {
|
|
78
|
+
cancelledIds.delete(id);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
self.postMessage({
|
|
82
|
+
id,
|
|
83
|
+
ok: true,
|
|
84
|
+
code: String(result)
|
|
85
|
+
});
|
|
86
|
+
} catch (error) {
|
|
87
|
+
if (cancelledIds.has(id)) {
|
|
88
|
+
cancelledIds.delete(id);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
self.postMessage({
|
|
92
|
+
id,
|
|
93
|
+
ok: false,
|
|
94
|
+
error: parseMdxErrorDetails(remapMdxErrorDetails(error, sourceMap))
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owomark/react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "React bindings and components for the OwoMark editor stack.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -33,9 +33,10 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@
|
|
37
|
-
"@owomark/
|
|
38
|
-
"@owomark/
|
|
36
|
+
"@mdx-js/mdx": "^3.0.0",
|
|
37
|
+
"@owomark/core": "^0.1.6",
|
|
38
|
+
"@owomark/processor": "^0.1.6",
|
|
39
|
+
"@owomark/view": "^0.1.6"
|
|
39
40
|
},
|
|
40
41
|
"peerDependencies": {
|
|
41
42
|
"react": ">=18",
|
package/dist/index.css
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
/* src/MdxSkeleton.css */
|
|
2
|
-
.owo-mdx-skeleton {
|
|
3
|
-
background:
|
|
4
|
-
linear-gradient(
|
|
5
|
-
90deg,
|
|
6
|
-
var(--owo-skeleton-base, #e5e7eb) 25%,
|
|
7
|
-
var(--owo-skeleton-shine, #f3f4f6) 50%,
|
|
8
|
-
var(--owo-skeleton-base, #e5e7eb) 75%);
|
|
9
|
-
background-size: 200% 100%;
|
|
10
|
-
animation: owo-mdx-skeleton-shimmer 1.5s ease-in-out infinite;
|
|
11
|
-
border-radius: 4px;
|
|
12
|
-
}
|
|
13
|
-
@keyframes owo-mdx-skeleton-shimmer {
|
|
14
|
-
0% {
|
|
15
|
-
background-position: 200% 0;
|
|
16
|
-
}
|
|
17
|
-
100% {
|
|
18
|
-
background-position: -200% 0;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
.owo-mdx-skeleton-block {
|
|
22
|
-
display: flex;
|
|
23
|
-
flex-direction: column;
|
|
24
|
-
gap: 8px;
|
|
25
|
-
padding: 12px 0;
|
|
26
|
-
}
|
|
27
|
-
.owo-mdx-skeleton-line {
|
|
28
|
-
height: 14px;
|
|
29
|
-
}
|
|
30
|
-
.owo-mdx-skeleton-line:last-child {
|
|
31
|
-
width: 60%;
|
|
32
|
-
}
|