@openstage/glyph-core 0.2.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/dist/api.d.ts +156 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +38 -0
- package/dist/api.js.map +1 -0
- package/dist/brand.d.ts +34 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +22 -0
- package/dist/brand.js.map +1 -0
- package/dist/commands.d.ts +24 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/commands.js +78 -0
- package/dist/commands.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/languages.d.ts +11 -0
- package/dist/languages.d.ts.map +1 -0
- package/dist/languages.js +21 -0
- package/dist/languages.js.map +1 -0
- package/dist/migrate.d.ts +12 -0
- package/dist/migrate.d.ts.map +1 -0
- package/dist/migrate.js +30 -0
- package/dist/migrate.js.map +1 -0
- package/dist/nodes.d.ts +70 -0
- package/dist/nodes.d.ts.map +1 -0
- package/dist/nodes.js +96 -0
- package/dist/nodes.js.map +1 -0
- package/dist/schema.d.ts +28 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +50 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +88 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
package/dist/api.d.ts
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { CommandId } from './brand.js';
|
|
2
|
+
import type { EditorDocument } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Imperative command surface — the same object passed to slash commands and
|
|
5
|
+
* returned by `editor.getApi()`. Engine-agnostic by design (no Tiptap types).
|
|
6
|
+
* All mutating methods act on the current selection and are no-ops if nothing
|
|
7
|
+
* is editable yet.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const api = editor.getApi();
|
|
12
|
+
* api.toggleBold();
|
|
13
|
+
* api.setHeading(2);
|
|
14
|
+
* api.setLink('https://example.com');
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export interface EditorApi {
|
|
18
|
+
getJSON(): EditorDocument;
|
|
19
|
+
setContent(document: EditorDocument): void;
|
|
20
|
+
focus(): void;
|
|
21
|
+
setHeading(level: 1 | 2 | 3): void;
|
|
22
|
+
setParagraph(): void;
|
|
23
|
+
toggleBold(): void;
|
|
24
|
+
toggleItalic(): void;
|
|
25
|
+
toggleBulletList(): void;
|
|
26
|
+
toggleOrderedList(): void;
|
|
27
|
+
toggleBlockquote(): void;
|
|
28
|
+
toggleCodeBlock(): void;
|
|
29
|
+
setLink(href: string): void;
|
|
30
|
+
undo(): void;
|
|
31
|
+
redo(): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A slash-menu entry. `keywords` widen fuzzy matching; `run` performs the
|
|
35
|
+
* action via the {@link EditorApi}.
|
|
36
|
+
*/
|
|
37
|
+
export type SlashCommand = {
|
|
38
|
+
/** Stable unique id (brand a string with `CommandId.of`). */
|
|
39
|
+
id: CommandId;
|
|
40
|
+
/** Text shown in the menu. */
|
|
41
|
+
label: string;
|
|
42
|
+
/** Extra search terms (e.g. `['h1', 'title']`). */
|
|
43
|
+
keywords?: string[];
|
|
44
|
+
/** Invoked when the item is chosen. */
|
|
45
|
+
run: (editor: EditorApi) => void;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Color tokens. Every key maps to a CSS custom property on the element (see
|
|
49
|
+
* {@link themeToCssVars}); unset keys keep the built-in light defaults. Assign
|
|
50
|
+
* to `editor.theme`.
|
|
51
|
+
*
|
|
52
|
+
* @example `editor.theme = { accent: '#2563eb', background: '#0b0b0b', text: '#eee' }`
|
|
53
|
+
*/
|
|
54
|
+
export type EditorTheme = {
|
|
55
|
+
background?: string;
|
|
56
|
+
text?: string;
|
|
57
|
+
mutedText?: string;
|
|
58
|
+
border?: string;
|
|
59
|
+
accent?: string;
|
|
60
|
+
selection?: string;
|
|
61
|
+
toolbarBackground?: string;
|
|
62
|
+
slashMenuBackground?: string;
|
|
63
|
+
slashMenuHover?: string;
|
|
64
|
+
slashMenuText?: string;
|
|
65
|
+
codeBackground?: string;
|
|
66
|
+
blockQuoteBorder?: string;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Identifiers for the built-in toolbar controls. `spacer` pushes the rest to
|
|
70
|
+
* the right; `status` is the save-status text; `codeLanguage` is the language
|
|
71
|
+
* picker (auto-hidden unless the caret is in a code block).
|
|
72
|
+
*/
|
|
73
|
+
export type ToolbarItemId = 'bold' | 'italic' | 'link' | 'heading1' | 'heading2' | 'heading3' | 'bulletList' | 'orderedList' | 'blockquote' | 'codeBlock' | 'codeLanguage' | 'undo' | 'redo' | 'spacer' | 'status';
|
|
74
|
+
/** Default toolbar layout when `config.toolbar` is not provided. */
|
|
75
|
+
export declare const DEFAULT_TOOLBAR: readonly ToolbarItemId[];
|
|
76
|
+
/**
|
|
77
|
+
* A custom toolbar glyph. A string is used as a plain text label; a Node is
|
|
78
|
+
* cloned per render; a factory is called with the owner document and must
|
|
79
|
+
* return a fresh Node. Nodes/factories keep rendering framework-agnostic and
|
|
80
|
+
* XSS-safe (the host builds the element, we never parse HTML strings).
|
|
81
|
+
*/
|
|
82
|
+
export type ToolbarIcon = string | Node | ((document: Document) => Node);
|
|
83
|
+
/**
|
|
84
|
+
* Behaviour/layout configuration assigned to `editor.config`. Assigning
|
|
85
|
+
* rebuilds the editor instance (content is preserved), so set it once per
|
|
86
|
+
* mount rather than per keystroke.
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```ts
|
|
90
|
+
* editor.config = {
|
|
91
|
+
* showHeader: true,
|
|
92
|
+
* toolbar: ['bold', 'italic', 'link', 'spacer', 'status'],
|
|
93
|
+
* icons: { bold: (d) => myIcon(d, 'bold') },
|
|
94
|
+
* };
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
export type EditorConfig = {
|
|
98
|
+
/** Show the built-in toolbar. Default `true`. Set `false` for headless use. */
|
|
99
|
+
showHeader?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* Keep the toolbar pinned while the document scrolls (CSS
|
|
102
|
+
* `position: sticky`). Default `true`. Set `false` for a toolbar that
|
|
103
|
+
* scrolls away with the content.
|
|
104
|
+
*
|
|
105
|
+
* Note: a sticky header only visibly floats when the editor is a bounded
|
|
106
|
+
* scroll region — set {@link maxHeight} (or constrain the element via CSS).
|
|
107
|
+
*/
|
|
108
|
+
floatingHeader?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Bound the editor's height and let its content scroll internally. This is
|
|
111
|
+
* what makes {@link floatingHeader} actually pin without the consumer adding
|
|
112
|
+
* any CSS. A number is treated as pixels; a string is used verbatim
|
|
113
|
+
* (e.g. `'70vh'`, `'480px'`). Omit for an editor that grows with content.
|
|
114
|
+
*/
|
|
115
|
+
maxHeight?: string | number;
|
|
116
|
+
/**
|
|
117
|
+
* Draw the editor's outer border. Default `true`. Set `false` for a
|
|
118
|
+
* seamless/borderless embed (only the outer frame border is removed;
|
|
119
|
+
* internal dividers and the theme are unaffected).
|
|
120
|
+
*/
|
|
121
|
+
bordered?: boolean;
|
|
122
|
+
/** Enable the `/` slash-command menu. Default `true`. */
|
|
123
|
+
enableSlashCommands?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Pick and order the built-in toolbar controls. Omit an id to hide it.
|
|
126
|
+
* Defaults to DEFAULT_TOOLBAR. Ignored when showHeader is false.
|
|
127
|
+
*/
|
|
128
|
+
toolbar?: readonly ToolbarItemId[];
|
|
129
|
+
/**
|
|
130
|
+
* Override the visible glyph for individual toolbar buttons. The accessible
|
|
131
|
+
* name/tooltip (title + aria-label) is kept from the built-in definition.
|
|
132
|
+
*/
|
|
133
|
+
icons?: Partial<Record<ToolbarItemId, ToolbarIcon>>;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Maps each emitted event name to its `CustomEvent.detail` type. Events bubble
|
|
137
|
+
* and are `composed` (cross Shadow DOM).
|
|
138
|
+
*
|
|
139
|
+
* @example
|
|
140
|
+
* ```ts
|
|
141
|
+
* editor.addEventListener('content-change', (e) => {
|
|
142
|
+
* const doc = (e as CustomEvent<EditorDocument>).detail;
|
|
143
|
+
* save(doc);
|
|
144
|
+
* });
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export type EditorEventMap = {
|
|
148
|
+
'content-change': EditorDocument;
|
|
149
|
+
'selection-change': void;
|
|
150
|
+
ready: void;
|
|
151
|
+
focus: void;
|
|
152
|
+
blur: void;
|
|
153
|
+
};
|
|
154
|
+
/** Maps an EditorTheme onto the CSS custom properties the element consumes. */
|
|
155
|
+
export declare const themeToCssVars: (theme: EditorTheme) => Record<string, string>;
|
|
156
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/api.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Default toolbar layout when `config.toolbar` is not provided. */
|
|
2
|
+
export const DEFAULT_TOOLBAR = [
|
|
3
|
+
'bold',
|
|
4
|
+
'italic',
|
|
5
|
+
'link',
|
|
6
|
+
'heading1',
|
|
7
|
+
'heading2',
|
|
8
|
+
'heading3',
|
|
9
|
+
'bulletList',
|
|
10
|
+
'orderedList',
|
|
11
|
+
'blockquote',
|
|
12
|
+
'codeBlock',
|
|
13
|
+
'undo',
|
|
14
|
+
'redo',
|
|
15
|
+
'spacer',
|
|
16
|
+
'codeLanguage',
|
|
17
|
+
'status',
|
|
18
|
+
];
|
|
19
|
+
const THEME_VAR_MAP = {
|
|
20
|
+
background: '--editor-background',
|
|
21
|
+
text: '--editor-text',
|
|
22
|
+
mutedText: '--editor-muted-text',
|
|
23
|
+
border: '--editor-border',
|
|
24
|
+
accent: '--editor-accent',
|
|
25
|
+
selection: '--editor-selection',
|
|
26
|
+
toolbarBackground: '--editor-toolbar-background',
|
|
27
|
+
slashMenuBackground: '--editor-slash-menu-background',
|
|
28
|
+
slashMenuHover: '--editor-slash-menu-hover',
|
|
29
|
+
slashMenuText: '--editor-slash-menu-text',
|
|
30
|
+
codeBackground: '--editor-code-background',
|
|
31
|
+
blockQuoteBorder: '--editor-block-quote-border',
|
|
32
|
+
};
|
|
33
|
+
/** Maps an EditorTheme onto the CSS custom properties the element consumes. */
|
|
34
|
+
export const themeToCssVars = (theme) => Object.keys(THEME_VAR_MAP).reduce((vars, key) => {
|
|
35
|
+
const value = theme[key];
|
|
36
|
+
return typeof value === 'string' ? { ...vars, [THEME_VAR_MAP[key]]: value } : vars;
|
|
37
|
+
}, {});
|
|
38
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AA6FA,oEAAoE;AACpE,MAAM,CAAC,MAAM,eAAe,GAA6B;IACvD,MAAM;IACN,QAAQ;IACR,MAAM;IACN,UAAU;IACV,UAAU;IACV,UAAU;IACV,YAAY;IACZ,aAAa;IACb,YAAY;IACZ,WAAW;IACX,MAAM;IACN,MAAM;IACN,QAAQ;IACR,cAAc;IACd,QAAQ;CACT,CAAC;AAmFF,MAAM,aAAa,GAAgD;IACjE,UAAU,EAAE,qBAAqB;IACjC,IAAI,EAAE,eAAe;IACrB,SAAS,EAAE,qBAAqB;IAChC,MAAM,EAAE,iBAAiB;IACzB,MAAM,EAAE,iBAAiB;IACzB,SAAS,EAAE,oBAAoB;IAC/B,iBAAiB,EAAE,6BAA6B;IAChD,mBAAmB,EAAE,gCAAgC;IACrD,cAAc,EAAE,2BAA2B;IAC3C,aAAa,EAAE,0BAA0B;IACzC,cAAc,EAAE,0BAA0B;IAC1C,gBAAgB,EAAE,6BAA6B;CAChD,CAAC;AAEF,+EAA+E;AAC/E,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAkB,EAA0B,EAAE,CAC1E,MAAM,CAAC,IAAI,CAAC,aAAa,CAA2B,CAAC,MAAM,CAC1D,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;IACZ,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACrF,CAAC,EACD,EAAE,CACH,CAAC"}
|
package/dist/brand.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nominal (branded) primitive types — distinct at compile time, plain strings
|
|
3
|
+
* at runtime. Construct with the matching `.of()` helper.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* const href = Href.of('https://example.com'); // Href, not just string
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
declare const __brand: unique symbol;
|
|
11
|
+
/** Attach a compile-time brand `B` to a base type `T`. */
|
|
12
|
+
export type Brand<T, B extends string> = T & {
|
|
13
|
+
readonly [__brand]: B;
|
|
14
|
+
};
|
|
15
|
+
/** A link target (the `href` of a link mark). */
|
|
16
|
+
export type Href = Brand<string, 'Href'>;
|
|
17
|
+
/** Constructs an {@link Href} from a string. */
|
|
18
|
+
export declare const Href: {
|
|
19
|
+
of: (value: string) => Href;
|
|
20
|
+
};
|
|
21
|
+
/** A code-block language id (e.g. `"typescript"`); see `supportedCodeLanguages`. */
|
|
22
|
+
export type Language = Brand<string, 'Language'>;
|
|
23
|
+
/** Constructs a {@link Language} from a string. */
|
|
24
|
+
export declare const Language: {
|
|
25
|
+
of: (value: string) => Language;
|
|
26
|
+
};
|
|
27
|
+
/** A slash-command identifier. */
|
|
28
|
+
export type CommandId = Brand<string, 'CommandId'>;
|
|
29
|
+
/** Constructs a {@link CommandId} from a string. */
|
|
30
|
+
export declare const CommandId: {
|
|
31
|
+
of: (value: string) => CommandId;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
34
|
+
//# sourceMappingURL=brand.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand.d.ts","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,CAAC,MAAM,OAAO,EAAE,OAAO,MAAM,CAAC;AAErC,0DAA0D;AAC1D,MAAM,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,IAAI,CAAC,GAAG;IAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;CAAE,CAAC;AAEvE,iDAAiD;AACjD,MAAM,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACzC,gDAAgD;AAChD,eAAO,MAAM,IAAI;gBACH,MAAM,KAAG,IAAI;CAC1B,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACjD,mDAAmD;AACnD,eAAO,MAAM,QAAQ;gBACP,MAAM,KAAG,QAAQ;CAC9B,CAAC;AAEF,kCAAkC;AAClC,MAAM,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AACnD,oDAAoD;AACpD,eAAO,MAAM,SAAS;gBACR,MAAM,KAAG,SAAS;CAC/B,CAAC"}
|
package/dist/brand.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nominal (branded) primitive types — distinct at compile time, plain strings
|
|
3
|
+
* at runtime. Construct with the matching `.of()` helper.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* const href = Href.of('https://example.com'); // Href, not just string
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
/** Constructs an {@link Href} from a string. */
|
|
11
|
+
export const Href = {
|
|
12
|
+
of: (value) => value,
|
|
13
|
+
};
|
|
14
|
+
/** Constructs a {@link Language} from a string. */
|
|
15
|
+
export const Language = {
|
|
16
|
+
of: (value) => value,
|
|
17
|
+
};
|
|
18
|
+
/** Constructs a {@link CommandId} from a string. */
|
|
19
|
+
export const CommandId = {
|
|
20
|
+
of: (value) => value,
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=brand.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brand.js","sourceRoot":"","sources":["../src/brand.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,gDAAgD;AAChD,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,EAAE,EAAE,CAAC,KAAa,EAAQ,EAAE,CAAC,KAAa;CAC3C,CAAC;AAIF,mDAAmD;AACnD,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,EAAE,EAAE,CAAC,KAAa,EAAY,EAAE,CAAC,KAAiB;CACnD,CAAC;AAIF,oDAAoD;AACpD,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,EAAE,EAAE,CAAC,KAAa,EAAa,EAAE,CAAC,KAAkB;CACrD,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { SlashCommand } from './api.js';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in slash-menu commands (headings, paragraph, lists, quote, code).
|
|
4
|
+
* Assign your own array to `editor.commands` to replace or extend; each
|
|
5
|
+
* command's `run` receives the {@link EditorApi}.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { defaultSlashCommands, CommandId } from '@openstage/glyph-core';
|
|
10
|
+
* editor.commands = [
|
|
11
|
+
* ...defaultSlashCommands,
|
|
12
|
+
* { id: CommandId.of('clear'), label: 'Clear', run: (api) => api.setParagraph() },
|
|
13
|
+
* ];
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare const defaultSlashCommands: readonly SlashCommand[];
|
|
17
|
+
/**
|
|
18
|
+
* Curried, case-insensitive filter over command label and keywords. An empty
|
|
19
|
+
* query returns a copy of all commands.
|
|
20
|
+
*
|
|
21
|
+
* @example `filterSlashCommands('head')(editor.commands)`
|
|
22
|
+
*/
|
|
23
|
+
export declare const filterSlashCommands: (query: string) => (commands: readonly SlashCommand[]) => SlashCommand[];
|
|
24
|
+
//# sourceMappingURL=commands.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAG7C;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,YAAY,EAiDvD,CAAC;AAQF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC7B,OAAO,MAAM,MACb,UAAU,SAAS,YAAY,EAAE,KAAG,YAAY,EAGhD,CAAC"}
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { CommandId } from './brand.js';
|
|
2
|
+
/**
|
|
3
|
+
* Built-in slash-menu commands (headings, paragraph, lists, quote, code).
|
|
4
|
+
* Assign your own array to `editor.commands` to replace or extend; each
|
|
5
|
+
* command's `run` receives the {@link EditorApi}.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { defaultSlashCommands, CommandId } from '@openstage/glyph-core';
|
|
10
|
+
* editor.commands = [
|
|
11
|
+
* ...defaultSlashCommands,
|
|
12
|
+
* { id: CommandId.of('clear'), label: 'Clear', run: (api) => api.setParagraph() },
|
|
13
|
+
* ];
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export const defaultSlashCommands = [
|
|
17
|
+
{
|
|
18
|
+
id: CommandId.of('heading-1'),
|
|
19
|
+
label: 'Heading 1',
|
|
20
|
+
keywords: ['h1', 'title'],
|
|
21
|
+
run: (e) => e.setHeading(1),
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
id: CommandId.of('heading-2'),
|
|
25
|
+
label: 'Heading 2',
|
|
26
|
+
keywords: ['h2'],
|
|
27
|
+
run: (e) => e.setHeading(2),
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
id: CommandId.of('heading-3'),
|
|
31
|
+
label: 'Heading 3',
|
|
32
|
+
keywords: ['h3'],
|
|
33
|
+
run: (e) => e.setHeading(3),
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: CommandId.of('paragraph'),
|
|
37
|
+
label: 'Paragraph',
|
|
38
|
+
keywords: ['text', 'body'],
|
|
39
|
+
run: (e) => e.setParagraph(),
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
id: CommandId.of('bullet-list'),
|
|
43
|
+
label: 'Bullet list',
|
|
44
|
+
keywords: ['ul', 'unordered'],
|
|
45
|
+
run: (e) => e.toggleBulletList(),
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: CommandId.of('numbered-list'),
|
|
49
|
+
label: 'Numbered list',
|
|
50
|
+
keywords: ['ol', 'ordered'],
|
|
51
|
+
run: (e) => e.toggleOrderedList(),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: CommandId.of('quote'),
|
|
55
|
+
label: 'Quote',
|
|
56
|
+
keywords: ['blockquote'],
|
|
57
|
+
run: (e) => e.toggleBlockquote(),
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
id: CommandId.of('code-block'),
|
|
61
|
+
label: 'Code block',
|
|
62
|
+
keywords: ['pre', 'code'],
|
|
63
|
+
run: (e) => e.toggleCodeBlock(),
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
const matches = (q) => (c) => c.label.toLowerCase().includes(q) ||
|
|
67
|
+
(c.keywords ?? []).some((k) => k.toLowerCase().includes(q));
|
|
68
|
+
/**
|
|
69
|
+
* Curried, case-insensitive filter over command label and keywords. An empty
|
|
70
|
+
* query returns a copy of all commands.
|
|
71
|
+
*
|
|
72
|
+
* @example `filterSlashCommands('head')(editor.commands)`
|
|
73
|
+
*/
|
|
74
|
+
export const filterSlashCommands = (query) => (commands) => {
|
|
75
|
+
const q = query.trim().toLowerCase();
|
|
76
|
+
return q ? commands.filter(matches(q)) : [...commands];
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@openstage/glyph-core` — the engine-agnostic core: the document model
|
|
3
|
+
* ({@link EditorDocument}), smart constructors (`./nodes`), validation
|
|
4
|
+
* ({@link isEditorDocument}), migration ({@link migrate}), branded types,
|
|
5
|
+
* and the public config/command types shared with the editor element.
|
|
6
|
+
*
|
|
7
|
+
* Has no DOM or editor-engine dependency; safe to use on a server to build,
|
|
8
|
+
* validate, or migrate documents.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { document, heading, paragraph, plain, isEditorDocument } from '@openstage/glyph-core';
|
|
13
|
+
* const doc = document(heading(1)(plain('Title')), paragraph(plain('Body')));
|
|
14
|
+
* isEditorDocument(doc); // true
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
export * from './brand.js';
|
|
20
|
+
export * from './types.js';
|
|
21
|
+
export * from './schema.js';
|
|
22
|
+
export * from './migrate.js';
|
|
23
|
+
export * from './api.js';
|
|
24
|
+
export * from './commands.js';
|
|
25
|
+
export * from './languages.js';
|
|
26
|
+
export * from './nodes.js';
|
|
27
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@openstage/glyph-core` — the engine-agnostic core: the document model
|
|
3
|
+
* ({@link EditorDocument}), smart constructors (`./nodes`), validation
|
|
4
|
+
* ({@link isEditorDocument}), migration ({@link migrate}), branded types,
|
|
5
|
+
* and the public config/command types shared with the editor element.
|
|
6
|
+
*
|
|
7
|
+
* Has no DOM or editor-engine dependency; safe to use on a server to build,
|
|
8
|
+
* validate, or migrate documents.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* import { document, heading, paragraph, plain, isEditorDocument } from '@openstage/glyph-core';
|
|
13
|
+
* const doc = document(heading(1)(plain('Title')), paragraph(plain('Body')));
|
|
14
|
+
* isEditorDocument(doc); // true
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @packageDocumentation
|
|
18
|
+
*/
|
|
19
|
+
export * from './brand.js';
|
|
20
|
+
export * from './types.js';
|
|
21
|
+
export * from './schema.js';
|
|
22
|
+
export * from './migrate.js';
|
|
23
|
+
export * from './api.js';
|
|
24
|
+
export * from './commands.js';
|
|
25
|
+
export * from './languages.js';
|
|
26
|
+
export * from './nodes.js';
|
|
27
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAc,YAAY,CAAC;AAC3B,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,UAAU,CAAC;AACzB,cAAc,eAAe,CAAC;AAC9B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical code-block language set. The `id` values must match the languages
|
|
3
|
+
* the renderer's highlighter registers so a block authored in the editor
|
|
4
|
+
* highlights consistently in the read-only view.
|
|
5
|
+
*/
|
|
6
|
+
export type CodeLanguage = {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly label: string;
|
|
9
|
+
};
|
|
10
|
+
export declare const supportedCodeLanguages: readonly CodeLanguage[];
|
|
11
|
+
//# sourceMappingURL=languages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.d.ts","sourceRoot":"","sources":["../src/languages.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3E,eAAO,MAAM,sBAAsB,EAAE,SAAS,YAAY,EAmBzD,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export const supportedCodeLanguages = [
|
|
2
|
+
{ id: 'bash', label: 'Bash' },
|
|
3
|
+
{ id: 'csharp', label: 'C#' },
|
|
4
|
+
{ id: 'css', label: 'CSS' },
|
|
5
|
+
{ id: 'fsharp', label: 'F#' },
|
|
6
|
+
{ id: 'go', label: 'Go' },
|
|
7
|
+
{ id: 'haskell', label: 'Haskell' },
|
|
8
|
+
{ id: 'java', label: 'Java' },
|
|
9
|
+
{ id: 'javascript', label: 'JavaScript' },
|
|
10
|
+
{ id: 'json', label: 'JSON' },
|
|
11
|
+
{ id: 'kotlin', label: 'Kotlin' },
|
|
12
|
+
{ id: 'markdown', label: 'Markdown' },
|
|
13
|
+
{ id: 'ocaml', label: 'OCaml' },
|
|
14
|
+
{ id: 'python', label: 'Python' },
|
|
15
|
+
{ id: 'rust', label: 'Rust' },
|
|
16
|
+
{ id: 'scala', label: 'Scala' },
|
|
17
|
+
{ id: 'sql', label: 'SQL' },
|
|
18
|
+
{ id: 'typescript', label: 'TypeScript' },
|
|
19
|
+
{ id: 'xml', label: 'HTML / XML' },
|
|
20
|
+
];
|
|
21
|
+
//# sourceMappingURL=languages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"languages.js","sourceRoot":"","sources":["../src/languages.ts"],"names":[],"mappings":"AAOA,MAAM,CAAC,MAAM,sBAAsB,GAA4B;IAC7D,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAC7B,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;IAC7B,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;IAC3B,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE;IAC7B,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IACzB,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACnC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAC7B,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;IACzC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAC7B,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACjC,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE;IACrC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;IAC/B,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACjC,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAC7B,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;IAC/B,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE;IAC3B,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;IACzC,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE;CACnC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EditorDocument } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Upgrades a document to the current {@link SCHEMA_VERSION}. Call this on any
|
|
4
|
+
* document loaded from storage before using it; it is the identity for
|
|
5
|
+
* current-version documents.
|
|
6
|
+
*
|
|
7
|
+
* @param document - A structurally valid document (see {@link isEditorDocument}).
|
|
8
|
+
* @returns The document at the current schema version.
|
|
9
|
+
* @throws RangeError if the document's `schemaVersion` is newer than supported.
|
|
10
|
+
*/
|
|
11
|
+
export declare const migrate: (document: EditorDocument) => EditorDocument;
|
|
12
|
+
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AA4BjD;;;;;;;;GAQG;AACH,eAAO,MAAM,OAAO,GAAI,UAAU,cAAc,KAAG,cAGpC,CAAC"}
|
package/dist/migrate.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Left, Right } from 'monadyssey';
|
|
2
|
+
import { SCHEMA_VERSION } from './schema.js';
|
|
3
|
+
// Ordered upgrade steps keyed by the version they migrate FROM. Empty today
|
|
4
|
+
// (only schema v1 exists); future bumps add a step here and nothing else.
|
|
5
|
+
const steps = new Map();
|
|
6
|
+
const applyFrom = (acc) => {
|
|
7
|
+
if (acc.schemaVersion >= SCHEMA_VERSION) {
|
|
8
|
+
return acc.schemaVersion === SCHEMA_VERSION ? acc : { ...acc, schemaVersion: SCHEMA_VERSION };
|
|
9
|
+
}
|
|
10
|
+
const step = steps.get(acc.schemaVersion);
|
|
11
|
+
return applyFrom(step ? step(acc) : { ...acc, schemaVersion: acc.schemaVersion + 1 });
|
|
12
|
+
};
|
|
13
|
+
// The only failure mode is a document newer than we support; modeled as Either
|
|
14
|
+
// internally and re-thrown as RangeError at the public edge.
|
|
15
|
+
const ensureSupported = (document) => document.schemaVersion > SCHEMA_VERSION
|
|
16
|
+
? Left.pure(new RangeError(`Document schemaVersion ${document.schemaVersion} is newer than supported ${SCHEMA_VERSION}`))
|
|
17
|
+
: Right.pure(document);
|
|
18
|
+
/**
|
|
19
|
+
* Upgrades a document to the current {@link SCHEMA_VERSION}. Call this on any
|
|
20
|
+
* document loaded from storage before using it; it is the identity for
|
|
21
|
+
* current-version documents.
|
|
22
|
+
*
|
|
23
|
+
* @param document - A structurally valid document (see {@link isEditorDocument}).
|
|
24
|
+
* @returns The document at the current schema version.
|
|
25
|
+
* @throws RangeError if the document's `schemaVersion` is newer than supported.
|
|
26
|
+
*/
|
|
27
|
+
export const migrate = (document) => ensureSupported(document).fold((error) => {
|
|
28
|
+
throw error;
|
|
29
|
+
}, applyFrom);
|
|
30
|
+
//# sourceMappingURL=migrate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.js","sourceRoot":"","sources":["../src/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAI7C,4EAA4E;AAC5E,0EAA0E;AAC1E,MAAM,KAAK,GAAuC,IAAI,GAAG,EAAE,CAAC;AAE5D,MAAM,SAAS,GAAG,CAAC,GAAmB,EAAkB,EAAE;IACxD,IAAI,GAAG,CAAC,aAAa,IAAI,cAAc,EAAE,CAAC;QACxC,OAAO,GAAG,CAAC,aAAa,KAAK,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;IAChG,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC1C,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,aAAa,EAAE,GAAG,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC,CAAC;AACxF,CAAC,CAAC;AAEF,+EAA+E;AAC/E,6DAA6D;AAC7D,MAAM,eAAe,GAAG,CAAC,QAAwB,EAAsC,EAAE,CACvF,QAAQ,CAAC,aAAa,GAAG,cAAc;IACrC,CAAC,CAAC,IAAI,CAAC,IAAI,CACP,IAAI,UAAU,CACZ,0BAA0B,QAAQ,CAAC,aAAa,4BAA4B,cAAc,EAAE,CAC7F,CACF;IACH,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAE3B;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,QAAwB,EAAkB,EAAE,CAClE,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;IACvC,MAAM,KAAK,CAAC;AACd,CAAC,EAAE,SAAS,CAAC,CAAC"}
|
package/dist/nodes.d.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { BulletListNode, CodeBlockNode, EditorContent, EditorDocument, EditorNode, HeadingNode, ListItemNode, NumberedListNode, ParagraphNode, QuoteNode, TextMark, TextNode } from './types.js';
|
|
2
|
+
import { Href, Language } from './brand.js';
|
|
3
|
+
/**
|
|
4
|
+
* Smart constructors for the document model. Prefer these over object literals:
|
|
5
|
+
* they are pure, correctly typed, brand string fields (href/language), and
|
|
6
|
+
* curry where a node has a configuration argument.
|
|
7
|
+
*
|
|
8
|
+
* @example Build a full document
|
|
9
|
+
* ```ts
|
|
10
|
+
* import {
|
|
11
|
+
* document, heading, paragraph, plain, text, bold, link,
|
|
12
|
+
* bulletList, listItem, codeBlock,
|
|
13
|
+
* } from '@openstage/glyph-core';
|
|
14
|
+
*
|
|
15
|
+
* const doc = document(
|
|
16
|
+
* heading(1)(plain('Welcome')),
|
|
17
|
+
* paragraph(plain('Hello '), text(bold)('world'), plain('.')),
|
|
18
|
+
* paragraph(text(link('https://example.com'))('a link')),
|
|
19
|
+
* bulletList(listItem(paragraph(plain('item one')))),
|
|
20
|
+
* codeBlock('typescript')('const x = 1;'),
|
|
21
|
+
* );
|
|
22
|
+
* editor.setContent(doc);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
/** Bold inline mark. Pass to {@link text}: `text(bold)('hi')`. */
|
|
26
|
+
export declare const bold: TextMark;
|
|
27
|
+
/** Italic inline mark. Pass to {@link text}: `text(italic)('hi')`. */
|
|
28
|
+
export declare const italic: TextMark;
|
|
29
|
+
/** Link inline mark. The href is branded; pass a raw string. */
|
|
30
|
+
export declare const link: (href: string | Href) => TextMark;
|
|
31
|
+
/**
|
|
32
|
+
* Curried text-node builder: apply marks first, then the string.
|
|
33
|
+
*
|
|
34
|
+
* @example `text(bold, italic)('important')` · `plain('plain text')`
|
|
35
|
+
*/
|
|
36
|
+
export declare const text: (...marks: TextMark[]) => (value: string) => TextNode;
|
|
37
|
+
/** Unmarked text node — `plain('hi')` is `text()('hi')`. */
|
|
38
|
+
export declare const plain: (value: string) => TextNode;
|
|
39
|
+
/** Paragraph block from inline {@link TextNode}s. */
|
|
40
|
+
export declare const paragraph: (...content: TextNode[]) => ParagraphNode;
|
|
41
|
+
/**
|
|
42
|
+
* Curried heading builder: choose the level (1–3), then the inline content.
|
|
43
|
+
*
|
|
44
|
+
* @example `heading(2)(plain('Section'))`
|
|
45
|
+
*/
|
|
46
|
+
export declare const heading: (level: 1 | 2 | 3) => (...content: TextNode[]) => HeadingNode;
|
|
47
|
+
/** A single list entry; wrap paragraphs for {@link bulletList}/{@link orderedList}. */
|
|
48
|
+
export declare const listItem: (...content: ParagraphNode[]) => ListItemNode;
|
|
49
|
+
/** Unordered list of {@link listItem}s. */
|
|
50
|
+
export declare const bulletList: (...content: ListItemNode[]) => BulletListNode;
|
|
51
|
+
/** Ordered (numbered) list of {@link listItem}s. */
|
|
52
|
+
export declare const orderedList: (...content: ListItemNode[]) => NumberedListNode;
|
|
53
|
+
/** Block quote containing one or more paragraphs. */
|
|
54
|
+
export declare const blockquote: (...content: ParagraphNode[]) => QuoteNode;
|
|
55
|
+
/**
|
|
56
|
+
* Curried code-block builder: optional language first, then the raw source.
|
|
57
|
+
* The language is branded and should match a renderer-supported id for
|
|
58
|
+
* highlighting (see `supportedCodeLanguages`).
|
|
59
|
+
*
|
|
60
|
+
* @example `codeBlock('rust')('fn main() {}')` · `codeBlock()('plain text')`
|
|
61
|
+
*/
|
|
62
|
+
export declare const codeBlock: (language?: string | Language) => (code: string) => CodeBlockNode;
|
|
63
|
+
/** Document root from top-level block nodes (no version envelope). */
|
|
64
|
+
export declare const doc: (...content: EditorNode[]) => EditorContent;
|
|
65
|
+
/**
|
|
66
|
+
* A complete {@link EditorDocument} (root + current schema version). This is
|
|
67
|
+
* the value you pass to `editor.setContent` or the renderer.
|
|
68
|
+
*/
|
|
69
|
+
export declare const document: (...content: EditorNode[]) => EditorDocument;
|
|
70
|
+
//# sourceMappingURL=nodes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,aAAa,EACb,cAAc,EACd,UAAU,EACV,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,QAAQ,EACR,QAAQ,EACT,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG5C;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,kEAAkE;AAClE,eAAO,MAAM,IAAI,EAAE,QAA2B,CAAC;AAE/C,sEAAsE;AACtE,eAAO,MAAM,MAAM,EAAE,QAA6B,CAAC;AAEnD,gEAAgE;AAChE,eAAO,MAAM,IAAI,GAAI,MAAM,MAAM,GAAG,IAAI,KAAG,QAGzC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,IAAI,GACd,GAAG,OAAO,QAAQ,EAAE,MACpB,OAAO,MAAM,KAAG,QACwE,CAAC;AAE5F,4DAA4D;AAC5D,eAAO,MAAM,KAAK,UAJR,MAAM,KAAG,QAIQ,CAAC;AAE5B,qDAAqD;AACrD,eAAO,MAAM,SAAS,GAAI,GAAG,SAAS,QAAQ,EAAE,KAAG,aAC0B,CAAC;AAE9E;;;;GAIG;AACH,eAAO,MAAM,OAAO,GACjB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAChB,GAAG,SAAS,QAAQ,EAAE,KAAG,WAIxB,CAAC;AAEL,uFAAuF;AACvF,eAAO,MAAM,QAAQ,GAAI,GAAG,SAAS,aAAa,EAAE,KAAG,YAGrD,CAAC;AAEH,2CAA2C;AAC3C,eAAO,MAAM,UAAU,GAAI,GAAG,SAAS,YAAY,EAAE,KAAG,cAGtD,CAAC;AAEH,oDAAoD;AACpD,eAAO,MAAM,WAAW,GAAI,GAAG,SAAS,YAAY,EAAE,KAAG,gBAGvD,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,UAAU,GAAI,GAAG,SAAS,aAAa,EAAE,KAAG,SAGvD,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GACnB,WAAW,MAAM,GAAG,QAAQ,MAC5B,MAAM,MAAM,KAAG,aAId,CAAC;AAEL,sEAAsE;AACtE,eAAO,MAAM,GAAG,GAAI,GAAG,SAAS,UAAU,EAAE,KAAG,aAA2C,CAAC;AAE3F;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,GAAG,SAAS,UAAU,EAAE,KAAG,cAGlD,CAAC"}
|
package/dist/nodes.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Href, Language } from './brand.js';
|
|
2
|
+
import { SCHEMA_VERSION } from './schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Smart constructors for the document model. Prefer these over object literals:
|
|
5
|
+
* they are pure, correctly typed, brand string fields (href/language), and
|
|
6
|
+
* curry where a node has a configuration argument.
|
|
7
|
+
*
|
|
8
|
+
* @example Build a full document
|
|
9
|
+
* ```ts
|
|
10
|
+
* import {
|
|
11
|
+
* document, heading, paragraph, plain, text, bold, link,
|
|
12
|
+
* bulletList, listItem, codeBlock,
|
|
13
|
+
* } from '@openstage/glyph-core';
|
|
14
|
+
*
|
|
15
|
+
* const doc = document(
|
|
16
|
+
* heading(1)(plain('Welcome')),
|
|
17
|
+
* paragraph(plain('Hello '), text(bold)('world'), plain('.')),
|
|
18
|
+
* paragraph(text(link('https://example.com'))('a link')),
|
|
19
|
+
* bulletList(listItem(paragraph(plain('item one')))),
|
|
20
|
+
* codeBlock('typescript')('const x = 1;'),
|
|
21
|
+
* );
|
|
22
|
+
* editor.setContent(doc);
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
/** Bold inline mark. Pass to {@link text}: `text(bold)('hi')`. */
|
|
26
|
+
export const bold = { type: 'bold' };
|
|
27
|
+
/** Italic inline mark. Pass to {@link text}: `text(italic)('hi')`. */
|
|
28
|
+
export const italic = { type: 'italic' };
|
|
29
|
+
/** Link inline mark. The href is branded; pass a raw string. */
|
|
30
|
+
export const link = (href) => ({
|
|
31
|
+
type: 'link',
|
|
32
|
+
attrs: { href: Href.of(href) },
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Curried text-node builder: apply marks first, then the string.
|
|
36
|
+
*
|
|
37
|
+
* @example `text(bold, italic)('important')` · `plain('plain text')`
|
|
38
|
+
*/
|
|
39
|
+
export const text = (...marks) => (value) => marks.length > 0 ? { type: 'text', text: value, marks } : { type: 'text', text: value };
|
|
40
|
+
/** Unmarked text node — `plain('hi')` is `text()('hi')`. */
|
|
41
|
+
export const plain = text();
|
|
42
|
+
/** Paragraph block from inline {@link TextNode}s. */
|
|
43
|
+
export const paragraph = (...content) => content.length > 0 ? { type: 'paragraph', content } : { type: 'paragraph' };
|
|
44
|
+
/**
|
|
45
|
+
* Curried heading builder: choose the level (1–3), then the inline content.
|
|
46
|
+
*
|
|
47
|
+
* @example `heading(2)(plain('Section'))`
|
|
48
|
+
*/
|
|
49
|
+
export const heading = (level) => (...content) => ({
|
|
50
|
+
type: 'heading',
|
|
51
|
+
attrs: { level },
|
|
52
|
+
...(content.length > 0 ? { content } : {}),
|
|
53
|
+
});
|
|
54
|
+
/** A single list entry; wrap paragraphs for {@link bulletList}/{@link orderedList}. */
|
|
55
|
+
export const listItem = (...content) => ({
|
|
56
|
+
type: 'listItem',
|
|
57
|
+
content,
|
|
58
|
+
});
|
|
59
|
+
/** Unordered list of {@link listItem}s. */
|
|
60
|
+
export const bulletList = (...content) => ({
|
|
61
|
+
type: 'bulletList',
|
|
62
|
+
content,
|
|
63
|
+
});
|
|
64
|
+
/** Ordered (numbered) list of {@link listItem}s. */
|
|
65
|
+
export const orderedList = (...content) => ({
|
|
66
|
+
type: 'orderedList',
|
|
67
|
+
content,
|
|
68
|
+
});
|
|
69
|
+
/** Block quote containing one or more paragraphs. */
|
|
70
|
+
export const blockquote = (...content) => ({
|
|
71
|
+
type: 'blockquote',
|
|
72
|
+
content,
|
|
73
|
+
});
|
|
74
|
+
/**
|
|
75
|
+
* Curried code-block builder: optional language first, then the raw source.
|
|
76
|
+
* The language is branded and should match a renderer-supported id for
|
|
77
|
+
* highlighting (see `supportedCodeLanguages`).
|
|
78
|
+
*
|
|
79
|
+
* @example `codeBlock('rust')('fn main() {}')` · `codeBlock()('plain text')`
|
|
80
|
+
*/
|
|
81
|
+
export const codeBlock = (language) => (code) => ({
|
|
82
|
+
type: 'codeBlock',
|
|
83
|
+
...(language ? { attrs: { language: Language.of(language) } } : {}),
|
|
84
|
+
content: code ? [{ type: 'text', text: code }] : [],
|
|
85
|
+
});
|
|
86
|
+
/** Document root from top-level block nodes (no version envelope). */
|
|
87
|
+
export const doc = (...content) => ({ type: 'doc', content });
|
|
88
|
+
/**
|
|
89
|
+
* A complete {@link EditorDocument} (root + current schema version). This is
|
|
90
|
+
* the value you pass to `editor.setContent` or the renderer.
|
|
91
|
+
*/
|
|
92
|
+
export const document = (...content) => ({
|
|
93
|
+
schemaVersion: SCHEMA_VERSION,
|
|
94
|
+
content: doc(...content),
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=nodes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nodes.js","sourceRoot":"","sources":["../src/nodes.ts"],"names":[],"mappings":"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"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { EditorContent, EditorDocument } from './types.js';
|
|
2
|
+
/** Current document schema version stamped onto new documents. */
|
|
3
|
+
export declare const SCHEMA_VERSION = 1;
|
|
4
|
+
/** An empty document root (a single empty paragraph). */
|
|
5
|
+
export declare const emptyContent: () => EditorContent;
|
|
6
|
+
/**
|
|
7
|
+
* A blank document at the current schema version — a good initial value for a
|
|
8
|
+
* new editor or "new document" action.
|
|
9
|
+
*/
|
|
10
|
+
export declare const createEmptyDocument: () => EditorDocument;
|
|
11
|
+
/**
|
|
12
|
+
* Structural type guard for untrusted input (backend responses, `localStorage`,
|
|
13
|
+
* paste payloads). Use it at trust boundaries before {@link migrate}; it checks
|
|
14
|
+
* shape, not deep node validity.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* const raw: unknown = JSON.parse(localStorage.getItem('doc') ?? 'null');
|
|
19
|
+
* if (isEditorDocument(raw)) editor.setContent(raw);
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export declare const isEditorDocument: (value: unknown) => value is EditorDocument;
|
|
23
|
+
/**
|
|
24
|
+
* Like {@link isEditorDocument} but returns the value typed as
|
|
25
|
+
* {@link EditorDocument}, throwing `TypeError` if it is not one.
|
|
26
|
+
*/
|
|
27
|
+
export declare const assertEditorDocument: (value: unknown) => EditorDocument;
|
|
28
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhE,kEAAkE;AAClE,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,yDAAyD;AACzD,eAAO,MAAM,YAAY,QAAO,aAG9B,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mBAAmB,QAAO,cAGrC,CAAC;AAKH;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,cAK1D,CAAC;AAUF;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,OAAO,OAAO,KAAG,cAMnD,CAAC"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Left, Right } from 'monadyssey';
|
|
2
|
+
/** Current document schema version stamped onto new documents. */
|
|
3
|
+
export const SCHEMA_VERSION = 1;
|
|
4
|
+
/** An empty document root (a single empty paragraph). */
|
|
5
|
+
export const emptyContent = () => ({
|
|
6
|
+
type: 'doc',
|
|
7
|
+
content: [{ type: 'paragraph' }],
|
|
8
|
+
});
|
|
9
|
+
/**
|
|
10
|
+
* A blank document at the current schema version — a good initial value for a
|
|
11
|
+
* new editor or "new document" action.
|
|
12
|
+
*/
|
|
13
|
+
export const createEmptyDocument = () => ({
|
|
14
|
+
schemaVersion: SCHEMA_VERSION,
|
|
15
|
+
content: emptyContent(),
|
|
16
|
+
});
|
|
17
|
+
const isObject = (value) => typeof value === 'object' && value !== null;
|
|
18
|
+
/**
|
|
19
|
+
* Structural type guard for untrusted input (backend responses, `localStorage`,
|
|
20
|
+
* paste payloads). Use it at trust boundaries before {@link migrate}; it checks
|
|
21
|
+
* shape, not deep node validity.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const raw: unknown = JSON.parse(localStorage.getItem('doc') ?? 'null');
|
|
26
|
+
* if (isEditorDocument(raw)) editor.setContent(raw);
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const isEditorDocument = (value) => {
|
|
30
|
+
if (!isObject(value))
|
|
31
|
+
return false;
|
|
32
|
+
if (typeof value.schemaVersion !== 'number')
|
|
33
|
+
return false;
|
|
34
|
+
const content = value.content;
|
|
35
|
+
return isObject(content) && content.type === 'doc' && Array.isArray(content.content);
|
|
36
|
+
};
|
|
37
|
+
// Internal decode boundary: success/failure modeled as Either rather than a
|
|
38
|
+
// thrown control-flow. The thrown TypeError is reconstituted only at the public
|
|
39
|
+
// edge (assertEditorDocument) so the public contract is unchanged.
|
|
40
|
+
const decodeEditorDocument = (value) => isEditorDocument(value)
|
|
41
|
+
? Right.pure(value)
|
|
42
|
+
: Left.pure(new TypeError('Value is not a valid EditorDocument'));
|
|
43
|
+
/**
|
|
44
|
+
* Like {@link isEditorDocument} but returns the value typed as
|
|
45
|
+
* {@link EditorDocument}, throwing `TypeError` if it is not one.
|
|
46
|
+
*/
|
|
47
|
+
export const assertEditorDocument = (value) => decodeEditorDocument(value).fold((error) => {
|
|
48
|
+
throw error;
|
|
49
|
+
}, (document) => document);
|
|
50
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,IAAI,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAGtD,kEAAkE;AAClE,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,yDAAyD;AACzD,MAAM,CAAC,MAAM,YAAY,GAAG,GAAkB,EAAE,CAAC,CAAC;IAChD,IAAI,EAAE,KAAK;IACX,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;CACjC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAmB,EAAE,CAAC,CAAC;IACxD,aAAa,EAAE,cAAc;IAC7B,OAAO,EAAE,YAAY,EAAE;CACxB,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAoC,EAAE,CACpE,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AAE9C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAA2B,EAAE;IAC1E,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,IAAI,OAAO,KAAK,CAAC,aAAa,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC9B,OAAO,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;AACvF,CAAC,CAAC;AAEF,4EAA4E;AAC5E,gFAAgF;AAChF,mEAAmE;AACnE,MAAM,oBAAoB,GAAG,CAAC,KAAc,EAAqC,EAAE,CACjF,gBAAgB,CAAC,KAAK,CAAC;IACrB,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;IACnB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAC,CAAC;AAEtE;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,KAAc,EAAkB,EAAE,CACrE,oBAAoB,CAAC,KAAK,CAAC,CAAC,IAAI,CAC9B,CAAC,KAAK,EAAE,EAAE;IACR,MAAM,KAAK,CAAC;AACd,CAAC,EACD,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CACvB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The document model — a serializable, framework-independent tree. This is the
|
|
3
|
+
* canonical wire/storage format: persist {@link EditorDocument} as JSON and
|
|
4
|
+
* pass it back unchanged to load. Build documents with the smart constructors
|
|
5
|
+
* in `./nodes` rather than by hand.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* const doc: EditorDocument = {
|
|
10
|
+
* schemaVersion: 1,
|
|
11
|
+
* content: {
|
|
12
|
+
* type: 'doc',
|
|
13
|
+
* content: [
|
|
14
|
+
* { type: 'heading', attrs: { level: 1 }, content: [{ type: 'text', text: 'Title' }] },
|
|
15
|
+
* { type: 'paragraph', content: [{ type: 'text', text: 'Body' }] },
|
|
16
|
+
* ],
|
|
17
|
+
* },
|
|
18
|
+
* };
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* @module
|
|
22
|
+
*/
|
|
23
|
+
import type { Href, Language } from './brand.js';
|
|
24
|
+
/** Inline formatting applied to a {@link TextNode}. `link.attrs.href` is branded. */
|
|
25
|
+
export type TextMark = {
|
|
26
|
+
type: 'bold';
|
|
27
|
+
} | {
|
|
28
|
+
type: 'italic';
|
|
29
|
+
} | {
|
|
30
|
+
type: 'link';
|
|
31
|
+
attrs: {
|
|
32
|
+
href: Href;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
export type TextNode = {
|
|
36
|
+
type: 'text';
|
|
37
|
+
text: string;
|
|
38
|
+
marks?: TextMark[];
|
|
39
|
+
};
|
|
40
|
+
export type ParagraphNode = {
|
|
41
|
+
type: 'paragraph';
|
|
42
|
+
content?: TextNode[];
|
|
43
|
+
};
|
|
44
|
+
export type HeadingNode = {
|
|
45
|
+
type: 'heading';
|
|
46
|
+
attrs: {
|
|
47
|
+
level: 1 | 2 | 3;
|
|
48
|
+
};
|
|
49
|
+
content?: TextNode[];
|
|
50
|
+
};
|
|
51
|
+
export type ListItemNode = {
|
|
52
|
+
type: 'listItem';
|
|
53
|
+
content: ParagraphNode[];
|
|
54
|
+
};
|
|
55
|
+
export type BulletListNode = {
|
|
56
|
+
type: 'bulletList';
|
|
57
|
+
content: ListItemNode[];
|
|
58
|
+
};
|
|
59
|
+
export type NumberedListNode = {
|
|
60
|
+
type: 'orderedList';
|
|
61
|
+
content: ListItemNode[];
|
|
62
|
+
};
|
|
63
|
+
export type QuoteNode = {
|
|
64
|
+
type: 'blockquote';
|
|
65
|
+
content: ParagraphNode[];
|
|
66
|
+
};
|
|
67
|
+
export type CodeBlockNode = {
|
|
68
|
+
type: 'codeBlock';
|
|
69
|
+
attrs?: {
|
|
70
|
+
language?: Language;
|
|
71
|
+
};
|
|
72
|
+
content?: TextNode[];
|
|
73
|
+
};
|
|
74
|
+
export type EditorNode = ParagraphNode | HeadingNode | BulletListNode | NumberedListNode | QuoteNode | CodeBlockNode;
|
|
75
|
+
/** Root node of a document tree. */
|
|
76
|
+
export type EditorContent = {
|
|
77
|
+
type: 'doc';
|
|
78
|
+
content: EditorNode[];
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* A complete, versioned document — the unit you save and load. `schemaVersion`
|
|
82
|
+
* lets {@link migrate} upgrade older payloads forward.
|
|
83
|
+
*/
|
|
84
|
+
export type EditorDocument = {
|
|
85
|
+
schemaVersion: number;
|
|
86
|
+
content: EditorContent;
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEjD,qFAAqF;AACrF,MAAM,MAAM,QAAQ,GAChB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,IAAI,CAAA;KAAE,CAAA;CAAE,CAAC;AAE5C,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE;QAAE,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;KAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,YAAY,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,QAAQ,CAAA;KAAE,CAAC;IAChC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB,aAAa,GACb,WAAW,GACX,cAAc,GACd,gBAAgB,GAChB,SAAS,GACT,aAAa,CAAC;AAElB,oCAAoC;AACpC,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,aAAa,CAAC;CACxB,CAAC"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@openstage/glyph-core",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"author": "Gabriel Bornea",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://codeberg.org/open-stage/glyph.git",
|
|
9
|
+
"directory": "packages/editor-core"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://codeberg.org/open-stage/glyph#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://codeberg.org/open-stage/glyph/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"main": "./dist/index.js",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"types": "./dist/index.d.ts",
|
|
21
|
+
"default": "./dist/index.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "rm -rf dist && tsc -p tsconfig.json",
|
|
32
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"monadyssey": "^2.0.1"
|
|
36
|
+
}
|
|
37
|
+
}
|