prosemirror-codemirror-block 0.2.8 → 0.2.9
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/README.md +97 -165
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
# prosemirror-codemirror-block
|
|
2
2
|
|
|
3
|
-

|
|
4
|
+
|
|
5
|
+
Sponsored by [Skiff](https://www.skiff.org/), the _best_ end-to-end encrypted Private & decentralized
|
|
6
|
+
workspace.
|
|
7
|
+
|
|
4
8
|
|
|
5
9
|
By [Viktor Váczi](https://emergence-engineering.com/cv/viktor) at [Emergence Engineering](https://emergence-engineering.com/)
|
|
6
10
|
|
|
7
|
-
Try it out at <https://emergence-engineering.com/blog/prosemirror-
|
|
11
|
+
Try it out at <https://emergence-engineering.com/blog/prosemirror-codemirror-block>
|
|
8
12
|
|
|
9
13
|
# Features
|
|
10
14
|
|
|
11
|
-
-
|
|
12
|
-
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
- Optional image title
|
|
16
|
-
- Image resizing with body resize listeners, so the image always fits the editor ( inspired by czi-prosemirror )
|
|
17
|
-
- Scaling images with editor size ( when resizing is enabled )
|
|
15
|
+
- CodeMirror 6 `code_block` in ProseMirror
|
|
16
|
+
- Customizable language selector
|
|
17
|
+
- Lazy-loaded language support
|
|
18
|
+
- Legacy ( CodeMirror 5 ) language support trough `@codemirror/legacy-modes`
|
|
18
19
|
|
|
19
20
|
# How to use
|
|
20
21
|
|
|
@@ -22,46 +23,70 @@ Try it out at <https://emergence-engineering.com/blog/prosemirror-image-plugin>
|
|
|
22
23
|
import { schema } from "prosemirror-schema-basic";
|
|
23
24
|
import { EditorState } from "prosemirror-state";
|
|
24
25
|
import { EditorView } from "prosemirror-view";
|
|
25
|
-
import {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
26
|
+
import { exampleSetup } from "prosemirror-example-setup";
|
|
27
|
+
import {
|
|
28
|
+
codeMirrorBlockPlugin,
|
|
29
|
+
defaultSettings,
|
|
30
|
+
languageLoaders,
|
|
31
|
+
codeBlockArrowHandlers,
|
|
32
|
+
legacyLanguageLoaders,
|
|
33
|
+
} from "prosemirror-codemirror-block";
|
|
34
|
+
import { undo, redo } from "prosemirror-history";
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
const codeBlockSpec = schema.spec.nodes.get("code_block");
|
|
38
|
+
|
|
39
|
+
export default new Schema({
|
|
40
|
+
nodes: schema.spec.nodes.update("code_block", {
|
|
41
|
+
...(codeBlockSpec || {}),
|
|
42
|
+
attrs: { ...codeBlockSpec?.attrs, lang: { default: null } },
|
|
43
|
+
}),
|
|
44
|
+
marks: schema.spec.marks,
|
|
39
45
|
});
|
|
40
46
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
content: [
|
|
47
|
+
|
|
48
|
+
const codeBlockDoc = {
|
|
49
|
+
content: [
|
|
45
50
|
{
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
content: [
|
|
52
|
+
{
|
|
53
|
+
text: "prosemirror-codemirror-block",
|
|
54
|
+
type: "text",
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
type: "paragraph",
|
|
48
58
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
59
|
+
{
|
|
60
|
+
content: [
|
|
61
|
+
{
|
|
62
|
+
text: "const jsFun = (arg) => {\n console.log(arg); \n}",
|
|
63
|
+
type: "text",
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
attrs: {
|
|
67
|
+
lang: "javascript",
|
|
68
|
+
},
|
|
69
|
+
type: "code_block",
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
type: "doc",
|
|
54
73
|
};
|
|
55
74
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
75
|
+
|
|
76
|
+
const state = EditorState.create<typeof schema>({
|
|
77
|
+
doc: schema.nodeFromJSON(codeBlockDoc),
|
|
78
|
+
plugins: [
|
|
79
|
+
...exampleSetup({
|
|
80
|
+
schema,
|
|
81
|
+
}),
|
|
82
|
+
codeMirrorBlockPlugin({
|
|
83
|
+
...defaultSettings,
|
|
84
|
+
languageLoaders: { ...languageLoaders, ...legacyLanguageLoaders },
|
|
85
|
+
undo,
|
|
86
|
+
redo,
|
|
87
|
+
}),
|
|
88
|
+
keymap(codeBlockArrowHandlers),
|
|
89
|
+
],
|
|
65
90
|
});
|
|
66
91
|
|
|
67
92
|
const view: EditorView = new EditorView(document.getElementById("editor"), {
|
|
@@ -70,133 +95,41 @@ const view: EditorView = new EditorView(document.getElementById("editor"), {
|
|
|
70
95
|
```
|
|
71
96
|
|
|
72
97
|
# Configuration
|
|
73
|
-
###
|
|
98
|
+
### CodeBlockSettings
|
|
74
99
|
|
|
75
100
|
Interface for the settings used by this plugin.
|
|
76
101
|
|
|
77
|
-
| name
|
|
78
|
-
|
|
79
|
-
|
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
|
|
|
83
|
-
|
|
|
84
|
-
|
|
|
85
|
-
|
|
|
86
|
-
|
|
|
87
|
-
| downloadImage | (url: string) => Promise\<string> | Download image data with a callback function. Useful for images with behind auth. |
|
|
88
|
-
| downloadPlaceholder | string | If `downloadImage` is defined then this image is showed while the download is in progress. |
|
|
89
|
-
| isBlock | boolean | `true` if you want block images, `false` if you want inline ( ProseMirror default ). Titles are only possible with block images. Default `true`. |
|
|
90
|
-
| enableResize | boolean | Enables resize features. Default `true`. |
|
|
91
|
-
| resizeCallback | (el: Element, updateCallback: () => void) => () => void | Creates & destroys resize listeners |
|
|
92
|
-
| imageMargin | number | Space in `px` on the side an image. Default 50. |
|
|
93
|
-
| minSize | number | Minimum size in `px` of an image. Default 50. |
|
|
94
|
-
| maxSize | number | Maximum size in `px` of an image. Default 2000. |
|
|
95
|
-
| scaleImage | boolean | If `true` then images scale proportionally with editor width. Default `true`. |
|
|
96
|
-
|
|
97
|
-
### updateImageNode
|
|
98
|
-
Returns the updated nodes ( `Schema["spec"]["nodes"] type` )
|
|
99
|
-
|
|
100
|
-
Arguments:
|
|
101
|
-
|
|
102
|
-
| index | name | type | description |
|
|
103
|
-
|-------|----------------|---------------------------|----------------------------------------------------------|
|
|
104
|
-
| 1 | nodes | Schema ["spec"] ["nodes"] | nodes from the to-be-updated Schema spec |
|
|
105
|
-
| 2 | pluginSettings | ImagePluginSettings | same plugin settings the plugin will be initialized with |
|
|
106
|
-
|
|
107
|
-
### startImageUpload
|
|
108
|
-
|
|
109
|
-
Dispatches a transaction in the editor view which starts the image upload process ( and places placeholder etc ).
|
|
110
|
-
Returns `undefined`
|
|
111
|
-
|
|
112
|
-
Arguments:
|
|
113
|
-
|
|
114
|
-
| index | name | type | description |
|
|
115
|
-
| ----- | -------------- | -------------------- | --------------------------------------------------- |
|
|
116
|
-
| 1 | view | EditorView | Reference of the mounted editor view |
|
|
117
|
-
| 2 | file | File | image file to be uploaded |
|
|
118
|
-
| 3 | alt | string | alt of the file ( file.name usually works ) |
|
|
119
|
-
| 4 | pluginSettings | ImagePluginSettings | same plugin settings the plugin was initialized with |
|
|
120
|
-
| 5 | schema | Schema | updated schema used by the editor |
|
|
121
|
-
| 6 | pos | number | insert position in the document |
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
### Uploading files
|
|
126
|
-
Be aware that the default `uploadFile` inserts the dataURI of the image directly into the
|
|
127
|
-
ProseMirror document. That can cause issues with large files, for ex. `gif`s with long animations.
|
|
128
|
-
|
|
129
|
-
### Upload placeholder
|
|
130
|
-
The plugin creates a widget decoration while the upload process is still in progress. The widget decoration's
|
|
131
|
-
dom node is a `<placeholder>`, an example style could be:
|
|
132
|
-
```css
|
|
133
|
-
placeholder {
|
|
134
|
-
color: #ccc;
|
|
135
|
-
position: relative;
|
|
136
|
-
top: 6px;
|
|
137
|
-
}
|
|
138
|
-
placeholder:after {
|
|
139
|
-
content: "☁";
|
|
140
|
-
font-size: 200%;
|
|
141
|
-
line-height: 0.1;
|
|
142
|
-
font-weight: bold;
|
|
143
|
-
}
|
|
144
|
-
```
|
|
145
|
-
|
|
146
|
-
### Uploading images from a file picker
|
|
147
|
-
|
|
148
|
-
A small React example
|
|
149
|
-
|
|
150
|
-
In the "html" / JSX part:
|
|
151
|
-
```typescript jsx
|
|
152
|
-
<input type="file" id="imageselector" onChange={onInputChange} />
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
The `onInputChange` callback:
|
|
156
|
-
```typescript
|
|
157
|
-
const onInputChange = useCallback(
|
|
158
|
-
(e: ChangeEvent<HTMLInputElement>) => {
|
|
159
|
-
if (
|
|
160
|
-
pmView?.state.selection.$from.parent.inlineContent &&
|
|
161
|
-
e.target.files?.length
|
|
162
|
-
) {
|
|
163
|
-
const file = e.target.files[0];
|
|
164
|
-
startImageUpload(
|
|
165
|
-
pmView,
|
|
166
|
-
file,
|
|
167
|
-
file.name,
|
|
168
|
-
defaultSettings,
|
|
169
|
-
imageSchema,
|
|
170
|
-
pmView.state.selection.from,
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
[pmView],
|
|
175
|
-
);
|
|
176
|
-
```
|
|
102
|
+
| name | type | description |
|
|
103
|
+
|-------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------|
|
|
104
|
+
| createSelect | (settings: CodeBlockSettings, dom: HTMLElement, node: ProseMirrorNode, view: EditorView, getPos: (() => number) | boolean) => ()=> void) | Callback to create lanaguge selector. Returns function that is called when the NodeView is cleaned up. Has default. |
|
|
105
|
+
| updateSelect | (settings: CodeBlockSettings, dom: HTMLElement, node: ProseMirrorNode, view: EditorView, getPos: (() => number) | boolean, oldNode: ProseMirrorNode) => ()=> void) | Called when the codeblock node is updated. Should update the select value to reflect the `lang` property of the node. |
|
|
106
|
+
| languageLoaders | ?LanguageLoaders | Record of functions which return a code extension for a given language. |
|
|
107
|
+
| languageNameMap | ?Record<string, string> | Can be used to give aliases to languages in the selector. |
|
|
108
|
+
| languageWhitelist | ?string[] | List of used languages. |
|
|
109
|
+
| undo | (state: EditorState, dispatch: (tr: Transaction) => void) => void | Undo provided by `prosemirror-history`. YJS uses a different one! |
|
|
110
|
+
| redo | (state: EditorState, dispatch: (tr: Transaction) => void) => void | Redo provided by `prosemirror-history`. YJS uses a different one! |
|
|
111
|
+
| theme | Extension[] | Insert codemirror theme here. Or any other extension you want! |
|
|
177
112
|
|
|
178
113
|
### CSS & Styles
|
|
179
114
|
|
|
180
|
-
The following
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
## Development
|
|
115
|
+
The following is a good starter style for the language selector:
|
|
116
|
+
```css
|
|
117
|
+
.codeblock-select {
|
|
118
|
+
position: absolute;
|
|
119
|
+
right: 0;
|
|
120
|
+
z-index: 100;
|
|
121
|
+
opacity: 0;
|
|
122
|
+
transition: all 0.3s ease;
|
|
123
|
+
margin: 6px 14px;
|
|
124
|
+
}
|
|
125
|
+
.codeblock-root {
|
|
126
|
+
position: relative;
|
|
127
|
+
}
|
|
194
128
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
4. link the package from the project you want to use it: `npm run link prosemirror-image-plugin`
|
|
129
|
+
.codeblock-root:hover .codeblock-select {
|
|
130
|
+
opacity: 1;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
200
133
|
|
|
201
134
|
### About us
|
|
202
135
|
|
|
@@ -205,5 +138,4 @@ Emergence Engineering is dev shop from the EU:
|
|
|
205
138
|
|
|
206
139
|
We're looking for work, especially with ProseMirror ;)
|
|
207
140
|
|
|
208
|
-
Feel free to contact me at
|
|
209
|
-
<viktor.vaczi@emergence-engineering.com>
|
|
141
|
+
Feel free to contact me at viktor.vaczi@emergence-engineering.com
|