markdown-design-doc-viewer-embed 0.0.0-stage → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,55 @@
1
1
  {
2
2
  "name": "markdown-design-doc-viewer-embed",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.5.0",
4
+ "description": "The viewer of Markdown Design Doc Viewer to embed in a web app (React or not): design documents in Markdown with their mermaid sequence diagrams, flowcharts, ER and state diagrams and wireframes linked to the steps after them.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/playree/markdown-design-doc-viewer.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/playree/markdown-design-doc-viewer/issues"
12
+ },
13
+ "homepage": "https://github.com/playree/markdown-design-doc-viewer/blob/main/docs/embed.md",
14
+ "keywords": [
15
+ "markdown",
16
+ "mermaid",
17
+ "design document",
18
+ "viewer",
19
+ "react",
20
+ "sequence diagram",
21
+ "flowchart",
22
+ "specification",
23
+ "documentation",
24
+ "設計書"
25
+ ],
26
+ "type": "module",
27
+ "sideEffects": [
28
+ "./viewer.css"
29
+ ],
30
+ "exports": {
31
+ ".": {
32
+ "types": "./types/embed/viewer.d.ts",
33
+ "default": "./index.js"
34
+ },
35
+ "./react": {
36
+ "types": "./types/embed/react.d.ts",
37
+ "default": "./react.js"
38
+ },
39
+ "./viewer.css": "./viewer.css",
40
+ "./package.json": "./package.json"
41
+ },
42
+ "peerDependencies": {
43
+ "mermaid": "^12.3.0",
44
+ "react": "^19.3.1",
45
+ "react-dom": "^19.3.1"
46
+ },
47
+ "peerDependenciesMeta": {
48
+ "react": {
49
+ "optional": true
50
+ },
51
+ "react-dom": {
52
+ "optional": true
53
+ }
54
+ }
55
+ }
package/react.js ADDED
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+
3
+ // embed/react.tsx
4
+ import { forwardRef, useEffect, useImperativeHandle, useRef } from "react";
5
+ import { createViewer, openLinkInNewTab } from "./index.js";
6
+ import { jsx } from "react/jsx-runtime";
7
+ var DesignDocViewer = forwardRef(function DesignDocViewer2({ className, style, ...options }, ref) {
8
+ const element = useRef(null);
9
+ const viewer = useRef(void 0);
10
+ const created = useRef(false);
11
+ const latest = useRef(options);
12
+ latest.current = options;
13
+ const revealing = options.onRevealLine !== void 0;
14
+ const viewerOptions = () => ({
15
+ ...latest.current,
16
+ onOpenLink: (href) => (latest.current.onOpenLink ?? openLinkInNewTab)(href),
17
+ // Only with one: without, a double-click does nothing.
18
+ onRevealLine: revealing ? (line) => latest.current.onRevealLine?.(line) : void 0
19
+ });
20
+ useEffect(() => {
21
+ const instance = createViewer(element.current, viewerOptions());
22
+ viewer.current = instance;
23
+ created.current = true;
24
+ return () => {
25
+ instance.destroy();
26
+ viewer.current = void 0;
27
+ };
28
+ }, [options.lang]);
29
+ const { markdown, documentId, baseUrl, readFile, resolveResource, theme, diagramLook, splitMinWidth, toc, limitContentWidth, stickyTableHeader, tableTreeHighlight, frontMatter, headingNumbers } = options;
30
+ useEffect(() => {
31
+ if (created.current) {
32
+ created.current = false;
33
+ return;
34
+ }
35
+ void viewer.current?.update(viewerOptions());
36
+ }, [options.lang, markdown, documentId, baseUrl, readFile, resolveResource, theme, diagramLook, splitMinWidth, toc, limitContentWidth, stickyTableHeader, tableTreeHighlight, frontMatter, headingNumbers, revealing]);
37
+ useImperativeHandle(ref, () => ({
38
+ scrollToLine: (line) => viewer.current?.scrollToLine(line),
39
+ markLine: (line) => viewer.current?.markLine(line)
40
+ }));
41
+ return /* @__PURE__ */ jsx("div", { ref: element, className, style });
42
+ });
43
+ export {
44
+ DesignDocViewer
45
+ };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The viewer of embed/viewer.ts as a React component. Its styles are embed/viewer.css, which the app imports.
3
+ *
4
+ * <DesignDocViewer markdown={text} baseUrl="/docs/" style={{ height: 600 }} />
5
+ *
6
+ * It needs a height, which the viewer fills. `readFile` and `resolveResource` render the document again when they
7
+ * change: keep them the same across renders (`useCallback`). The other callbacks may change freely.
8
+ */
9
+ import { type CSSProperties } from 'react';
10
+ import { type ViewerOptions } from './viewer.js';
11
+ export type { ViewerOptions } from './viewer.js';
12
+ export interface DesignDocViewerProps extends ViewerOptions {
13
+ className?: string;
14
+ style?: CSSProperties;
15
+ }
16
+ /** What the `ref` of a `DesignDocViewer` gives. */
17
+ export interface DesignDocViewerHandle {
18
+ /** Scrolls the viewer so that this line (0-based) of the Markdown is at the top. */
19
+ scrollToLine(line: number): void;
20
+ /** Marks the element of this line (0-based), and scrolls it into view. */
21
+ markLine(line: number): void;
22
+ }
23
+ export declare const DesignDocViewer: import("react").ForwardRefExoticComponent<DesignDocViewerProps & import("react").RefAttributes<DesignDocViewerHandle>>;
@@ -0,0 +1,66 @@
1
+ import type { DiagramLook } from '../src/shared/protocol.js';
2
+ export type { DiagramLook };
3
+ export interface ViewerOptions {
4
+ /** The Markdown of the design document. */
5
+ markdown: string;
6
+ /**
7
+ * Tells the documents apart: when it changes, the viewer shows another document, from its top. While it stays the
8
+ * same, an update keeps the scrolling, as when the document is edited.
9
+ */
10
+ documentId?: string;
11
+ /**
12
+ * The URL of the folder of the document, from which the paths of its images and wireframes are resolved (and the
13
+ * wireframes read with `fetch`, without `readFile`).
14
+ */
15
+ baseUrl?: string;
16
+ /**
17
+ * Reads a file of a wireframe (its HTML, or a style sheet of it), given its path as written in the document (relative
18
+ * to it, or to the root with a leading `/`), decoded (`%20` is a space). Returns undefined when it cannot be read.
19
+ */
20
+ readFile?: (path: string) => Promise<string | undefined>;
21
+ /** The URL of an image `src` of the document. By default, resolved from `baseUrl`. */
22
+ resolveResource?: (src: string) => string;
23
+ /** The language of the texts of the viewer (`en` by default, or that of the browser). Only read by `createViewer`. */
24
+ lang?: 'en' | 'ja';
25
+ /** Light or dark colors, or those of the system (`auto`, the default). */
26
+ theme?: 'light' | 'dark' | 'auto';
27
+ /** `neo` (the default) or `classic` (flat) diagrams. */
28
+ diagramLook?: DiagramLook;
29
+ /** The width (px) from which the diagrams and their steps are side by side. 1000 by default. */
30
+ splitMinWidth?: number;
31
+ /** The table of contents at the right. true by default. */
32
+ toc?: boolean;
33
+ /** Limits the width of the document. true by default. */
34
+ limitContentWidth?: boolean;
35
+ /** Keeps the header row of a long table at the top while it scrolls. true by default. */
36
+ stickyTableHeader?: boolean;
37
+ /** Highlights the parent and children of a row of a table shown as a tree. true by default. */
38
+ tableTreeHighlight?: boolean;
39
+ /** Shows the front matter (as the header of a design document, or as a table). true by default. */
40
+ frontMatter?: boolean;
41
+ /** Shows the `autonumber` numbers on the linked headings. true by default. */
42
+ headingNumbers?: boolean;
43
+ /**
44
+ * Opens a link of the document (other than `#heading`, which the viewer scrolls to). By default, http(s) and mailto
45
+ * links open in a new tab, and the others do nothing.
46
+ */
47
+ onOpenLink?: (href: string) => void;
48
+ /** Called with the line (0-based) of the Markdown double-clicked in the viewer, e.g. to show it in an editor. */
49
+ onRevealLine?: (line: number) => void;
50
+ }
51
+ export interface Viewer {
52
+ /** Resolves once the document is shown, with its diagrams (that of `createViewer`, or of an update made meanwhile). */
53
+ ready: Promise<void>;
54
+ /** Changes some options (all but `lang`) and renders the document again. Resolves once it is shown (or superseded). */
55
+ update(options: Partial<Omit<ViewerOptions, 'lang'>>): Promise<void>;
56
+ /** Scrolls the viewer so that this line (0-based) of the Markdown is at the top. */
57
+ scrollToLine(line: number): void;
58
+ /** Marks the element of this line (0-based), and scrolls it into view: e.g. the line of the cursor of an editor. */
59
+ markLine(line: number): void;
60
+ /** Removes the viewer from its element. */
61
+ destroy(): void;
62
+ }
63
+ /** What `onOpenLink` does by default: opens http(s) and mailto links in a new tab. */
64
+ export declare function openLinkInNewTab(href: string): void;
65
+ /** Shows the design document of `options` in `container`, which it fills. */
66
+ export declare function createViewer(container: HTMLElement, options: ViewerOptions): Viewer;
@@ -0,0 +1,111 @@
1
+ /** Messages exchanged between the extension host and the preview webview. */
2
+ /** Look of the mermaid diagrams: mermaid's default (`neo`, with shadows), or the flat `classic` one. */
3
+ export type DiagramLook = 'neo' | 'classic';
4
+ /** Color theme of the preview: VS Code's (`auto`), or always light / dark. */
5
+ export type PreviewTheme = 'auto' | 'light' | 'dark';
6
+ /** The differences from a revision shown by an `update` (`renderDiff` in diffRender.ts). */
7
+ export interface DiffView {
8
+ /** What the document is compared with, translated (e.g. the commit). */
9
+ label: string;
10
+ /** HTML of the revision's blocks that changed, by their `data-seqnotes-diff-old`. */
11
+ old: string[];
12
+ stats: {
13
+ added: number;
14
+ changed: number;
15
+ deleted: number;
16
+ };
17
+ }
18
+ export type ToWebview =
19
+ /**
20
+ * Render this document. With another `uri` than the previous update (another document opened in the same
21
+ * window, by the desktop app), the preview starts at the top, or at `fragment` (the id of a heading) when given.
22
+ * With `diff`, the HTML is that of `renderDiff`, and the preview shows the differences.
23
+ */
24
+ {
25
+ type: 'update';
26
+ uri: string;
27
+ html: string;
28
+ splitMinWidth: number;
29
+ syncEditor: boolean;
30
+ toc: boolean;
31
+ diagramLook: DiagramLook;
32
+ theme: PreviewTheme;
33
+ limitContentWidth: boolean;
34
+ stickyTableHeader: boolean;
35
+ tableTreeHighlight: boolean;
36
+ fragment?: string;
37
+ diff?: DiffView;
38
+ }
39
+ /** Editor scrolled: align the preview so that this line is at the top. */
40
+ | {
41
+ type: 'scrollToLine';
42
+ line: number;
43
+ }
44
+ /** Editor cursor moved: mark the element for this line. */
45
+ | {
46
+ type: 'markLine';
47
+ line: number;
48
+ }
49
+ /** Render this HTML for an exported file and send it back with `exported`. With `diff`, the HTML is that of `renderDiff`. */
50
+ | {
51
+ type: 'export';
52
+ id: number;
53
+ html: string;
54
+ diagramLook: DiagramLook;
55
+ diff?: DiffView;
56
+ };
57
+ export type FromWebview = {
58
+ type: 'ready';
59
+ }
60
+ /** Double-click in the preview: reveal this line in the editor. */
61
+ | {
62
+ type: 'revealLine';
63
+ line: number;
64
+ } | {
65
+ type: 'openLink';
66
+ href: string;
67
+ }
68
+ /**
69
+ * The rendered body of an `export` request, or why it failed. `diagramErrors` are the messages of the diagrams
70
+ * mermaid could not render (shown in the body in their place), `warnings` the problems found while rendering it
71
+ * (the selectors of the parts of the wireframes that match nothing), with their 0-based lines.
72
+ */
73
+ | {
74
+ type: 'exported';
75
+ id: number;
76
+ body?: string;
77
+ diagramErrors?: string[];
78
+ warnings?: {
79
+ line?: number;
80
+ message: string;
81
+ }[];
82
+ error?: string;
83
+ }
84
+ /** The differences shown are closed: back to the document alone. */
85
+ | {
86
+ type: 'closeDiff';
87
+ };
88
+ export interface WebviewState {
89
+ uri: string;
90
+ /** Width of the diagram column in percent. */
91
+ split?: number;
92
+ /** The search and the order of a list of documents (webview/indexList.ts). */
93
+ indexList?: IndexListState;
94
+ }
95
+ /** What a list of documents shows (webview/indexList.ts): kept while the list is updated. */
96
+ export interface IndexListState {
97
+ query: string;
98
+ /**
99
+ * The column the rows are sorted by (its `data-seqnotes-column`: `title`, `file` or a key of the front matter),
100
+ * and the order; the order of the list without it.
101
+ */
102
+ sort?: {
103
+ column: string;
104
+ descending: boolean;
105
+ };
106
+ }
107
+ /**
108
+ * Titles (tooltips) and labels of the preview's controls, in English: the host translates them and writes them on the
109
+ * body as `data-seqnotes-<name>` attributes, which the webview reads (and fills in their `{0}`).
110
+ */
111
+ export declare const WEBVIEW_TITLES: Record<string, string>;