fountainjs-editor 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 +460 -0
- package/dist/fountainjs-react.cjs +1 -0
- package/dist/fountainjs-react.js +8 -0
- package/dist/fountainjs.cjs +1 -0
- package/dist/fountainjs.js +219 -0
- package/dist/index-1c508d95.js +1172 -0
- package/dist/index-cafd8e26.cjs +40 -0
- package/package.json +76 -0
- package/src/core/editor.ts +15 -0
- package/src/core/index.ts +6 -0
- package/src/core/plugin.ts +4 -0
- package/src/core/schema/index.ts +5 -0
- package/src/core/schema/mark-spec.ts +5 -0
- package/src/core/schema/mark.ts +7 -0
- package/src/core/schema/node-spec.ts +12 -0
- package/src/core/schema/node.ts +12 -0
- package/src/core/schema/schema.ts +17 -0
- package/src/core/selection.ts +17 -0
- package/src/core/state.ts +13 -0
- package/src/core/transaction/add-mark-step.ts +19 -0
- package/src/core/transaction/index.ts +9 -0
- package/src/core/transaction/insert-text-step.ts +18 -0
- package/src/core/transaction/remove-mark-step.ts +17 -0
- package/src/core/transaction/replace-step.ts +6 -0
- package/src/core/transaction/replace-text-step.ts +33 -0
- package/src/core/transaction/set-node-attrs-step.ts +30 -0
- package/src/core/transaction/step.ts +2 -0
- package/src/core/transaction/transaction.ts +8 -0
- package/src/core/transaction/transform.ts +23 -0
- package/src/extensions/index.ts +64 -0
- package/src/extensions/marks/em.ts +2 -0
- package/src/extensions/marks/strong.ts +2 -0
- package/src/extensions/nodes/bullet-list.ts +9 -0
- package/src/extensions/nodes/doc.ts +2 -0
- package/src/extensions/nodes/figcaption.ts +5 -0
- package/src/extensions/nodes/heading.ts +7 -0
- package/src/extensions/nodes/image-super-view.ts +90 -0
- package/src/extensions/nodes/image-super.ts +7 -0
- package/src/extensions/nodes/list-item.ts +9 -0
- package/src/extensions/nodes/paragraph.ts +2 -0
- package/src/extensions/nodes/table-cell.ts +5 -0
- package/src/extensions/nodes/table-row.ts +2 -0
- package/src/extensions/nodes/table.ts +5 -0
- package/src/extensions/nodes/text.ts +2 -0
- package/src/extensions/plugins/history.ts +12 -0
- package/src/extensions/plugins/markdown-shortcuts.ts +52 -0
- package/src/index.ts +12 -0
- package/src/react/FountainEditor.tsx +19 -0
- package/src/react/Navigator.tsx +36 -0
- package/src/react/index.ts +4 -0
- package/src/react/useFountain.ts +10 -0
- package/src/react/useNavigatorState.ts +41 -0
- package/src/view/dom-renderer.ts +77 -0
- package/src/view/index.ts +2 -0
- package/src/view/input.ts +74 -0
- package/src/view/node-view.ts +9 -0
- package/src/view/selection-handler.ts +76 -0
- package/src/view/view.ts +290 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 FountainJS Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# FountainJS Editor
|
|
2
|
+
|
|
3
|
+
A modern, modular, and extensible rich text editor library built with TypeScript. Use it in React, Vue, Angular, or vanilla JavaScript projects.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
✨ **Modular Architecture** - Built from the ground up to be composable and extensible
|
|
8
|
+
📝 **Multiple Content Types** - Headings, paragraphs, tables, lists, images, and more
|
|
9
|
+
⌨️ **Keyboard Shortcuts** - Built-in support for Ctrl+B (bold), Ctrl+I (italic), and more
|
|
10
|
+
🎨 **Flexible Styling** - Customize the editor appearance with CSS
|
|
11
|
+
🔌 **Plugin System** - Extend functionality with plugins (history, markdown shortcuts, etc.)
|
|
12
|
+
🎯 **Type-Safe** - Full TypeScript support with comprehensive type definitions
|
|
13
|
+
📱 **Responsive** - Works great on desktop and mobile devices
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
### Via npm
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm install @fountainjs/editor
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Via pnpm
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pnpm add @fountainjs/editor
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Via yarn
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
yarn add @fountainjs/editor
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Quick Start - React
|
|
36
|
+
|
|
37
|
+
### Basic Editor
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import React from 'react';
|
|
41
|
+
import { useFountain, FountainEditor, CoreSchemaSpec, historyPlugin } from '@fountainjs/editor/react';
|
|
42
|
+
|
|
43
|
+
function MyEditor() {
|
|
44
|
+
const editor = useFountain({
|
|
45
|
+
schema: CoreSchemaSpec,
|
|
46
|
+
plugins: [historyPlugin],
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div style={{ padding: '2rem' }}>
|
|
51
|
+
<FountainEditor editor={editor} />
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export default MyEditor;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### With Toolbar
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import React from 'react';
|
|
63
|
+
import { Node, useFountain, FountainEditor, CoreSchemaSpec, historyPlugin } from '@fountainjs/editor/react';
|
|
64
|
+
|
|
65
|
+
function Editor() {
|
|
66
|
+
const editor = useFountain({
|
|
67
|
+
schema: CoreSchemaSpec,
|
|
68
|
+
plugins: [historyPlugin],
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
const insertHeading = (level: 1 | 2 | 3) => {
|
|
72
|
+
if (!editor) return;
|
|
73
|
+
const { state } = editor;
|
|
74
|
+
const text = new Node(state.schema.nodes.text, {}, [], 'Heading');
|
|
75
|
+
const heading = new Node(state.schema.nodes.heading, { level }, [text]);
|
|
76
|
+
const tr = state.createTransaction().replace(
|
|
77
|
+
state.doc.content.length,
|
|
78
|
+
state.doc.content.length,
|
|
79
|
+
[heading]
|
|
80
|
+
);
|
|
81
|
+
editor.dispatch(tr);
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<div>
|
|
86
|
+
<div style={{ marginBottom: '1rem' }}>
|
|
87
|
+
<button onClick={() => insertHeading(1)}>H1</button>
|
|
88
|
+
<button onClick={() => insertHeading(2)}>H2</button>
|
|
89
|
+
<button onClick={() => insertHeading(3)}>H3</button>
|
|
90
|
+
</div>
|
|
91
|
+
<FountainEditor editor={editor} />
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export default Editor;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Quick Start - Vanilla JavaScript
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
import {
|
|
103
|
+
createEditor,
|
|
104
|
+
EditorView,
|
|
105
|
+
CoreSchemaSpec,
|
|
106
|
+
historyPlugin,
|
|
107
|
+
} from '@fountainjs/editor';
|
|
108
|
+
|
|
109
|
+
// Create an editor
|
|
110
|
+
const editor = createEditor({
|
|
111
|
+
schema: CoreSchemaSpec,
|
|
112
|
+
plugins: [historyPlugin],
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Mount it to a DOM element
|
|
116
|
+
const container = document.getElementById('editor');
|
|
117
|
+
const view = new EditorView(container, editor);
|
|
118
|
+
|
|
119
|
+
// Subscribe to changes
|
|
120
|
+
editor.subscribe((newState) => {
|
|
121
|
+
console.log('Editor state changed:', newState);
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## API Documentation
|
|
126
|
+
|
|
127
|
+
### Core Components
|
|
128
|
+
|
|
129
|
+
#### `useFountain(config)`
|
|
130
|
+
|
|
131
|
+
Hook to create and manage a FountainJS editor instance in React.
|
|
132
|
+
|
|
133
|
+
**Parameters:**
|
|
134
|
+
|
|
135
|
+
```typescript
|
|
136
|
+
interface EditorConfig {
|
|
137
|
+
schema: SchemaSpec;
|
|
138
|
+
state?: EditorState;
|
|
139
|
+
plugins?: Plugin[];
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Returns:** `Editor | null`
|
|
144
|
+
|
|
145
|
+
**Example:**
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
const editor = useFountain({
|
|
149
|
+
schema: CoreSchemaSpec,
|
|
150
|
+
plugins: [historyPlugin],
|
|
151
|
+
});
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
#### `FountainEditor`
|
|
157
|
+
|
|
158
|
+
React component that renders the editor.
|
|
159
|
+
|
|
160
|
+
**Props:**
|
|
161
|
+
|
|
162
|
+
```typescript
|
|
163
|
+
interface FountainEditorProps {
|
|
164
|
+
editor: Editor | null;
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
**Example:**
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
<FountainEditor editor={editor} />
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
#### `Navigator`
|
|
177
|
+
|
|
178
|
+
React component that displays the document structure.
|
|
179
|
+
|
|
180
|
+
**Props:**
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
interface NavigatorProps {
|
|
184
|
+
editor: Editor | null;
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
**Example:**
|
|
189
|
+
|
|
190
|
+
```tsx
|
|
191
|
+
<Navigator editor={editor} />
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
#### `createEditor(config)`
|
|
197
|
+
|
|
198
|
+
Creates a new editor instance (vanilla JS).
|
|
199
|
+
|
|
200
|
+
**Parameters:**
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
interface EditorConfig {
|
|
204
|
+
schema: SchemaSpec;
|
|
205
|
+
state?: EditorState;
|
|
206
|
+
plugins?: Plugin[];
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Returns:** `Editor`
|
|
211
|
+
|
|
212
|
+
**Example:**
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
const editor = createEditor({
|
|
216
|
+
schema: CoreSchemaSpec,
|
|
217
|
+
plugins: [historyPlugin],
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
#### `EditorView`
|
|
224
|
+
|
|
225
|
+
Mounts an editor to a DOM element and manages rendering.
|
|
226
|
+
|
|
227
|
+
**Constructor:**
|
|
228
|
+
|
|
229
|
+
```typescript
|
|
230
|
+
new EditorView(mount: HTMLElement, editor: Editor)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Methods:**
|
|
234
|
+
|
|
235
|
+
- `execCommand(command: string, value?: string): boolean` - Execute a browser command
|
|
236
|
+
- `destroy(): void` - Cleanup and remove the editor
|
|
237
|
+
|
|
238
|
+
**Example:**
|
|
239
|
+
|
|
240
|
+
```typescript
|
|
241
|
+
const view = new EditorView(document.getElementById('editor'), editor);
|
|
242
|
+
|
|
243
|
+
// Later...
|
|
244
|
+
view.destroy();
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### Built-in Schemas
|
|
250
|
+
|
|
251
|
+
#### `CoreSchemaSpec`
|
|
252
|
+
|
|
253
|
+
A comprehensive schema that includes:
|
|
254
|
+
|
|
255
|
+
- **Nodes:** doc, paragraph, heading, bullet_list, list_item, table, table_row, table_cell, image_super, figcaption, text
|
|
256
|
+
- **Marks:** strong (bold), em (italic)
|
|
257
|
+
|
|
258
|
+
**Usage:**
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
import { CoreSchemaSpec } from '@fountainjs/editor';
|
|
262
|
+
|
|
263
|
+
const editor = useFountain({
|
|
264
|
+
schema: CoreSchemaSpec,
|
|
265
|
+
});
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
### Plugins
|
|
271
|
+
|
|
272
|
+
#### `historyPlugin`
|
|
273
|
+
|
|
274
|
+
Provides undo/redo functionality.
|
|
275
|
+
|
|
276
|
+
**Usage:**
|
|
277
|
+
|
|
278
|
+
```typescript
|
|
279
|
+
import { historyPlugin } from '@fountainjs/editor';
|
|
280
|
+
|
|
281
|
+
const editor = useFountain({
|
|
282
|
+
schema: CoreSchemaSpec,
|
|
283
|
+
plugins: [historyPlugin],
|
|
284
|
+
});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
### Schema Types
|
|
290
|
+
|
|
291
|
+
#### `SchemaSpec`
|
|
292
|
+
|
|
293
|
+
Define custom node and mark types.
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
interface SchemaSpec {
|
|
297
|
+
nodes: { [name: string]: NodeSpec };
|
|
298
|
+
marks?: { [name: string]: MarkSpec };
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
**Example:**
|
|
303
|
+
|
|
304
|
+
```typescript
|
|
305
|
+
const mySchema: SchemaSpec = {
|
|
306
|
+
nodes: {
|
|
307
|
+
doc: {
|
|
308
|
+
content: 'block+',
|
|
309
|
+
},
|
|
310
|
+
paragraph: {
|
|
311
|
+
content: 'inline*',
|
|
312
|
+
parseDOM: [{ tag: 'p' }],
|
|
313
|
+
toDOM: () => ['p', 0],
|
|
314
|
+
},
|
|
315
|
+
text: {
|
|
316
|
+
inline: true,
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
marks: {
|
|
320
|
+
bold: {
|
|
321
|
+
parseDOM: [{ tag: 'strong' }],
|
|
322
|
+
toDOM: () => ['strong', 0],
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
};
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
#### `Node`
|
|
331
|
+
|
|
332
|
+
Represents a node in the document tree.
|
|
333
|
+
|
|
334
|
+
```typescript
|
|
335
|
+
new Node(
|
|
336
|
+
type: NodeType,
|
|
337
|
+
attrs: Record<string, any>,
|
|
338
|
+
content: Node[],
|
|
339
|
+
text?: string
|
|
340
|
+
)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**Properties:**
|
|
344
|
+
|
|
345
|
+
- `type: NodeType` - The node type
|
|
346
|
+
- `attrs: Record<string, any>` - Attributes like `{ level: 2 }` for headings
|
|
347
|
+
- `content: Node[]` - Child nodes
|
|
348
|
+
- `text?: string` - For text nodes, the text content
|
|
349
|
+
|
|
350
|
+
**Example:**
|
|
351
|
+
|
|
352
|
+
```typescript
|
|
353
|
+
const heading = new Node(
|
|
354
|
+
schema.nodes.heading,
|
|
355
|
+
{ level: 1 },
|
|
356
|
+
[
|
|
357
|
+
new Node(schema.nodes.text, {}, [], 'Hello World')
|
|
358
|
+
]
|
|
359
|
+
);
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
### Keyboard Shortcuts
|
|
365
|
+
|
|
366
|
+
By default, FountainJS supports:
|
|
367
|
+
|
|
368
|
+
| Shortcut | Action |
|
|
369
|
+
|----------|--------|
|
|
370
|
+
| `Ctrl+B` / `Cmd+B` | Toggle bold |
|
|
371
|
+
| `Ctrl+I` / `Cmd+I` | Toggle italic |
|
|
372
|
+
| `Ctrl+Z` / `Cmd+Z` | Undo (requires history plugin) |
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Customization
|
|
377
|
+
|
|
378
|
+
### Custom Styling
|
|
379
|
+
|
|
380
|
+
The editor renders semantic HTML, so you can style it with CSS:
|
|
381
|
+
|
|
382
|
+
```css
|
|
383
|
+
[role="textbox"] {
|
|
384
|
+
padding: 12px;
|
|
385
|
+
font-size: 16px;
|
|
386
|
+
line-height: 1.6;
|
|
387
|
+
border: 1px solid #ddd;
|
|
388
|
+
border-radius: 4px;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
[role="textbox"] h1 {
|
|
392
|
+
font-size: 32px;
|
|
393
|
+
font-weight: bold;
|
|
394
|
+
margin: 1em 0 0.5em 0;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
[role="textbox"] h2 {
|
|
398
|
+
font-size: 24px;
|
|
399
|
+
margin: 0.8em 0 0.4em 0;
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Custom Schema
|
|
404
|
+
|
|
405
|
+
Define your own schema for specific use cases:
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
import { SchemaSpec, useFountain, CoreSchemaSpec } from '@fountainjs/editor/react';
|
|
409
|
+
|
|
410
|
+
const customSchema: SchemaSpec = {
|
|
411
|
+
...CoreSchemaSpec,
|
|
412
|
+
nodes: {
|
|
413
|
+
...CoreSchemaSpec.nodes,
|
|
414
|
+
// Override or add custom nodes
|
|
415
|
+
customNode: {
|
|
416
|
+
content: 'inline*',
|
|
417
|
+
parseDOM: [{ tag: 'div', class: 'custom' }],
|
|
418
|
+
toDOM: () => ['div', { class: 'custom' }, 0],
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const editor = useFountain({
|
|
424
|
+
schema: customSchema,
|
|
425
|
+
});
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## Browser Support
|
|
431
|
+
|
|
432
|
+
- Chrome/Edge 88+
|
|
433
|
+
- Firefox 87+
|
|
434
|
+
- Safari 14+
|
|
435
|
+
- iOS Safari 14+
|
|
436
|
+
- Chrome for Android 88+
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## License
|
|
441
|
+
|
|
442
|
+
MIT - See LICENSE file for details
|
|
443
|
+
|
|
444
|
+
---
|
|
445
|
+
|
|
446
|
+
## Contributing
|
|
447
|
+
|
|
448
|
+
Contributions are welcome! Please read our contributing guidelines before submitting pull requests.
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## Support
|
|
453
|
+
|
|
454
|
+
- 📖 [Documentation](https://fountainjs.dev)
|
|
455
|
+
- 🐛 [Issues](https://github.com/yourusername/fountainjs/issues)
|
|
456
|
+
- 💬 [Discussions](https://github.com/yourusername/fountainjs/discussions)
|
|
457
|
+
|
|
458
|
+
---
|
|
459
|
+
|
|
460
|
+
**Made with ❤️ for developers who want a powerful, flexible text editor**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./index-cafd8e26.cjs");require("react");exports.FountainEditor=t.FountainEditor;exports.Navigator=t.Navigator;exports.useFountain=t.useFountain;exports.useNavigatorState=t.useNavigatorState;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";var D=Object.defineProperty;var O=(n,t,e)=>t in n?D(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var l=(n,t,e)=>(O(n,typeof t!="symbol"?t+"":t,e),e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./index-cafd8e26.cjs");require("react");class p{constructor(t,e){l(this,"type");l(this,"attrs");this.type=t,this.attrs=e}static fromJSON(t,e){const i=t.marks[e.type];if(!i)throw new Error(`Unknown mark type: ${e.type}`);return new p(i,{...e.attrs})}}class N extends o.Step{constructor(t,e,i){super(),this.path=t,this.offset=e,this.text=i}apply(t){let e=t,i=[];for(const r of this.path)i.push(e),e=e.content[r];if(!e||!e.isText)throw new Error("Target for InsertTextStep is not a text node.");let c=e.withText((e.text||"").slice(0,this.offset)+this.text+(e.text||"").slice(this.offset));for(let r=i.length-1;r>=0;r--){const a=i[r],d=[...a.content];d[this.path[r]]=c,c=new o.Node(a.type,a.attrs,d,a.text,a.marks)}return c}}class u{constructor(t){l(this,"spec");this.spec=t}}const h={content:"block+",toDOM(){return["div",0]}},m={content:"inline*",group:"block",toDOM(){return["p",0]}},g={group:"inline"},w={attrs:{level:{default:1}},content:"inline*",group:"block",toDOM(n){return[`h${n.attrs.level}`,0]}};class R{constructor(t,e,i){l(this,"dom");l(this,"contentDOM");l(this,"img");l(this,"getPos");l(this,"onResizeStart",t=>{t.preventDefault();const e=t.clientX,i=this.dom.offsetWidth,s=r=>{const a=i+(r.clientX-e);this.dom.style.width=`${a}px`},c=()=>{window.removeEventListener("mousemove",s),window.removeEventListener("mouseup",c);const r=this.getPos();if(r===void 0)return;const a={...this.node.attrs,width:this.dom.style.width},d=[r],T=this.view.editor.createTransaction().setNodeAttrs(d,a);this.view.editor.dispatch(T)};window.addEventListener("mousemove",s),window.addEventListener("mouseup",c)});this.node=t,this.view=e,this.getPos=i,this.dom=document.createElement("figure"),this.dom.style.position="relative",this.dom.style.margin="1rem 0",this.dom.style.display="inline-block",this.img=document.createElement("img"),this.updateImageAttributes(t.attrs),this.contentDOM=document.createElement("div");const s=document.createElement("div");s.style.position="absolute",s.style.bottom="5px",s.style.right="5px",s.style.width="10px",s.style.height="10px",s.style.backgroundColor="#007bff",s.style.cursor="nwse-resize",s.style.border="1px solid white",this.dom.appendChild(this.img),this.dom.appendChild(this.contentDOM),this.dom.appendChild(s),s.addEventListener("mousedown",this.onResizeStart)}update(t){return t.type!==this.node.type?!1:(this.updateImageAttributes(t.attrs),this.node=t,!0)}updateImageAttributes(t){this.img.src=t.src,this.img.alt=t.alt,this.img.title=t.title,this.dom.style.width=t.width,this.img.style.width="100%"}}const f={group:"block",content:"figcaption?",attrs:{src:{default:""},alt:{default:""},title:{default:""},width:{default:"100%"}},toDOM:n=>{const{src:t,alt:e,title:i,width:s}=n.attrs;return["figure",{style:`width: ${s};`},["img",{src:t,alt:e,title:i}],0]},nodeView:R},y={content:"inline*",toDOM:()=>["figcaption",{style:"text-align: center; color: #666; font-style: italic;"},0]},S={group:"block",content:"table_row+",toDOM(){return["table",{style:"border-collapse: collapse; width: 100%;"},["tbody",0]]}},b={content:"table_cell+",toDOM(){return["tr",0]}},x={content:"paragraph+",attrs:{colspan:{default:1},rowspan:{default:1}},toDOM(n){return["td",{style:"border: 1px solid #ddd; padding: 8px;",...n.attrs},0]}},v={group:"block",content:"list_item+",toDOM(){return["ul",0]}},M={content:"paragraph+ (bullet_list)?",toDOM(){return["li",0]}},E={toDOM(){return["strong",0]}},k={toDOM(){return["em",0]}},P=100;function A(){return{done:[],undone:[]}}const I=new u({state:{init:A,apply:(n,t)=>{if(n.steps.length>0){const e=[...t.done,n];return e.length>P&&e.shift(),{done:e,undone:[]}}return t}}});function _(n){return console.log("Undo command called (not implemented)"),!1}function C(n){return console.log("Redo command called (not implemented)"),!1}const L=new u({}),z={nodes:{doc:h,paragraph:m,text:g,heading:w,image_super:f,figcaption:y,table:S,table_row:b,table_cell:x,bullet_list:v,list_item:M},marks:{strong:E,em:k}};exports.AddMarkStep=o.AddMarkStep;exports.Editor=o.Editor;exports.EditorState=o.EditorState;exports.EditorView=o.EditorView;exports.FountainEditor=o.FountainEditor;exports.MarkType=o.MarkType;exports.Navigator=o.Navigator;exports.Node=o.Node;exports.NodeType=o.NodeType;exports.RemoveMarkStep=o.RemoveMarkStep;exports.ReplaceStep=o.ReplaceStep;exports.ReplaceTextStep=o.ReplaceTextStep;exports.Schema=o.Schema;exports.Selection=o.Selection;exports.SetNodeAttrsStep=o.SetNodeAttrsStep;exports.Step=o.Step;exports.Transaction=o.Transaction;exports.Transform=o.Transform;exports.createEditor=o.createEditor;exports.useFountain=o.useFountain;exports.useNavigatorState=o.useNavigatorState;exports.CoreSchemaSpec=z;exports.InsertTextStep=N;exports.Mark=p;exports.Plugin=u;exports.bulletList=v;exports.doc=h;exports.em=k;exports.figcaption=y;exports.heading=w;exports.historyPlugin=I;exports.imageSuper=f;exports.listItem=M;exports.markdownShortcutsPlugin=L;exports.paragraph=m;exports.redo=C;exports.strong=E;exports.table=S;exports.tableCell=x;exports.tableRow=b;exports.text=g;exports.undo=_;
|