@soroush.tech/markdown 0.1.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/LICENSE +21 -0
- package/README.md +179 -0
- package/dist/CodeBlock-CVlrvVPP.mjs +159 -0
- package/dist/CodeBlock-Cymx1ZAY.cjs +176 -0
- package/dist/CodeBlock.cjs +5 -0
- package/dist/CodeBlock.d.cts +2 -0
- package/dist/CodeBlock.d.mts +2 -0
- package/dist/CodeBlock.mjs +2 -0
- package/dist/Control.cjs +61 -0
- package/dist/Control.d.cts +18 -0
- package/dist/Control.d.mts +18 -0
- package/dist/Control.mjs +60 -0
- package/dist/Editor.cjs +129 -0
- package/dist/Editor.d.cts +40 -0
- package/dist/Editor.d.mts +40 -0
- package/dist/Editor.mjs +128 -0
- package/dist/MarkdownContext.cjs +13 -0
- package/dist/MarkdownContext.d.cts +2 -0
- package/dist/MarkdownContext.d.mts +2 -0
- package/dist/MarkdownContext.mjs +11 -0
- package/dist/Mermaid-BclI9A7e.mjs +231 -0
- package/dist/Mermaid-DqP2Q0bt.cjs +236 -0
- package/dist/Mermaid.cjs +3 -0
- package/dist/Mermaid.d.cts +2 -0
- package/dist/Mermaid.d.mts +2 -0
- package/dist/Mermaid.mjs +2 -0
- package/dist/Preview-BVT70uXa.cjs +276 -0
- package/dist/Preview-C1CwRDj5.mjs +246 -0
- package/dist/Preview.cjs +3 -0
- package/dist/Preview.d.cts +53 -0
- package/dist/Preview.d.mts +53 -0
- package/dist/Preview.mjs +2 -0
- package/dist/Toolbar-Ba3l-oBU.cjs +600 -0
- package/dist/Toolbar-C0SNI-JK.mjs +589 -0
- package/dist/Toolbar.cjs +4 -0
- package/dist/Toolbar.d.cts +13 -0
- package/dist/Toolbar.d.mts +13 -0
- package/dist/Toolbar.mjs +2 -0
- package/dist/applyAction-BDkgYhOd.cjs +120 -0
- package/dist/applyAction-BGWMbUYT.mjs +115 -0
- package/dist/index-BO0LyUUG.d.cts +27 -0
- package/dist/index-BO0LyUUG.d.mts +27 -0
- package/dist/index-BtMTBOcM.d.cts +48 -0
- package/dist/index-BtMTBOcM.d.mts +48 -0
- package/dist/index-rGZIhUgj.d.cts +76 -0
- package/dist/index-rGZIhUgj.d.mts +76 -0
- package/dist/index.cjs +19 -0
- package/dist/index.d.cts +50 -0
- package/dist/index.d.mts +50 -0
- package/dist/index.mjs +8 -0
- package/package.json +110 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
//#region src/utils/applyAction.ts
|
|
2
|
+
const fusesWithMarker = (char) => !/[\s*_~`]/.test(char);
|
|
3
|
+
function stripWrap(action, { value, selectionStart, selectionEnd }) {
|
|
4
|
+
const { prefix, suffix } = action;
|
|
5
|
+
const selected = value.slice(selectionStart, selectionEnd);
|
|
6
|
+
const keep = (content) => content === action.placeholder ? "" : content;
|
|
7
|
+
if (selected.length >= prefix.length + suffix.length && selected.startsWith(prefix) && selected.endsWith(suffix)) {
|
|
8
|
+
const core = keep(selected.slice(prefix.length, selected.length - suffix.length));
|
|
9
|
+
return {
|
|
10
|
+
value: value.slice(0, selectionStart) + core + value.slice(selectionEnd),
|
|
11
|
+
selectionStart,
|
|
12
|
+
selectionEnd: selectionStart + core.length
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (selectionStart >= prefix.length && value.slice(selectionStart - prefix.length, selectionStart) === prefix && value.slice(selectionEnd, selectionEnd + suffix.length) === suffix) {
|
|
16
|
+
const start = selectionStart - prefix.length;
|
|
17
|
+
const core = keep(selected);
|
|
18
|
+
return {
|
|
19
|
+
value: value.slice(0, start) + core + value.slice(selectionEnd + suffix.length),
|
|
20
|
+
selectionStart: start,
|
|
21
|
+
selectionEnd: start + core.length
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function wrapInline(action, { value, selectionStart, selectionEnd }) {
|
|
27
|
+
const selected = value.slice(selectionStart, selectionEnd);
|
|
28
|
+
const leadingLength = selected.length - selected.trimStart().length;
|
|
29
|
+
const trailingLength = selected.length - selected.trimEnd().length;
|
|
30
|
+
const core = selected.slice(leadingLength, selected.length - trailingLength) || action.placeholder;
|
|
31
|
+
let before = selected.slice(0, leadingLength);
|
|
32
|
+
if (!before && selectionStart > 0 && fusesWithMarker(value[selectionStart - 1])) before = " ";
|
|
33
|
+
let after = selected.slice(selected.length - trailingLength);
|
|
34
|
+
if (!after && selectionEnd < value.length && fusesWithMarker(value[selectionEnd])) after = " ";
|
|
35
|
+
const value_ = value.slice(0, selectionStart) + before + action.prefix + core + action.suffix + after + value.slice(selectionEnd);
|
|
36
|
+
const start = selectionStart + before.length + action.prefix.length;
|
|
37
|
+
return {
|
|
38
|
+
value: value_,
|
|
39
|
+
selectionStart: start,
|
|
40
|
+
selectionEnd: start + core.length
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function wrapBlock(action, { value, selectionStart, selectionEnd }) {
|
|
44
|
+
const core = value.slice(selectionStart, selectionEnd) || action.placeholder;
|
|
45
|
+
const before = selectionStart > 0 && value[selectionStart - 1] !== "\n" ? "\n" : "";
|
|
46
|
+
const after = selectionEnd < value.length && value[selectionEnd] !== "\n" ? "\n" : "";
|
|
47
|
+
const value_ = value.slice(0, selectionStart) + before + action.prefix + core + action.suffix + after + value.slice(selectionEnd);
|
|
48
|
+
const start = selectionStart + before.length + action.prefix.length;
|
|
49
|
+
return {
|
|
50
|
+
value: value_,
|
|
51
|
+
selectionStart: start,
|
|
52
|
+
selectionEnd: start + core.length
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function applyWrap(action, selection) {
|
|
56
|
+
if (action.block) return wrapBlock(action, selection);
|
|
57
|
+
return stripWrap(action, selection) ?? wrapInline(action, selection);
|
|
58
|
+
}
|
|
59
|
+
function toggleLinePrefix(action, line) {
|
|
60
|
+
if (!action.family) return action.linePrefix + line;
|
|
61
|
+
const existing = action.family.exec(line)?.[0] ?? "";
|
|
62
|
+
const stripped = line.slice(existing.length);
|
|
63
|
+
if (existing === action.linePrefix && action.toggle !== false) return stripped;
|
|
64
|
+
return action.linePrefix + stripped;
|
|
65
|
+
}
|
|
66
|
+
function applyLinePrefix(action, { value, selectionStart, selectionEnd }) {
|
|
67
|
+
const lineStart = selectionStart === 0 ? 0 : value.lastIndexOf("\n", selectionStart - 1) + 1;
|
|
68
|
+
const nextNewline = value.indexOf("\n", selectionEnd);
|
|
69
|
+
const lineEnd = nextNewline === -1 ? value.length : nextNewline;
|
|
70
|
+
const prefixed = value.slice(lineStart, lineEnd).split("\n").map((line) => toggleLinePrefix(action, line)).join("\n");
|
|
71
|
+
return {
|
|
72
|
+
value: value.slice(0, lineStart) + prefixed + value.slice(lineEnd),
|
|
73
|
+
selectionStart: lineStart,
|
|
74
|
+
selectionEnd: lineStart + prefixed.length
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function fenceEndAfter(value, pos) {
|
|
78
|
+
let offset = 0;
|
|
79
|
+
let openStart = -1;
|
|
80
|
+
for (const line of value.split("\n")) {
|
|
81
|
+
const lineEnd = offset + line.length;
|
|
82
|
+
if (line.startsWith("```")) if (openStart === -1) openStart = offset;
|
|
83
|
+
else {
|
|
84
|
+
if (pos >= openStart && pos <= lineEnd) return lineEnd;
|
|
85
|
+
openStart = -1;
|
|
86
|
+
}
|
|
87
|
+
offset = lineEnd + 1;
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function applyInsert(action, { value, selectionStart, selectionEnd }) {
|
|
92
|
+
const fenceEnd = fenceEndAfter(value, selectionStart);
|
|
93
|
+
const at = fenceEnd ?? selectionEnd;
|
|
94
|
+
const from = fenceEnd ?? selectionStart;
|
|
95
|
+
const value_ = value.slice(0, from) + action.snippet + value.slice(at);
|
|
96
|
+
const caret = from + action.snippet.length;
|
|
97
|
+
return {
|
|
98
|
+
value: value_,
|
|
99
|
+
selectionStart: caret,
|
|
100
|
+
selectionEnd: caret
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Pure transform: applies a toolbar `action` to the given selection and returns the next
|
|
105
|
+
* source plus the selection to restore around the inserted markdown. No DOM access.
|
|
106
|
+
*/
|
|
107
|
+
function applyAction(action, selection) {
|
|
108
|
+
switch (action.kind) {
|
|
109
|
+
case "wrap": return applyWrap(action, selection);
|
|
110
|
+
case "linePrefix": return applyLinePrefix(action, selection);
|
|
111
|
+
case "insert": return applyInsert(action, selection);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
Object.defineProperty(exports, "applyAction", {
|
|
116
|
+
enumerable: true,
|
|
117
|
+
get: function() {
|
|
118
|
+
return applyAction;
|
|
119
|
+
}
|
|
120
|
+
});
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
//#region src/utils/applyAction.ts
|
|
2
|
+
const fusesWithMarker = (char) => !/[\s*_~`]/.test(char);
|
|
3
|
+
function stripWrap(action, { value, selectionStart, selectionEnd }) {
|
|
4
|
+
const { prefix, suffix } = action;
|
|
5
|
+
const selected = value.slice(selectionStart, selectionEnd);
|
|
6
|
+
const keep = (content) => content === action.placeholder ? "" : content;
|
|
7
|
+
if (selected.length >= prefix.length + suffix.length && selected.startsWith(prefix) && selected.endsWith(suffix)) {
|
|
8
|
+
const core = keep(selected.slice(prefix.length, selected.length - suffix.length));
|
|
9
|
+
return {
|
|
10
|
+
value: value.slice(0, selectionStart) + core + value.slice(selectionEnd),
|
|
11
|
+
selectionStart,
|
|
12
|
+
selectionEnd: selectionStart + core.length
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
if (selectionStart >= prefix.length && value.slice(selectionStart - prefix.length, selectionStart) === prefix && value.slice(selectionEnd, selectionEnd + suffix.length) === suffix) {
|
|
16
|
+
const start = selectionStart - prefix.length;
|
|
17
|
+
const core = keep(selected);
|
|
18
|
+
return {
|
|
19
|
+
value: value.slice(0, start) + core + value.slice(selectionEnd + suffix.length),
|
|
20
|
+
selectionStart: start,
|
|
21
|
+
selectionEnd: start + core.length
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
function wrapInline(action, { value, selectionStart, selectionEnd }) {
|
|
27
|
+
const selected = value.slice(selectionStart, selectionEnd);
|
|
28
|
+
const leadingLength = selected.length - selected.trimStart().length;
|
|
29
|
+
const trailingLength = selected.length - selected.trimEnd().length;
|
|
30
|
+
const core = selected.slice(leadingLength, selected.length - trailingLength) || action.placeholder;
|
|
31
|
+
let before = selected.slice(0, leadingLength);
|
|
32
|
+
if (!before && selectionStart > 0 && fusesWithMarker(value[selectionStart - 1])) before = " ";
|
|
33
|
+
let after = selected.slice(selected.length - trailingLength);
|
|
34
|
+
if (!after && selectionEnd < value.length && fusesWithMarker(value[selectionEnd])) after = " ";
|
|
35
|
+
const value_ = value.slice(0, selectionStart) + before + action.prefix + core + action.suffix + after + value.slice(selectionEnd);
|
|
36
|
+
const start = selectionStart + before.length + action.prefix.length;
|
|
37
|
+
return {
|
|
38
|
+
value: value_,
|
|
39
|
+
selectionStart: start,
|
|
40
|
+
selectionEnd: start + core.length
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function wrapBlock(action, { value, selectionStart, selectionEnd }) {
|
|
44
|
+
const core = value.slice(selectionStart, selectionEnd) || action.placeholder;
|
|
45
|
+
const before = selectionStart > 0 && value[selectionStart - 1] !== "\n" ? "\n" : "";
|
|
46
|
+
const after = selectionEnd < value.length && value[selectionEnd] !== "\n" ? "\n" : "";
|
|
47
|
+
const value_ = value.slice(0, selectionStart) + before + action.prefix + core + action.suffix + after + value.slice(selectionEnd);
|
|
48
|
+
const start = selectionStart + before.length + action.prefix.length;
|
|
49
|
+
return {
|
|
50
|
+
value: value_,
|
|
51
|
+
selectionStart: start,
|
|
52
|
+
selectionEnd: start + core.length
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function applyWrap(action, selection) {
|
|
56
|
+
if (action.block) return wrapBlock(action, selection);
|
|
57
|
+
return stripWrap(action, selection) ?? wrapInline(action, selection);
|
|
58
|
+
}
|
|
59
|
+
function toggleLinePrefix(action, line) {
|
|
60
|
+
if (!action.family) return action.linePrefix + line;
|
|
61
|
+
const existing = action.family.exec(line)?.[0] ?? "";
|
|
62
|
+
const stripped = line.slice(existing.length);
|
|
63
|
+
if (existing === action.linePrefix && action.toggle !== false) return stripped;
|
|
64
|
+
return action.linePrefix + stripped;
|
|
65
|
+
}
|
|
66
|
+
function applyLinePrefix(action, { value, selectionStart, selectionEnd }) {
|
|
67
|
+
const lineStart = selectionStart === 0 ? 0 : value.lastIndexOf("\n", selectionStart - 1) + 1;
|
|
68
|
+
const nextNewline = value.indexOf("\n", selectionEnd);
|
|
69
|
+
const lineEnd = nextNewline === -1 ? value.length : nextNewline;
|
|
70
|
+
const prefixed = value.slice(lineStart, lineEnd).split("\n").map((line) => toggleLinePrefix(action, line)).join("\n");
|
|
71
|
+
return {
|
|
72
|
+
value: value.slice(0, lineStart) + prefixed + value.slice(lineEnd),
|
|
73
|
+
selectionStart: lineStart,
|
|
74
|
+
selectionEnd: lineStart + prefixed.length
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function fenceEndAfter(value, pos) {
|
|
78
|
+
let offset = 0;
|
|
79
|
+
let openStart = -1;
|
|
80
|
+
for (const line of value.split("\n")) {
|
|
81
|
+
const lineEnd = offset + line.length;
|
|
82
|
+
if (line.startsWith("```")) if (openStart === -1) openStart = offset;
|
|
83
|
+
else {
|
|
84
|
+
if (pos >= openStart && pos <= lineEnd) return lineEnd;
|
|
85
|
+
openStart = -1;
|
|
86
|
+
}
|
|
87
|
+
offset = lineEnd + 1;
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function applyInsert(action, { value, selectionStart, selectionEnd }) {
|
|
92
|
+
const fenceEnd = fenceEndAfter(value, selectionStart);
|
|
93
|
+
const at = fenceEnd ?? selectionEnd;
|
|
94
|
+
const from = fenceEnd ?? selectionStart;
|
|
95
|
+
const value_ = value.slice(0, from) + action.snippet + value.slice(at);
|
|
96
|
+
const caret = from + action.snippet.length;
|
|
97
|
+
return {
|
|
98
|
+
value: value_,
|
|
99
|
+
selectionStart: caret,
|
|
100
|
+
selectionEnd: caret
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Pure transform: applies a toolbar `action` to the given selection and returns the next
|
|
105
|
+
* source plus the selection to restore around the inserted markdown. No DOM access.
|
|
106
|
+
*/
|
|
107
|
+
function applyAction(action, selection) {
|
|
108
|
+
switch (action.kind) {
|
|
109
|
+
case "wrap": return applyWrap(action, selection);
|
|
110
|
+
case "linePrefix": return applyLinePrefix(action, selection);
|
|
111
|
+
case "insert": return applyInsert(action, selection);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { applyAction as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/Mermaid/DiagramViewer.d.ts
|
|
2
|
+
interface DiagramViewerProps {
|
|
3
|
+
/** The rendered mermaid SVG markup. */
|
|
4
|
+
svg: string;
|
|
5
|
+
/** Show the expand-to-fullscreen control and dialog. Off for the nested (in-dialog) viewer. */
|
|
6
|
+
expandable?: boolean;
|
|
7
|
+
/** Fill the parent's height — used by the viewer inside the fullscreen dialog. */
|
|
8
|
+
fill?: boolean;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/Mermaid/Mermaid.d.ts
|
|
12
|
+
/** DiagramViewer props a consumer may set — `svg` and `fill` are managed internally. */
|
|
13
|
+
type DiagramProps = Omit<DiagramViewerProps, 'svg' | 'fill'>;
|
|
14
|
+
interface MermaidProps {
|
|
15
|
+
/** The mermaid diagram source — the body of a ` ```mermaid ` fenced block. */
|
|
16
|
+
chart: string;
|
|
17
|
+
/** Props forwarded to the diagram's zoom/pan viewer (e.g. `expandable`). */
|
|
18
|
+
diagram?: DiagramProps;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders a mermaid diagram. Until the client renders the SVG — and if the source is
|
|
22
|
+
* invalid — it falls back to the diagram source in a `CodeBlock`, so server output and
|
|
23
|
+
* no-JS readers still show something useful and hydration stays stable.
|
|
24
|
+
*/
|
|
25
|
+
declare function Mermaid({ chart, diagram }: Readonly<MermaidProps>): import("react").JSX.Element;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { Mermaid as n, MermaidProps as r, DiagramProps as t };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/Mermaid/DiagramViewer.d.ts
|
|
2
|
+
interface DiagramViewerProps {
|
|
3
|
+
/** The rendered mermaid SVG markup. */
|
|
4
|
+
svg: string;
|
|
5
|
+
/** Show the expand-to-fullscreen control and dialog. Off for the nested (in-dialog) viewer. */
|
|
6
|
+
expandable?: boolean;
|
|
7
|
+
/** Fill the parent's height — used by the viewer inside the fullscreen dialog. */
|
|
8
|
+
fill?: boolean;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/Mermaid/Mermaid.d.ts
|
|
12
|
+
/** DiagramViewer props a consumer may set — `svg` and `fill` are managed internally. */
|
|
13
|
+
type DiagramProps = Omit<DiagramViewerProps, 'svg' | 'fill'>;
|
|
14
|
+
interface MermaidProps {
|
|
15
|
+
/** The mermaid diagram source — the body of a ` ```mermaid ` fenced block. */
|
|
16
|
+
chart: string;
|
|
17
|
+
/** Props forwarded to the diagram's zoom/pan viewer (e.g. `expandable`). */
|
|
18
|
+
diagram?: DiagramProps;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders a mermaid diagram. Until the client renders the SVG — and if the source is
|
|
22
|
+
* invalid — it falls back to the diagram source in a `CodeBlock`, so server output and
|
|
23
|
+
* no-JS readers still show something useful and hydration stays stable.
|
|
24
|
+
*/
|
|
25
|
+
declare function Mermaid({ chart, diagram }: Readonly<MermaidProps>): import("react").JSX.Element;
|
|
26
|
+
//#endregion
|
|
27
|
+
export { Mermaid as n, MermaidProps as r, DiagramProps as t };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { ViewProps } from "@soroush.tech/design-system/View";
|
|
3
|
+
//#region src/CodeBlock/CodeBlock.d.ts
|
|
4
|
+
interface CodeBlockProps extends ViewProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Fenced-code block: a horizontally scrollable, syntax-highlighted surface with a
|
|
9
|
+
* copy-to-clipboard button that sticks to the top-right while the block is in view.
|
|
10
|
+
*/
|
|
11
|
+
declare function CodeBlock({ children, ...rest }: Readonly<CodeBlockProps>): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/CodeBlock/CodeBlock.data.d.ts
|
|
14
|
+
/**
|
|
15
|
+
* Syntax-highlighting tokens for `CodeBlock` — mapped onto highlight.js token classes.
|
|
16
|
+
* Not part of design-system's own scales; `../index.ts` augments
|
|
17
|
+
* `@soroush.tech/design-system/theme` so `theme.syntax` is available wherever this
|
|
18
|
+
* package is imported. Merge one of the presets below into your theme via
|
|
19
|
+
* `createTheme(baseTheme, { syntax: syntaxDark })`, or supply your own.
|
|
20
|
+
*/
|
|
21
|
+
interface ThemeSyntax {
|
|
22
|
+
/** Default code text — plain identifiers, operators, punctuation. */
|
|
23
|
+
base: string;
|
|
24
|
+
/** Keywords, built-ins, types, literals, selector tags. */
|
|
25
|
+
keyword: string;
|
|
26
|
+
/** Strings, template literals, regular expressions. */
|
|
27
|
+
string: string;
|
|
28
|
+
/** Numbers, symbols, links. */
|
|
29
|
+
number: string;
|
|
30
|
+
/** Function / class titles, section headings, attributes. */
|
|
31
|
+
title: string;
|
|
32
|
+
/** Fields, constants, and property keys. */
|
|
33
|
+
constant: string;
|
|
34
|
+
/** Type and class names. */
|
|
35
|
+
type: string;
|
|
36
|
+
/** Comments and quotes — rendered dimmed and italic. */
|
|
37
|
+
comment: string;
|
|
38
|
+
/** Markup tags/names, meta, variables, deletions. */
|
|
39
|
+
tag: string;
|
|
40
|
+
/** Font family for the code surface — independent of `theme.fonts.mono`. */
|
|
41
|
+
font: string;
|
|
42
|
+
}
|
|
43
|
+
/** Matched to the JetBrains "Islands Dark" editor scheme. */
|
|
44
|
+
declare const syntaxDark: ThemeSyntax;
|
|
45
|
+
/** Matched to the JetBrains "Islands Light" editor scheme. */
|
|
46
|
+
declare const syntaxLight: ThemeSyntax;
|
|
47
|
+
//#endregion
|
|
48
|
+
export { CodeBlockProps as a, CodeBlock as i, syntaxDark as n, syntaxLight as r, ThemeSyntax as t };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { ViewProps } from "@soroush.tech/design-system/View";
|
|
3
|
+
//#region src/CodeBlock/CodeBlock.d.ts
|
|
4
|
+
interface CodeBlockProps extends ViewProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Fenced-code block: a horizontally scrollable, syntax-highlighted surface with a
|
|
9
|
+
* copy-to-clipboard button that sticks to the top-right while the block is in view.
|
|
10
|
+
*/
|
|
11
|
+
declare function CodeBlock({ children, ...rest }: Readonly<CodeBlockProps>): import("react").JSX.Element;
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/CodeBlock/CodeBlock.data.d.ts
|
|
14
|
+
/**
|
|
15
|
+
* Syntax-highlighting tokens for `CodeBlock` — mapped onto highlight.js token classes.
|
|
16
|
+
* Not part of design-system's own scales; `../index.ts` augments
|
|
17
|
+
* `@soroush.tech/design-system/theme` so `theme.syntax` is available wherever this
|
|
18
|
+
* package is imported. Merge one of the presets below into your theme via
|
|
19
|
+
* `createTheme(baseTheme, { syntax: syntaxDark })`, or supply your own.
|
|
20
|
+
*/
|
|
21
|
+
interface ThemeSyntax {
|
|
22
|
+
/** Default code text — plain identifiers, operators, punctuation. */
|
|
23
|
+
base: string;
|
|
24
|
+
/** Keywords, built-ins, types, literals, selector tags. */
|
|
25
|
+
keyword: string;
|
|
26
|
+
/** Strings, template literals, regular expressions. */
|
|
27
|
+
string: string;
|
|
28
|
+
/** Numbers, symbols, links. */
|
|
29
|
+
number: string;
|
|
30
|
+
/** Function / class titles, section headings, attributes. */
|
|
31
|
+
title: string;
|
|
32
|
+
/** Fields, constants, and property keys. */
|
|
33
|
+
constant: string;
|
|
34
|
+
/** Type and class names. */
|
|
35
|
+
type: string;
|
|
36
|
+
/** Comments and quotes — rendered dimmed and italic. */
|
|
37
|
+
comment: string;
|
|
38
|
+
/** Markup tags/names, meta, variables, deletions. */
|
|
39
|
+
tag: string;
|
|
40
|
+
/** Font family for the code surface — independent of `theme.fonts.mono`. */
|
|
41
|
+
font: string;
|
|
42
|
+
}
|
|
43
|
+
/** Matched to the JetBrains "Islands Dark" editor scheme. */
|
|
44
|
+
declare const syntaxDark: ThemeSyntax;
|
|
45
|
+
/** Matched to the JetBrains "Islands Light" editor scheme. */
|
|
46
|
+
declare const syntaxLight: ThemeSyntax;
|
|
47
|
+
//#endregion
|
|
48
|
+
export { CodeBlockProps as a, CodeBlock as i, syntaxDark as n, syntaxLight as r, ThemeSyntax as t };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { IconName } from "@soroush.tech/design-system/Icon";
|
|
2
|
+
//#region src/const.d.ts
|
|
3
|
+
/** How a text label is rendered — mirrors the mark it inserts. */
|
|
4
|
+
type ToolbarLabelEmphasis = 'bold' | 'italic' | 'strike';
|
|
5
|
+
/** Shared presentation for a toolbar control. */
|
|
6
|
+
interface BaseAction {
|
|
7
|
+
id: string;
|
|
8
|
+
/** Text label shown when no `icon` is set. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Accessible name — always the control's aria-label. */
|
|
11
|
+
ariaLabel: string;
|
|
12
|
+
/** Registry icon shown instead of the text label. */
|
|
13
|
+
icon?: IconName;
|
|
14
|
+
/** Styles the text label to mirror the mark (e.g. bold `B`). Ignored when `icon` is set. */
|
|
15
|
+
emphasis?: ToolbarLabelEmphasis;
|
|
16
|
+
/** Consecutive actions sharing a group id render as one joined button cluster. */
|
|
17
|
+
group?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Wraps the selection (or a placeholder) in a leading/trailing marker — bold, links, code blocks. */
|
|
20
|
+
interface WrapAction extends BaseAction {
|
|
21
|
+
kind: 'wrap';
|
|
22
|
+
prefix: string;
|
|
23
|
+
suffix: string;
|
|
24
|
+
placeholder: string;
|
|
25
|
+
/** Block-level fence (e.g. code block): separated by newlines and never toggled off. */
|
|
26
|
+
block?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Prepends a marker to every line the selection touches — headings, quotes, lists. */
|
|
29
|
+
interface LinePrefixAction extends BaseAction {
|
|
30
|
+
kind: 'linePrefix';
|
|
31
|
+
linePrefix: string;
|
|
32
|
+
/**
|
|
33
|
+
* Line-start pattern for a family of mutually-exclusive markers (e.g. all list types). When
|
|
34
|
+
* set, applying the action strips any matching marker first, then toggles its own off or
|
|
35
|
+
* replaces a sibling's — so the list/ordered/task buttons swap and toggle instead of stacking.
|
|
36
|
+
*/
|
|
37
|
+
family?: RegExp;
|
|
38
|
+
/**
|
|
39
|
+
* Whether re-applying an action that already owns the line's marker removes it. Defaults to
|
|
40
|
+
* toggling off; set `false` for replace-only families (e.g. heading levels from a select,
|
|
41
|
+
* where picking a level should set it, not toggle it away).
|
|
42
|
+
*/
|
|
43
|
+
toggle?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Inserts a standalone snippet at the caret, ignoring the selection — tables, rules. */
|
|
46
|
+
interface InsertAction extends BaseAction {
|
|
47
|
+
kind: 'insert';
|
|
48
|
+
snippet: string;
|
|
49
|
+
}
|
|
50
|
+
type ToolbarAction = WrapAction | LinePrefixAction | InsertAction;
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/MarkdownContext/MarkdownContext.d.ts
|
|
53
|
+
/** A textarea selection range shared between the Editor and the Toolbar. */
|
|
54
|
+
interface MarkdownSelection {
|
|
55
|
+
start: number;
|
|
56
|
+
end: number;
|
|
57
|
+
}
|
|
58
|
+
interface MarkdownContextValue {
|
|
59
|
+
/** Current markdown source. */
|
|
60
|
+
value: string;
|
|
61
|
+
/** Called with the next source on edit or a toolbar action. */
|
|
62
|
+
onChange: (value: string) => void;
|
|
63
|
+
/** Applies a toolbar action at the last remembered selection and queues the caret to restore. */
|
|
64
|
+
dispatch: (action: ToolbarAction) => void;
|
|
65
|
+
/** Records the current textarea selection — the Editor calls this on select/blur. */
|
|
66
|
+
rememberSelection: (selection: MarkdownSelection) => void;
|
|
67
|
+
/** Queues a selection to restore after the next value change (e.g. after Tab). */
|
|
68
|
+
queueSelection: (selection: MarkdownSelection) => void;
|
|
69
|
+
/** Returns and clears the queued selection — the Editor's effect calls this to restore focus. */
|
|
70
|
+
takeQueuedSelection: () => MarkdownSelection | null;
|
|
71
|
+
}
|
|
72
|
+
declare const MarkdownContext: import("react").Context<MarkdownContextValue | null>;
|
|
73
|
+
/** Reads the Markdown compound context; throws if used outside `<Markdown.Control>`. */
|
|
74
|
+
declare function useMarkdownContext(): MarkdownContextValue;
|
|
75
|
+
//#endregion
|
|
76
|
+
export { useMarkdownContext as i, MarkdownContextValue as n, MarkdownSelection as r, MarkdownContext as t };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { IconName } from "@soroush.tech/design-system/Icon";
|
|
2
|
+
//#region src/const.d.ts
|
|
3
|
+
/** How a text label is rendered — mirrors the mark it inserts. */
|
|
4
|
+
type ToolbarLabelEmphasis = 'bold' | 'italic' | 'strike';
|
|
5
|
+
/** Shared presentation for a toolbar control. */
|
|
6
|
+
interface BaseAction {
|
|
7
|
+
id: string;
|
|
8
|
+
/** Text label shown when no `icon` is set. */
|
|
9
|
+
label: string;
|
|
10
|
+
/** Accessible name — always the control's aria-label. */
|
|
11
|
+
ariaLabel: string;
|
|
12
|
+
/** Registry icon shown instead of the text label. */
|
|
13
|
+
icon?: IconName;
|
|
14
|
+
/** Styles the text label to mirror the mark (e.g. bold `B`). Ignored when `icon` is set. */
|
|
15
|
+
emphasis?: ToolbarLabelEmphasis;
|
|
16
|
+
/** Consecutive actions sharing a group id render as one joined button cluster. */
|
|
17
|
+
group?: string;
|
|
18
|
+
}
|
|
19
|
+
/** Wraps the selection (or a placeholder) in a leading/trailing marker — bold, links, code blocks. */
|
|
20
|
+
interface WrapAction extends BaseAction {
|
|
21
|
+
kind: 'wrap';
|
|
22
|
+
prefix: string;
|
|
23
|
+
suffix: string;
|
|
24
|
+
placeholder: string;
|
|
25
|
+
/** Block-level fence (e.g. code block): separated by newlines and never toggled off. */
|
|
26
|
+
block?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** Prepends a marker to every line the selection touches — headings, quotes, lists. */
|
|
29
|
+
interface LinePrefixAction extends BaseAction {
|
|
30
|
+
kind: 'linePrefix';
|
|
31
|
+
linePrefix: string;
|
|
32
|
+
/**
|
|
33
|
+
* Line-start pattern for a family of mutually-exclusive markers (e.g. all list types). When
|
|
34
|
+
* set, applying the action strips any matching marker first, then toggles its own off or
|
|
35
|
+
* replaces a sibling's — so the list/ordered/task buttons swap and toggle instead of stacking.
|
|
36
|
+
*/
|
|
37
|
+
family?: RegExp;
|
|
38
|
+
/**
|
|
39
|
+
* Whether re-applying an action that already owns the line's marker removes it. Defaults to
|
|
40
|
+
* toggling off; set `false` for replace-only families (e.g. heading levels from a select,
|
|
41
|
+
* where picking a level should set it, not toggle it away).
|
|
42
|
+
*/
|
|
43
|
+
toggle?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Inserts a standalone snippet at the caret, ignoring the selection — tables, rules. */
|
|
46
|
+
interface InsertAction extends BaseAction {
|
|
47
|
+
kind: 'insert';
|
|
48
|
+
snippet: string;
|
|
49
|
+
}
|
|
50
|
+
type ToolbarAction = WrapAction | LinePrefixAction | InsertAction;
|
|
51
|
+
//#endregion
|
|
52
|
+
//#region src/MarkdownContext/MarkdownContext.d.ts
|
|
53
|
+
/** A textarea selection range shared between the Editor and the Toolbar. */
|
|
54
|
+
interface MarkdownSelection {
|
|
55
|
+
start: number;
|
|
56
|
+
end: number;
|
|
57
|
+
}
|
|
58
|
+
interface MarkdownContextValue {
|
|
59
|
+
/** Current markdown source. */
|
|
60
|
+
value: string;
|
|
61
|
+
/** Called with the next source on edit or a toolbar action. */
|
|
62
|
+
onChange: (value: string) => void;
|
|
63
|
+
/** Applies a toolbar action at the last remembered selection and queues the caret to restore. */
|
|
64
|
+
dispatch: (action: ToolbarAction) => void;
|
|
65
|
+
/** Records the current textarea selection — the Editor calls this on select/blur. */
|
|
66
|
+
rememberSelection: (selection: MarkdownSelection) => void;
|
|
67
|
+
/** Queues a selection to restore after the next value change (e.g. after Tab). */
|
|
68
|
+
queueSelection: (selection: MarkdownSelection) => void;
|
|
69
|
+
/** Returns and clears the queued selection — the Editor's effect calls this to restore focus. */
|
|
70
|
+
takeQueuedSelection: () => MarkdownSelection | null;
|
|
71
|
+
}
|
|
72
|
+
declare const MarkdownContext: import("react").Context<MarkdownContextValue | null>;
|
|
73
|
+
/** Reads the Markdown compound context; throws if used outside `<Markdown.Control>`. */
|
|
74
|
+
declare function useMarkdownContext(): MarkdownContextValue;
|
|
75
|
+
//#endregion
|
|
76
|
+
export { useMarkdownContext as i, MarkdownContextValue as n, MarkdownSelection as r, MarkdownContext as t };
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_Preview = require("./Preview-BVT70uXa.cjs");
|
|
3
|
+
const require_MarkdownContext = require("./MarkdownContext.cjs");
|
|
4
|
+
const require_Control = require("./Control.cjs");
|
|
5
|
+
const require_Toolbar = require("./Toolbar-Ba3l-oBU.cjs");
|
|
6
|
+
const require_Editor = require("./Editor.cjs");
|
|
7
|
+
const require_CodeBlock = require("./CodeBlock-Cymx1ZAY.cjs");
|
|
8
|
+
const require_Mermaid = require("./Mermaid-DqP2Q0bt.cjs");
|
|
9
|
+
exports.CodeBlock = require_CodeBlock.CodeBlock;
|
|
10
|
+
exports.Control = require_Control.Control;
|
|
11
|
+
exports.Editor = require_Editor.Editor;
|
|
12
|
+
exports.MarkdownContext = require_MarkdownContext.MarkdownContext;
|
|
13
|
+
exports.Mermaid = require_Mermaid.Mermaid;
|
|
14
|
+
exports.Preview = require_Preview.Preview;
|
|
15
|
+
exports.TablePicker = require_Toolbar.TablePicker;
|
|
16
|
+
exports.Toolbar = require_Toolbar.Toolbar;
|
|
17
|
+
exports.syntaxDark = require_CodeBlock.syntaxDark;
|
|
18
|
+
exports.syntaxLight = require_CodeBlock.syntaxLight;
|
|
19
|
+
exports.useMarkdownContext = require_MarkdownContext.useMarkdownContext;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { a as CodeBlockProps, i as CodeBlock, n as syntaxDark, r as syntaxLight, t as ThemeSyntax } from "./index-BtMTBOcM.cjs";
|
|
2
|
+
import { Control, ControlProps } from "./Control.cjs";
|
|
3
|
+
import { Editor, EditorProps } from "./Editor.cjs";
|
|
4
|
+
import { i as useMarkdownContext, n as MarkdownContextValue, r as MarkdownSelection, t as MarkdownContext } from "./index-rGZIhUgj.cjs";
|
|
5
|
+
import { n as Mermaid, r as MermaidProps, t as DiagramProps } from "./index-BO0LyUUG.cjs";
|
|
6
|
+
import { Preview, PreviewProps, PreviewSlotProps } from "./Preview.cjs";
|
|
7
|
+
import { TablePicker, TablePickerProps, Toolbar } from "./Toolbar.cjs";
|
|
8
|
+
//#region src/index.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Per-theme overrides for the `Mermaid` renderer, merged over (and winning against) its default
|
|
11
|
+
* mermaid `themeVariables`. Common variables are listed for autocomplete; any other mermaid theme
|
|
12
|
+
* variable is accepted. Set via `theme.mermaid` (e.g. `createTheme(baseTheme, { mermaid: … })`).
|
|
13
|
+
*/
|
|
14
|
+
interface MermaidThemeVariables {
|
|
15
|
+
darkMode?: boolean;
|
|
16
|
+
background?: string;
|
|
17
|
+
fontFamily?: string;
|
|
18
|
+
fontSize?: string;
|
|
19
|
+
primaryColor?: string;
|
|
20
|
+
primaryTextColor?: string;
|
|
21
|
+
primaryBorderColor?: string;
|
|
22
|
+
secondaryColor?: string;
|
|
23
|
+
tertiaryColor?: string;
|
|
24
|
+
lineColor?: string;
|
|
25
|
+
textColor?: string;
|
|
26
|
+
mainBkg?: string;
|
|
27
|
+
noteBkgColor?: string;
|
|
28
|
+
noteTextColor?: string;
|
|
29
|
+
[variable: string]: string | number | boolean | undefined;
|
|
30
|
+
}
|
|
31
|
+
declare module '@soroush.tech/design-system/theme' {
|
|
32
|
+
interface ThemeComponents {
|
|
33
|
+
MarkdownEditor?: import('@soroush.tech/design-system/theme').ComponentConfig;
|
|
34
|
+
MarkdownPreview?: import('@soroush.tech/design-system/theme').ComponentConfig;
|
|
35
|
+
MarkdownToolbar?: import('@soroush.tech/design-system/theme').ComponentConfig<Record<string, unknown>, 'root' | 'strike' | 'tablePickerCell'>;
|
|
36
|
+
CodeBlock?: import('@soroush.tech/design-system/theme').ComponentConfig<Record<string, unknown>, 'root' | 'surface'>;
|
|
37
|
+
}
|
|
38
|
+
interface Theme {
|
|
39
|
+
/** Per-theme overrides for the `Mermaid` renderer's mermaid `themeVariables`. */
|
|
40
|
+
mermaid?: MermaidThemeVariables;
|
|
41
|
+
/**
|
|
42
|
+
* Syntax-highlighting tokens for `CodeBlock` — see `syntaxDark`/`syntaxLight`. Optional
|
|
43
|
+
* only so `design-system`'s own `baseTheme` literal still satisfies `Theme` in this
|
|
44
|
+
* monorepo's source-consuming builds; `CodeBlock` requires it in practice (no fallback).
|
|
45
|
+
*/
|
|
46
|
+
syntax?: ThemeSyntax;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { CodeBlock, CodeBlockProps, Control, ControlProps, DiagramProps, Editor, EditorProps, MarkdownContext, MarkdownContextValue, MarkdownSelection, Mermaid, MermaidProps, MermaidThemeVariables, Preview, PreviewProps, PreviewSlotProps, TablePicker, TablePickerProps, ThemeSyntax, Toolbar, syntaxDark, syntaxLight, useMarkdownContext };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { a as CodeBlockProps, i as CodeBlock, n as syntaxDark, r as syntaxLight, t as ThemeSyntax } from "./index-BtMTBOcM.mjs";
|
|
2
|
+
import { Control, ControlProps } from "./Control.mjs";
|
|
3
|
+
import { Editor, EditorProps } from "./Editor.mjs";
|
|
4
|
+
import { i as useMarkdownContext, n as MarkdownContextValue, r as MarkdownSelection, t as MarkdownContext } from "./index-rGZIhUgj.mjs";
|
|
5
|
+
import { n as Mermaid, r as MermaidProps, t as DiagramProps } from "./index-BO0LyUUG.mjs";
|
|
6
|
+
import { Preview, PreviewProps, PreviewSlotProps } from "./Preview.mjs";
|
|
7
|
+
import { TablePicker, TablePickerProps, Toolbar } from "./Toolbar.mjs";
|
|
8
|
+
//#region src/index.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Per-theme overrides for the `Mermaid` renderer, merged over (and winning against) its default
|
|
11
|
+
* mermaid `themeVariables`. Common variables are listed for autocomplete; any other mermaid theme
|
|
12
|
+
* variable is accepted. Set via `theme.mermaid` (e.g. `createTheme(baseTheme, { mermaid: … })`).
|
|
13
|
+
*/
|
|
14
|
+
interface MermaidThemeVariables {
|
|
15
|
+
darkMode?: boolean;
|
|
16
|
+
background?: string;
|
|
17
|
+
fontFamily?: string;
|
|
18
|
+
fontSize?: string;
|
|
19
|
+
primaryColor?: string;
|
|
20
|
+
primaryTextColor?: string;
|
|
21
|
+
primaryBorderColor?: string;
|
|
22
|
+
secondaryColor?: string;
|
|
23
|
+
tertiaryColor?: string;
|
|
24
|
+
lineColor?: string;
|
|
25
|
+
textColor?: string;
|
|
26
|
+
mainBkg?: string;
|
|
27
|
+
noteBkgColor?: string;
|
|
28
|
+
noteTextColor?: string;
|
|
29
|
+
[variable: string]: string | number | boolean | undefined;
|
|
30
|
+
}
|
|
31
|
+
declare module '@soroush.tech/design-system/theme' {
|
|
32
|
+
interface ThemeComponents {
|
|
33
|
+
MarkdownEditor?: import('@soroush.tech/design-system/theme').ComponentConfig;
|
|
34
|
+
MarkdownPreview?: import('@soroush.tech/design-system/theme').ComponentConfig;
|
|
35
|
+
MarkdownToolbar?: import('@soroush.tech/design-system/theme').ComponentConfig<Record<string, unknown>, 'root' | 'strike' | 'tablePickerCell'>;
|
|
36
|
+
CodeBlock?: import('@soroush.tech/design-system/theme').ComponentConfig<Record<string, unknown>, 'root' | 'surface'>;
|
|
37
|
+
}
|
|
38
|
+
interface Theme {
|
|
39
|
+
/** Per-theme overrides for the `Mermaid` renderer's mermaid `themeVariables`. */
|
|
40
|
+
mermaid?: MermaidThemeVariables;
|
|
41
|
+
/**
|
|
42
|
+
* Syntax-highlighting tokens for `CodeBlock` — see `syntaxDark`/`syntaxLight`. Optional
|
|
43
|
+
* only so `design-system`'s own `baseTheme` literal still satisfies `Theme` in this
|
|
44
|
+
* monorepo's source-consuming builds; `CodeBlock` requires it in practice (no fallback).
|
|
45
|
+
*/
|
|
46
|
+
syntax?: ThemeSyntax;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { CodeBlock, CodeBlockProps, Control, ControlProps, DiagramProps, Editor, EditorProps, MarkdownContext, MarkdownContextValue, MarkdownSelection, Mermaid, MermaidProps, MermaidThemeVariables, Preview, PreviewProps, PreviewSlotProps, TablePicker, TablePickerProps, ThemeSyntax, Toolbar, syntaxDark, syntaxLight, useMarkdownContext };
|