@dxos/plugin-mermaid 0.8.4-main.fd6878d → 0.9.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.
Files changed (57) hide show
  1. package/LICENSE +102 -5
  2. package/PLUGIN.mdl +260 -0
  3. package/README.md +1 -1
  4. package/dist/lib/neutral/MermaidPlugin.mjs +29 -0
  5. package/dist/lib/neutral/MermaidPlugin.mjs.map +7 -0
  6. package/dist/lib/neutral/capabilities/index.mjs +7 -0
  7. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  8. package/dist/lib/neutral/chunk-WD2YFG2L.mjs +36 -0
  9. package/dist/lib/neutral/chunk-WD2YFG2L.mjs.map +7 -0
  10. package/dist/lib/neutral/index.mjs +7 -0
  11. package/dist/lib/neutral/index.mjs.map +7 -0
  12. package/dist/lib/neutral/markdown-extension-7YWEUNWO.mjs +172 -0
  13. package/dist/lib/neutral/markdown-extension-7YWEUNWO.mjs.map +7 -0
  14. package/dist/lib/neutral/meta.json +1 -0
  15. package/dist/lib/neutral/meta.mjs +7 -0
  16. package/dist/lib/neutral/meta.mjs.map +7 -0
  17. package/dist/lib/neutral/plugin.mjs +11 -0
  18. package/dist/lib/neutral/plugin.mjs.map +7 -0
  19. package/dist/types/src/MermaidPlugin.d.ts +3 -1
  20. package/dist/types/src/MermaidPlugin.d.ts.map +1 -1
  21. package/dist/types/src/MermaidPlugin.test.d.ts +2 -0
  22. package/dist/types/src/MermaidPlugin.test.d.ts.map +1 -0
  23. package/dist/types/src/capabilities/index.d.ts +3 -0
  24. package/dist/types/src/capabilities/index.d.ts.map +1 -0
  25. package/dist/types/src/capabilities/markdown-extension.d.ts +5 -0
  26. package/dist/types/src/capabilities/markdown-extension.d.ts.map +1 -0
  27. package/dist/types/src/extensions/index.d.ts +1 -1
  28. package/dist/types/src/extensions/index.d.ts.map +1 -1
  29. package/dist/types/src/extensions/mermaid-extension.d.ts +7 -0
  30. package/dist/types/src/extensions/mermaid-extension.d.ts.map +1 -0
  31. package/dist/types/src/extensions/mermaid.stories.d.ts +11 -11
  32. package/dist/types/src/extensions/mermaid.stories.d.ts.map +1 -1
  33. package/dist/types/src/index.d.ts +0 -1
  34. package/dist/types/src/index.d.ts.map +1 -1
  35. package/dist/types/src/meta.d.ts +2 -3
  36. package/dist/types/src/meta.d.ts.map +1 -1
  37. package/dist/types/src/plugin.d.ts +3 -0
  38. package/dist/types/src/plugin.d.ts.map +1 -0
  39. package/dist/types/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +59 -31
  41. package/src/MermaidPlugin.test.ts +30 -0
  42. package/src/MermaidPlugin.tsx +21 -12
  43. package/src/capabilities/index.ts +7 -0
  44. package/src/capabilities/markdown-extension.ts +14 -0
  45. package/src/extensions/index.ts +1 -1
  46. package/src/extensions/mermaid-extension.ts +215 -0
  47. package/src/extensions/mermaid.stories.tsx +20 -21
  48. package/src/index.ts +0 -1
  49. package/src/meta.ts +27 -7
  50. package/src/plugin.ts +9 -0
  51. package/src/vite-env.d.ts +10 -0
  52. package/dist/lib/browser/index.mjs +0 -136
  53. package/dist/lib/browser/index.mjs.map +0 -7
  54. package/dist/lib/browser/meta.json +0 -1
  55. package/dist/types/src/extensions/mermaid.d.ts +0 -4
  56. package/dist/types/src/extensions/mermaid.d.ts.map +0 -1
  57. package/src/extensions/mermaid.ts +0 -155
@@ -1,136 +0,0 @@
1
- // src/MermaidPlugin.tsx
2
- import { contributes, defineModule, definePlugin } from "@dxos/app-framework";
3
- import { MarkdownCapabilities, MarkdownEvents } from "@dxos/plugin-markdown";
4
-
5
- // src/extensions/mermaid.ts
6
- import { syntaxTree } from "@codemirror/language";
7
- import { RangeSetBuilder, StateField } from "@codemirror/state";
8
- import { Decoration, EditorView, WidgetType } from "@codemirror/view";
9
- import _mermaid from "mermaid";
10
- var mermaid = (options = {}) => {
11
- return [
12
- StateField.define({
13
- create: (state) => update(state, options),
14
- update: (_, tr) => update(tr.state, options),
15
- provide: (field) => EditorView.decorations.from(field)
16
- }),
17
- styles
18
- ];
19
- };
20
- var update = (state, options) => {
21
- const builder = new RangeSetBuilder();
22
- syntaxTree(state).iterate({
23
- enter: (node) => {
24
- if (node.name === "FencedCode") {
25
- const cursor = state.selection.main.head;
26
- if (state.readOnly || cursor < node.from || cursor > node.to) {
27
- const info = node.node.getChild("CodeInfo");
28
- if (info) {
29
- const type = state.sliceDoc(info.from, info.to);
30
- const text = node.node.getChild("CodeText");
31
- if (type === "mermaid" && text) {
32
- const content = state.sliceDoc(text.from, text.to);
33
- builder.add(node.from, node.to, Decoration.replace({
34
- widget: new MermaidWidget(`mermaid-${node.from}`, content)
35
- }));
36
- }
37
- }
38
- }
39
- }
40
- }
41
- });
42
- return builder.finish();
43
- };
44
- var MermaidWidget = class extends WidgetType {
45
- _id;
46
- _source;
47
- _svg;
48
- _error;
49
- // TODO(burdon): Mermaid API requires unique id.
50
- constructor(_id, _source) {
51
- super(), this._id = _id, this._source = _source;
52
- }
53
- eq(other) {
54
- return this._source === other._source;
55
- }
56
- toDOM(view) {
57
- const div = document.createElement("div");
58
- setTimeout(async () => {
59
- _mermaid.initialize({
60
- darkMode: view.state.facet(EditorView.darkTheme),
61
- theme: "neutral"
62
- });
63
- const svg = await this.render(div);
64
- if (this._error) {
65
- div.className = "cm-mermaid-error";
66
- div.innerText = this._error;
67
- } else {
68
- div.className = "cm-mermaid";
69
- div.innerHTML = svg;
70
- view.requestMeasure();
71
- }
72
- });
73
- return div;
74
- }
75
- async render(container) {
76
- try {
77
- const valid = await _mermaid.parse(this._source);
78
- if (valid) {
79
- const result = await _mermaid.render(this._id, this._source);
80
- this._error = void 0;
81
- this._svg = result.svg;
82
- return result.svg;
83
- }
84
- } catch (err) {
85
- this._error = String(err);
86
- this._svg = void 0;
87
- }
88
- }
89
- ignoreEvent(e) {
90
- return !/^mouse/.test(e.type);
91
- }
92
- };
93
- var styles = EditorView.theme({
94
- "& .cm-mermaid": {
95
- position: "relative",
96
- display: "inline-flex",
97
- width: "100%",
98
- justifyContent: "center"
99
- },
100
- // '& .cm-mermaid-label': {
101
- // position: 'absolute',
102
- // right: 0,
103
- // textSize: 10,
104
- // },
105
- "& .cm-mermaid-error": {
106
- display: "inline-block",
107
- color: "var(--dx-errorText)"
108
- }
109
- });
110
-
111
- // src/meta.ts
112
- var MERMAID_PLUGIN = "dxos.org/plugin/mermaid";
113
- var meta = {
114
- id: MERMAID_PLUGIN,
115
- name: "Mermaid",
116
- description: "Tool that renders text definitions to create diagrams.",
117
- icon: "ph--anchor-simple--regular",
118
- source: "https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-mermaid"
119
- };
120
-
121
- // src/MermaidPlugin.tsx
122
- var MermaidPlugin = () => definePlugin(meta, [
123
- defineModule({
124
- id: `${meta.id}/module/markdown`,
125
- activatesOn: MarkdownEvents.SetupExtensions,
126
- activate: () => contributes(MarkdownCapabilities.Extensions, [
127
- mermaid
128
- ])
129
- })
130
- ]);
131
- export {
132
- MERMAID_PLUGIN,
133
- MermaidPlugin,
134
- meta
135
- };
136
- //# sourceMappingURL=index.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/MermaidPlugin.tsx", "../../../src/extensions/mermaid.ts", "../../../src/meta.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { contributes, defineModule, definePlugin } from '@dxos/app-framework';\nimport { MarkdownCapabilities, MarkdownEvents } from '@dxos/plugin-markdown';\n\nimport { mermaid } from './extensions';\nimport { meta } from './meta';\n\nexport const MermaidPlugin = () =>\n definePlugin(meta, [\n defineModule({\n id: `${meta.id}/module/markdown`,\n activatesOn: MarkdownEvents.SetupExtensions,\n activate: () => contributes(MarkdownCapabilities.Extensions, [mermaid]),\n }),\n ]);\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { syntaxTree } from '@codemirror/language';\nimport {\n type EditorState,\n type Extension,\n type RangeSet,\n RangeSetBuilder,\n StateField,\n type Transaction,\n} from '@codemirror/state';\nimport { Decoration, EditorView, WidgetType } from '@codemirror/view';\nimport _mermaid from 'mermaid';\n\nexport type MermaidOptions = {};\n\nexport const mermaid = (options: MermaidOptions = {}): Extension => {\n return [\n StateField.define<RangeSet<Decoration>>({\n create: (state) => update(state, options),\n update: (_: RangeSet<Decoration>, tr: Transaction) => update(tr.state, options),\n provide: (field) => EditorView.decorations.from(field),\n }),\n styles,\n ];\n};\n\nconst update = (state: EditorState, options: MermaidOptions) => {\n const builder = new RangeSetBuilder<Decoration>();\n syntaxTree(state).iterate({\n enter: (node) => {\n if (node.name === 'FencedCode') {\n const cursor = state.selection.main.head;\n if (state.readOnly || cursor < node.from || cursor > node.to) {\n const info = node.node.getChild('CodeInfo');\n if (info) {\n const type = state.sliceDoc(info.from, info.to);\n const text = node.node.getChild('CodeText');\n if (type === 'mermaid' && text) {\n const content = state.sliceDoc(text.from, text.to);\n // TODO(burdon): Error if extension defined AFTER decorateMarkdown.\n // Decorations that replace line breaks may not be specified via plugins\n builder.add(\n node.from,\n node.to,\n Decoration.replace({\n widget: new MermaidWidget(`mermaid-${node.from}`, content),\n }),\n );\n }\n }\n }\n }\n },\n });\n\n return builder.finish();\n};\n\nclass MermaidWidget extends WidgetType {\n _svg: string | undefined;\n _error: string | undefined;\n\n // TODO(burdon): Mermaid API requires unique id.\n constructor(\n private readonly _id: string,\n private readonly _source: string,\n ) {\n super();\n }\n\n override eq(other: this): boolean {\n return this._source === other._source;\n }\n\n override toDOM(view: EditorView): HTMLDivElement {\n const div = document.createElement('div');\n setTimeout(async () => {\n // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts\n _mermaid.initialize({\n darkMode: view.state.facet(EditorView.darkTheme),\n theme: 'neutral',\n // TODO(burdon): Styles.\n // NOTE: Must specify 'base' in order to override.\n // theme: 'base',\n // themeVariables: {\n // primaryColor: getToken('extend.colors.red.100'),\n // primaryBorderColor: getToken('extend.colors.neutral.200'),\n // },\n // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagrams/flowchart/styles.ts\n // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagrams/sequence/styles.js\n // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagrams/state/styles.js\n // themeCSS: '.node rect { fill: red; }',\n });\n\n // TODO(burdon): Cache?\n const svg = await this.render(div);\n if (this._error) {\n div.className = 'cm-mermaid-error';\n div.innerText = this._error;\n } else {\n div.className = 'cm-mermaid';\n div.innerHTML = svg!;\n\n // const label = document.createElement('span');\n // label.innerText = 'Mermaid';\n // label.className = 'cm-mermaid-label';\n // wrapper.appendChild(label);\n view.requestMeasure();\n }\n });\n\n return div;\n }\n\n async render(container: Element): Promise<string | undefined> {\n try {\n // https://github.com/mermaid-js/mermaid\n const valid = await _mermaid.parse(this._source);\n if (valid) {\n const result = await _mermaid.render(this._id, this._source);\n this._error = undefined;\n this._svg = result.svg;\n return result.svg;\n }\n } catch (err: any) {\n this._error = String(err);\n this._svg = undefined;\n }\n }\n\n override ignoreEvent(e: Event): boolean {\n return !/^mouse/.test(e.type);\n }\n}\n\nconst styles = EditorView.theme({\n '& .cm-mermaid': {\n position: 'relative',\n display: 'inline-flex',\n width: '100%',\n justifyContent: 'center',\n },\n // '& .cm-mermaid-label': {\n // position: 'absolute',\n // right: 0,\n // textSize: 10,\n // },\n '& .cm-mermaid-error': {\n display: 'inline-block',\n color: 'var(--dx-errorText)',\n },\n});\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type PluginMeta } from '@dxos/app-framework';\n\nexport const MERMAID_PLUGIN = 'dxos.org/plugin/mermaid';\n\nexport const meta: PluginMeta = {\n id: MERMAID_PLUGIN,\n name: 'Mermaid',\n description: 'Tool that renders text definitions to create diagrams.',\n icon: 'ph--anchor-simple--regular',\n source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-mermaid',\n};\n"],
5
- "mappings": "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",
6
- "names": ["contributes", "defineModule", "definePlugin", "MarkdownCapabilities", "MarkdownEvents", "syntaxTree", "RangeSetBuilder", "StateField", "Decoration", "EditorView", "WidgetType", "_mermaid", "mermaid", "options", "StateField", "define", "create", "state", "update", "_", "tr", "provide", "field", "EditorView", "decorations", "from", "styles", "builder", "RangeSetBuilder", "syntaxTree", "iterate", "enter", "node", "name", "cursor", "selection", "main", "head", "readOnly", "to", "info", "getChild", "type", "sliceDoc", "text", "content", "add", "Decoration", "replace", "widget", "MermaidWidget", "finish", "WidgetType", "_svg", "_error", "_id", "_source", "eq", "other", "toDOM", "view", "div", "document", "createElement", "setTimeout", "_mermaid", "initialize", "darkMode", "facet", "darkTheme", "theme", "svg", "render", "className", "innerText", "innerHTML", "requestMeasure", "container", "valid", "parse", "result", "undefined", "err", "String", "ignoreEvent", "e", "test", "position", "display", "width", "justifyContent", "color", "MERMAID_PLUGIN", "meta", "id", "name", "description", "icon", "source", "MermaidPlugin", "definePlugin", "meta", "defineModule", "id", "activatesOn", "MarkdownEvents", "SetupExtensions", "activate", "contributes", "MarkdownCapabilities", "Extensions", "mermaid"]
7
- }
@@ -1 +0,0 @@
1
- {"inputs":{"src/extensions/mermaid.ts":{"bytes":15195,"imports":[{"path":"@codemirror/language","kind":"import-statement","external":true},{"path":"@codemirror/state","kind":"import-statement","external":true},{"path":"@codemirror/view","kind":"import-statement","external":true},{"path":"mermaid","kind":"import-statement","external":true}],"format":"esm"},"src/extensions/index.ts":{"bytes":468,"imports":[{"path":"src/extensions/mermaid.ts","kind":"import-statement","original":"./mermaid"}],"format":"esm"},"src/meta.ts":{"bytes":1476,"imports":[],"format":"esm"},"src/MermaidPlugin.tsx":{"bytes":2302,"imports":[{"path":"@dxos/app-framework","kind":"import-statement","external":true},{"path":"@dxos/plugin-markdown","kind":"import-statement","external":true},{"path":"src/extensions/index.ts","kind":"import-statement","original":"./extensions"},{"path":"src/meta.ts","kind":"import-statement","original":"./meta"}],"format":"esm"},"src/index.ts":{"bytes":551,"imports":[{"path":"src/MermaidPlugin.tsx","kind":"import-statement","original":"./MermaidPlugin"},{"path":"src/meta.ts","kind":"import-statement","original":"./meta"}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":9664},"dist/lib/browser/index.mjs":{"imports":[{"path":"@dxos/app-framework","kind":"import-statement","external":true},{"path":"@dxos/plugin-markdown","kind":"import-statement","external":true},{"path":"@codemirror/language","kind":"import-statement","external":true},{"path":"@codemirror/state","kind":"import-statement","external":true},{"path":"@codemirror/view","kind":"import-statement","external":true},{"path":"mermaid","kind":"import-statement","external":true}],"exports":["MERMAID_PLUGIN","MermaidPlugin","meta"],"entryPoint":"src/index.ts","inputs":{"src/MermaidPlugin.tsx":{"bytesInOutput":405},"src/extensions/mermaid.ts":{"bytesInOutput":2906},"src/extensions/index.ts":{"bytesInOutput":0},"src/meta.ts":{"bytesInOutput":299},"src/index.ts":{"bytesInOutput":0}},"bytes":3796}}}
@@ -1,4 +0,0 @@
1
- import { type Extension } from '@codemirror/state';
2
- export type MermaidOptions = {};
3
- export declare const mermaid: (options?: MermaidOptions) => Extension;
4
- //# sourceMappingURL=mermaid.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mermaid.d.ts","sourceRoot":"","sources":["../../../../src/extensions/mermaid.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,SAAS,EAKf,MAAM,mBAAmB,CAAC;AAI3B,MAAM,MAAM,cAAc,GAAG,EAAE,CAAC;AAEhC,eAAO,MAAM,OAAO,GAAI,UAAS,cAAmB,KAAG,SAStD,CAAC"}
@@ -1,155 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- import { syntaxTree } from '@codemirror/language';
6
- import {
7
- type EditorState,
8
- type Extension,
9
- type RangeSet,
10
- RangeSetBuilder,
11
- StateField,
12
- type Transaction,
13
- } from '@codemirror/state';
14
- import { Decoration, EditorView, WidgetType } from '@codemirror/view';
15
- import _mermaid from 'mermaid';
16
-
17
- export type MermaidOptions = {};
18
-
19
- export const mermaid = (options: MermaidOptions = {}): Extension => {
20
- return [
21
- StateField.define<RangeSet<Decoration>>({
22
- create: (state) => update(state, options),
23
- update: (_: RangeSet<Decoration>, tr: Transaction) => update(tr.state, options),
24
- provide: (field) => EditorView.decorations.from(field),
25
- }),
26
- styles,
27
- ];
28
- };
29
-
30
- const update = (state: EditorState, options: MermaidOptions) => {
31
- const builder = new RangeSetBuilder<Decoration>();
32
- syntaxTree(state).iterate({
33
- enter: (node) => {
34
- if (node.name === 'FencedCode') {
35
- const cursor = state.selection.main.head;
36
- if (state.readOnly || cursor < node.from || cursor > node.to) {
37
- const info = node.node.getChild('CodeInfo');
38
- if (info) {
39
- const type = state.sliceDoc(info.from, info.to);
40
- const text = node.node.getChild('CodeText');
41
- if (type === 'mermaid' && text) {
42
- const content = state.sliceDoc(text.from, text.to);
43
- // TODO(burdon): Error if extension defined AFTER decorateMarkdown.
44
- // Decorations that replace line breaks may not be specified via plugins
45
- builder.add(
46
- node.from,
47
- node.to,
48
- Decoration.replace({
49
- widget: new MermaidWidget(`mermaid-${node.from}`, content),
50
- }),
51
- );
52
- }
53
- }
54
- }
55
- }
56
- },
57
- });
58
-
59
- return builder.finish();
60
- };
61
-
62
- class MermaidWidget extends WidgetType {
63
- _svg: string | undefined;
64
- _error: string | undefined;
65
-
66
- // TODO(burdon): Mermaid API requires unique id.
67
- constructor(
68
- private readonly _id: string,
69
- private readonly _source: string,
70
- ) {
71
- super();
72
- }
73
-
74
- override eq(other: this): boolean {
75
- return this._source === other._source;
76
- }
77
-
78
- override toDOM(view: EditorView): HTMLDivElement {
79
- const div = document.createElement('div');
80
- setTimeout(async () => {
81
- // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.type.ts
82
- _mermaid.initialize({
83
- darkMode: view.state.facet(EditorView.darkTheme),
84
- theme: 'neutral',
85
- // TODO(burdon): Styles.
86
- // NOTE: Must specify 'base' in order to override.
87
- // theme: 'base',
88
- // themeVariables: {
89
- // primaryColor: getToken('extend.colors.red.100'),
90
- // primaryBorderColor: getToken('extend.colors.neutral.200'),
91
- // },
92
- // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagrams/flowchart/styles.ts
93
- // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagrams/sequence/styles.js
94
- // https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagrams/state/styles.js
95
- // themeCSS: '.node rect { fill: red; }',
96
- });
97
-
98
- // TODO(burdon): Cache?
99
- const svg = await this.render(div);
100
- if (this._error) {
101
- div.className = 'cm-mermaid-error';
102
- div.innerText = this._error;
103
- } else {
104
- div.className = 'cm-mermaid';
105
- div.innerHTML = svg!;
106
-
107
- // const label = document.createElement('span');
108
- // label.innerText = 'Mermaid';
109
- // label.className = 'cm-mermaid-label';
110
- // wrapper.appendChild(label);
111
- view.requestMeasure();
112
- }
113
- });
114
-
115
- return div;
116
- }
117
-
118
- async render(container: Element): Promise<string | undefined> {
119
- try {
120
- // https://github.com/mermaid-js/mermaid
121
- const valid = await _mermaid.parse(this._source);
122
- if (valid) {
123
- const result = await _mermaid.render(this._id, this._source);
124
- this._error = undefined;
125
- this._svg = result.svg;
126
- return result.svg;
127
- }
128
- } catch (err: any) {
129
- this._error = String(err);
130
- this._svg = undefined;
131
- }
132
- }
133
-
134
- override ignoreEvent(e: Event): boolean {
135
- return !/^mouse/.test(e.type);
136
- }
137
- }
138
-
139
- const styles = EditorView.theme({
140
- '& .cm-mermaid': {
141
- position: 'relative',
142
- display: 'inline-flex',
143
- width: '100%',
144
- justifyContent: 'center',
145
- },
146
- // '& .cm-mermaid-label': {
147
- // position: 'absolute',
148
- // right: 0,
149
- // textSize: 10,
150
- // },
151
- '& .cm-mermaid-error': {
152
- display: 'inline-block',
153
- color: 'var(--dx-errorText)',
154
- },
155
- });