@tiptap/extension-invisible-characters 3.30.2 → 3.30.4

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/index.js CHANGED
@@ -1,20 +1,17 @@
1
- // src/invisible-characters.ts
2
1
  import { Extension } from "@tiptap/core";
3
-
4
- // src/plugin/InvisibleCharactersPlugin.ts
5
2
  import { AllSelection, Plugin, PluginKey } from "@tiptap/pm/state";
6
- import { DecorationSet } from "@tiptap/pm/view";
7
-
8
- // src/plugin/reducers.ts
9
- var stateReducer = (state, visible) => {
10
- if (visible === void 0) {
11
- return state;
12
- }
13
- return { ...state, visible };
3
+ import { Decoration, DecorationSet } from "@tiptap/pm/view";
4
+ //#region src/plugin/reducers.ts
5
+ const stateReducer = (state, visible) => {
6
+ if (visible === void 0) return state;
7
+ return {
8
+ ...state,
9
+ visible
10
+ };
14
11
  };
15
-
16
- // src/plugin/style.ts
17
- var style = `.tiptap-invisible-character {
12
+ //#endregion
13
+ //#region src/plugin/style.ts
14
+ const style = `.tiptap-invisible-character {
18
15
  height: 0;
19
16
  padding: 0;
20
17
  pointer-events: none;
@@ -33,15 +30,15 @@ var style = `.tiptap-invisible-character {
33
30
  }
34
31
 
35
32
  .tiptap-invisible-character--space::before {
36
- content: '\xB7'
33
+ content: '·'
37
34
  }
38
35
 
39
36
  .tiptap-invisible-character--break::before {
40
- content: '\xAC'
37
+ content: '¬'
41
38
  }
42
39
 
43
40
  .tiptap-invisible-character--paragraph::before {
44
- content: '\xB6'
41
+ content: ''
45
42
  }
46
43
 
47
44
  .tiptap-invisible-character + img.ProseMirror-separator {
@@ -55,273 +52,233 @@ var style = `.tiptap-invisible-character {
55
52
  display: none;
56
53
  }
57
54
  `;
58
-
59
- // src/plugin/utils/create-style-tag.ts
60
- var createStyleTag = (style2, nonce) => {
61
- const tiptapStyleTag = document.querySelector("style[data-tiptap-extension-invisible-characters-style]");
62
- if (tiptapStyleTag !== null) {
63
- return tiptapStyleTag;
64
- }
65
- const styleNode = document.createElement("style");
66
- if (nonce) {
67
- styleNode.setAttribute("nonce", nonce);
68
- }
69
- styleNode.setAttribute("data-tiptap-extension-invisible-characters-style", "");
70
- styleNode.innerHTML = style2;
71
- document.getElementsByTagName("head")[0].appendChild(styleNode);
72
- return styleNode;
55
+ //#endregion
56
+ //#region src/plugin/utils/create-style-tag.ts
57
+ const createStyleTag = (style, nonce) => {
58
+ const tiptapStyleTag = document.querySelector("style[data-tiptap-extension-invisible-characters-style]");
59
+ if (tiptapStyleTag !== null) return tiptapStyleTag;
60
+ const styleNode = document.createElement("style");
61
+ if (nonce) styleNode.setAttribute("nonce", nonce);
62
+ styleNode.setAttribute("data-tiptap-extension-invisible-characters-style", "");
63
+ styleNode.innerHTML = style;
64
+ document.getElementsByTagName("head")[0].appendChild(styleNode);
65
+ return styleNode;
73
66
  };
74
-
75
- // src/plugin/utils/get-updated-ranges.ts
76
- var getUpdatedRanges = ({ mapping }) => {
77
- const ranges = [];
78
- mapping.maps.forEach((stepMap, i) => {
79
- stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
80
- ranges.push([mapping.slice(i + 1).map(newStart), mapping.slice(i + 1).map(newEnd)]);
81
- });
82
- });
83
- return ranges;
67
+ //#endregion
68
+ //#region src/plugin/utils/get-updated-ranges.ts
69
+ const getUpdatedRanges = ({ mapping }) => {
70
+ const ranges = [];
71
+ mapping.maps.forEach((stepMap, i) => {
72
+ stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
73
+ ranges.push([mapping.slice(i + 1).map(newStart), mapping.slice(i + 1).map(newEnd)]);
74
+ });
75
+ });
76
+ return ranges;
84
77
  };
85
-
86
- // src/plugin/InvisibleCharactersPlugin.ts
87
- var InvisibleCharactersPluginKey = new PluginKey("invisibleCharacters");
88
- var InvisibleCharactersPlugin = (state, options) => {
89
- const key = InvisibleCharactersPluginKey;
90
- const emptyDecorationSet = DecorationSet.create(state.doc, []);
91
- const addDecorationsBetweenPositions = (from, to, editorState, decorations) => {
92
- return options.builders.sort((builderA, builderB) => {
93
- if (builderA.priority > builderB.priority) {
94
- return 1;
95
- }
96
- return -1;
97
- }).reduce((newDecos, builder) => {
98
- return builder.createDecoration(from, to, editorState.doc, newDecos);
99
- }, decorations);
100
- };
101
- return new Plugin({
102
- key,
103
- state: {
104
- init: () => {
105
- const { $from, $to } = new AllSelection(state.doc);
106
- if (options.injectCSS && document) {
107
- createStyleTag(style, options.injectNonce);
108
- }
109
- return {
110
- visible: options.visible,
111
- decorations: addDecorationsBetweenPositions(
112
- $from.pos,
113
- $to.pos,
114
- state,
115
- DecorationSet.empty
116
- )
117
- };
118
- },
119
- apply: (tr, pluginState, _, currentState) => {
120
- const newPluginState = stateReducer(
121
- pluginState,
122
- tr.getMeta("setInvisibleCharactersVisible")
123
- );
124
- const decorations = getUpdatedRanges(tr).reduce(
125
- (nextDecorations, [from, to]) => {
126
- return addDecorationsBetweenPositions(from, to, currentState, nextDecorations);
127
- },
128
- newPluginState.decorations.map(tr.mapping, tr.doc)
129
- );
130
- return {
131
- ...newPluginState,
132
- decorations
133
- };
134
- }
135
- },
136
- props: {
137
- decorations(editorState) {
138
- const pluginState = this.getState(editorState);
139
- const visible = pluginState == null ? void 0 : pluginState.visible;
140
- const decorations = pluginState == null ? void 0 : pluginState.decorations;
141
- return visible ? decorations : emptyDecorationSet;
142
- }
143
- }
144
- });
78
+ //#endregion
79
+ //#region src/plugin/InvisibleCharactersPlugin.ts
80
+ const InvisibleCharactersPluginKey = new PluginKey("invisibleCharacters");
81
+ const InvisibleCharactersPlugin = (state, options) => {
82
+ const key = InvisibleCharactersPluginKey;
83
+ const emptyDecorationSet = DecorationSet.create(state.doc, []);
84
+ const addDecorationsBetweenPositions = (from, to, editorState, decorations) => {
85
+ return options.builders.sort((builderA, builderB) => {
86
+ if (builderA.priority > builderB.priority) return 1;
87
+ return -1;
88
+ }).reduce((newDecos, builder) => {
89
+ return builder.createDecoration(from, to, editorState.doc, newDecos);
90
+ }, decorations);
91
+ };
92
+ return new Plugin({
93
+ key,
94
+ state: {
95
+ init: () => {
96
+ const { $from, $to } = new AllSelection(state.doc);
97
+ if (options.injectCSS && document) createStyleTag(style, options.injectNonce);
98
+ return {
99
+ visible: options.visible,
100
+ decorations: addDecorationsBetweenPositions($from.pos, $to.pos, state, DecorationSet.empty)
101
+ };
102
+ },
103
+ apply: (tr, pluginState, _, currentState) => {
104
+ const newPluginState = stateReducer(pluginState, tr.getMeta("setInvisibleCharactersVisible"));
105
+ const decorations = getUpdatedRanges(tr).reduce((nextDecorations, [from, to]) => {
106
+ return addDecorationsBetweenPositions(from, to, currentState, nextDecorations);
107
+ }, newPluginState.decorations.map(tr.mapping, tr.doc));
108
+ return {
109
+ ...newPluginState,
110
+ decorations
111
+ };
112
+ }
113
+ },
114
+ props: { decorations(editorState) {
115
+ const pluginState = this.getState(editorState);
116
+ const visible = pluginState === null || pluginState === void 0 ? void 0 : pluginState.visible;
117
+ const decorations = pluginState === null || pluginState === void 0 ? void 0 : pluginState.decorations;
118
+ return visible ? decorations : emptyDecorationSet;
119
+ } }
120
+ });
145
121
  };
146
-
147
- // src/plugin/utils/create-decoration-widget.ts
148
- import { Decoration } from "@tiptap/pm/view";
149
- var createDecorationWidget = (pos, type, content) => {
150
- const createElement = () => {
151
- const newElement = document.createElement("span");
152
- newElement.classList.add("tiptap-invisible-character");
153
- newElement.classList.add(`tiptap-invisible-character--${type}`);
154
- if (content) {
155
- newElement.textContent = content;
156
- }
157
- return newElement;
158
- };
159
- return Decoration.widget(pos, createElement, {
160
- key: type,
161
- marks: [],
162
- side: 1e3
163
- });
122
+ //#endregion
123
+ //#region src/plugin/utils/create-decoration-widget.ts
124
+ const createDecorationWidget = (pos, type, content) => {
125
+ const createElement = () => {
126
+ const newElement = document.createElement("span");
127
+ newElement.classList.add("tiptap-invisible-character");
128
+ newElement.classList.add(`tiptap-invisible-character--${type}`);
129
+ if (content) newElement.textContent = content;
130
+ return newElement;
131
+ };
132
+ return Decoration.widget(pos, createElement, {
133
+ key: type,
134
+ marks: [],
135
+ side: 1e3
136
+ });
164
137
  };
165
-
166
- // src/plugin/InvisibleNode.ts
167
- var defaultPosition = (node, pos) => pos + node.nodeSize - 1;
138
+ //#endregion
139
+ //#region src/plugin/InvisibleNode.ts
140
+ /** Default position for nodes is always at the end of the node */
141
+ const defaultPosition = (node, pos) => pos + node.nodeSize - 1;
168
142
  var InvisibleNode = class {
169
- constructor(options) {
170
- this.predicate = options.predicate;
171
- this.type = options.type;
172
- this.position = options.position || defaultPosition;
173
- this.content = options.content;
174
- this.priority = options.priority || 100;
175
- }
176
- createDecoration(from, to, doc, decorations) {
177
- let newDecorations = decorations;
178
- doc.nodesBetween(from, to, (node, pos) => {
179
- if (this.test(node)) {
180
- const decorationPosition = this.position(node, pos);
181
- const oldDecorations = newDecorations.find(
182
- decorationPosition,
183
- decorationPosition,
184
- (spec) => spec.key === this.type
185
- );
186
- newDecorations = newDecorations.remove(oldDecorations).add(doc, [createDecorationWidget(decorationPosition, this.type, this.content)]);
187
- }
188
- });
189
- return newDecorations;
190
- }
191
- test(value) {
192
- return this.predicate(value);
193
- }
143
+ constructor(options) {
144
+ this.predicate = options.predicate;
145
+ this.type = options.type;
146
+ this.position = options.position || defaultPosition;
147
+ this.content = options.content;
148
+ this.priority = options.priority || 100;
149
+ }
150
+ createDecoration(from, to, doc, decorations) {
151
+ let newDecorations = decorations;
152
+ doc.nodesBetween(from, to, (node, pos) => {
153
+ if (this.test(node)) {
154
+ const decorationPosition = this.position(node, pos);
155
+ const oldDecorations = newDecorations.find(decorationPosition, decorationPosition, (spec) => spec.key === this.type);
156
+ newDecorations = newDecorations.remove(oldDecorations).add(doc, [createDecorationWidget(decorationPosition, this.type, this.content)]);
157
+ }
158
+ });
159
+ return newDecorations;
160
+ }
161
+ test(value) {
162
+ return this.predicate(value);
163
+ }
194
164
  };
195
-
196
- // src/plugin/invisible-characters/hardBreak.ts
165
+ //#endregion
166
+ //#region src/plugin/invisible-characters/hardBreak.ts
197
167
  var HardBreakNode = class extends InvisibleNode {
198
- constructor() {
199
- super({
200
- type: "break",
201
- predicate: (node) => node.type === node.type.schema.nodes.hardBreak
202
- });
203
- }
168
+ constructor() {
169
+ super({
170
+ type: "break",
171
+ predicate: (node) => node.type === node.type.schema.nodes.hardBreak
172
+ });
173
+ }
204
174
  };
205
-
206
- // src/plugin/invisible-characters/paragraph.ts
175
+ //#endregion
176
+ //#region src/plugin/invisible-characters/paragraph.ts
207
177
  var ParagraphNode = class extends InvisibleNode {
208
- constructor() {
209
- super({
210
- type: "paragraph",
211
- predicate: (node) => node.type === node.type.schema.nodes.paragraph
212
- });
213
- }
178
+ constructor() {
179
+ super({
180
+ type: "paragraph",
181
+ predicate: (node) => node.type === node.type.schema.nodes.paragraph
182
+ });
183
+ }
214
184
  };
215
-
216
- // src/plugin/utils/text-between.ts
217
- var textBetween = (from, to, doc) => {
218
- const positions = [];
219
- doc.nodesBetween(from, to, (node, pos) => {
220
- var _a;
221
- if (node.isText) {
222
- const offset = Math.max(from, pos) - pos;
223
- positions.push({
224
- pos: pos + offset,
225
- text: ((_a = node.text) == null ? void 0 : _a.slice(offset, to - pos)) || ""
226
- });
227
- }
228
- });
229
- return positions;
185
+ //#endregion
186
+ //#region src/plugin/utils/text-between.ts
187
+ const textBetween = (from, to, doc) => {
188
+ const positions = [];
189
+ doc.nodesBetween(from, to, (node, pos) => {
190
+ if (node.isText) {
191
+ var _node$text;
192
+ const offset = Math.max(from, pos) - pos;
193
+ positions.push({
194
+ pos: pos + offset,
195
+ text: ((_node$text = node.text) === null || _node$text === void 0 ? void 0 : _node$text.slice(offset, to - pos)) || ""
196
+ });
197
+ }
198
+ });
199
+ return positions;
230
200
  };
231
-
232
- // src/plugin/InvisibleCharacter.ts
201
+ //#endregion
202
+ //#region src/plugin/InvisibleCharacter.ts
233
203
  var InvisibleCharacter = class {
234
- constructor(options) {
235
- this.predicate = options.predicate;
236
- this.type = options.type;
237
- this.content = options.content;
238
- this.priority = options.priority || 100;
239
- }
240
- createDecoration(from, to, doc, decorations) {
241
- const textContent = textBetween(from, to, doc);
242
- return textContent.reduce((oldDecorations, currentPosition) => {
243
- return currentPosition.text.split("").reduce((innerDecorations, char, i) => {
244
- return this.test(char) ? innerDecorations.add(doc, [
245
- createDecorationWidget(currentPosition.pos + i, this.type, this.content)
246
- ]) : innerDecorations;
247
- }, oldDecorations);
248
- }, decorations);
249
- }
250
- test(value) {
251
- return this.predicate(value);
252
- }
204
+ constructor(options) {
205
+ this.predicate = options.predicate;
206
+ this.type = options.type;
207
+ this.content = options.content;
208
+ this.priority = options.priority || 100;
209
+ }
210
+ createDecoration(from, to, doc, decorations) {
211
+ return textBetween(from, to, doc).reduce((oldDecorations, currentPosition) => {
212
+ return currentPosition.text.split("").reduce((innerDecorations, char, i) => {
213
+ return this.test(char) ? innerDecorations.add(doc, [createDecorationWidget(currentPosition.pos + i, this.type, this.content)]) : innerDecorations;
214
+ }, oldDecorations);
215
+ }, decorations);
216
+ }
217
+ test(value) {
218
+ return this.predicate(value);
219
+ }
253
220
  };
254
-
255
- // src/plugin/invisible-characters/space.ts
221
+ //#endregion
222
+ //#region src/plugin/invisible-characters/space.ts
256
223
  var SpaceCharacter = class extends InvisibleCharacter {
257
- constructor() {
258
- super({
259
- type: "space",
260
- predicate: (char) => char === " "
261
- });
262
- }
224
+ constructor() {
225
+ super({
226
+ type: "space",
227
+ predicate: (char) => char === " "
228
+ });
229
+ }
263
230
  };
264
-
265
- // src/invisible-characters.ts
266
- var InvisibleCharacters = Extension.create({
267
- name: "invisibleCharacters",
268
- addOptions() {
269
- return {
270
- visible: true,
271
- builders: [new SpaceCharacter(), new ParagraphNode(), new HardBreakNode()],
272
- injectCSS: true,
273
- injectNonce: void 0
274
- };
275
- },
276
- addProseMirrorPlugins() {
277
- return [InvisibleCharactersPlugin(this.editor.state, this.options)];
278
- },
279
- addStorage() {
280
- return {
281
- visibility: () => this.options.visible
282
- };
283
- },
284
- onBeforeCreate() {
285
- this.storage.visibility = () => {
286
- var _a;
287
- return (_a = InvisibleCharactersPluginKey.getState(this.editor.state)) == null ? void 0 : _a.visible;
288
- };
289
- },
290
- addCommands() {
291
- return {
292
- showInvisibleCharacters: (visibility = true) => ({ dispatch, tr }) => {
293
- if (dispatch) {
294
- tr.setMeta("setInvisibleCharactersVisible", visibility);
295
- }
296
- return true;
297
- },
298
- hideInvisibleCharacters: () => ({ dispatch, tr }) => {
299
- if (dispatch) {
300
- tr.setMeta("setInvisibleCharactersVisible", false);
301
- }
302
- return true;
303
- },
304
- toggleInvisibleCharacters: () => ({ dispatch, tr, state }) => {
305
- var _a;
306
- const visibility = !((_a = InvisibleCharactersPluginKey.getState(state)) == null ? void 0 : _a.visible);
307
- if (dispatch) {
308
- tr.setMeta("setInvisibleCharactersVisible", visibility);
309
- }
310
- return true;
311
- }
312
- };
313
- }
231
+ //#endregion
232
+ //#region src/invisible-characters.ts
233
+ const InvisibleCharacters = Extension.create({
234
+ name: "invisibleCharacters",
235
+ addOptions() {
236
+ return {
237
+ visible: true,
238
+ builders: [
239
+ new SpaceCharacter(),
240
+ new ParagraphNode(),
241
+ new HardBreakNode()
242
+ ],
243
+ injectCSS: true,
244
+ injectNonce: void 0
245
+ };
246
+ },
247
+ addProseMirrorPlugins() {
248
+ return [InvisibleCharactersPlugin(this.editor.state, this.options)];
249
+ },
250
+ addStorage() {
251
+ return { visibility: () => this.options.visible };
252
+ },
253
+ onBeforeCreate() {
254
+ this.storage.visibility = () => {
255
+ var _InvisibleCharactersP;
256
+ return (_InvisibleCharactersP = InvisibleCharactersPluginKey.getState(this.editor.state)) === null || _InvisibleCharactersP === void 0 ? void 0 : _InvisibleCharactersP.visible;
257
+ };
258
+ },
259
+ addCommands() {
260
+ return {
261
+ showInvisibleCharacters: (visibility = true) => ({ dispatch, tr }) => {
262
+ if (dispatch) tr.setMeta("setInvisibleCharactersVisible", visibility);
263
+ return true;
264
+ },
265
+ hideInvisibleCharacters: () => ({ dispatch, tr }) => {
266
+ if (dispatch) tr.setMeta("setInvisibleCharactersVisible", false);
267
+ return true;
268
+ },
269
+ toggleInvisibleCharacters: () => ({ dispatch, tr, state }) => {
270
+ var _InvisibleCharactersP2;
271
+ const visibility = !((_InvisibleCharactersP2 = InvisibleCharactersPluginKey.getState(state)) === null || _InvisibleCharactersP2 === void 0 ? void 0 : _InvisibleCharactersP2.visible);
272
+ if (dispatch) tr.setMeta("setInvisibleCharactersVisible", visibility);
273
+ return true;
274
+ }
275
+ };
276
+ }
314
277
  });
278
+ //#endregion
279
+ //#region src/index.ts
280
+ var src_default = InvisibleCharacters;
281
+ //#endregion
282
+ export { HardBreakNode, InvisibleCharacter, InvisibleCharacters, InvisibleNode, ParagraphNode, SpaceCharacter, src_default as default };
315
283
 
316
- // src/index.ts
317
- var index_default = InvisibleCharacters;
318
- export {
319
- HardBreakNode,
320
- InvisibleCharacter,
321
- InvisibleCharacters,
322
- InvisibleNode,
323
- ParagraphNode,
324
- SpaceCharacter,
325
- index_default as default
326
- };
327
284
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/invisible-characters.ts","../src/plugin/InvisibleCharactersPlugin.ts","../src/plugin/reducers.ts","../src/plugin/style.ts","../src/plugin/utils/create-style-tag.ts","../src/plugin/utils/get-updated-ranges.ts","../src/plugin/utils/create-decoration-widget.ts","../src/plugin/InvisibleNode.ts","../src/plugin/invisible-characters/hardBreak.ts","../src/plugin/invisible-characters/paragraph.ts","../src/plugin/utils/text-between.ts","../src/plugin/InvisibleCharacter.ts","../src/plugin/invisible-characters/space.ts","../src/index.ts"],"sourcesContent":["import { Extension } from '@tiptap/core'\n\nimport { InvisibleCharactersPlugin, InvisibleCharactersPluginKey } from './plugin/index.js'\nimport { HardBreakNode } from './plugin/invisible-characters/hardBreak.js'\nimport { ParagraphNode } from './plugin/invisible-characters/paragraph.js'\nimport { SpaceCharacter } from './plugin/invisible-characters/space.js'\nimport type { InvisibleCharactersOptions } from './types.js'\n\nexport { HardBreakNode, ParagraphNode, SpaceCharacter }\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n invisibleCharacters: {\n /**\n * Show invisible characters\n */\n showInvisibleCharacters: (show?: boolean) => ReturnType\n\n /**\n * Hide invisible characters\n */\n hideInvisibleCharacters: () => ReturnType\n\n /**\n * Toggle invisible characters\n */\n toggleInvisibleCharacters: () => ReturnType\n }\n }\n}\n\nexport const InvisibleCharacters = Extension.create<InvisibleCharactersOptions>({\n name: 'invisibleCharacters',\n\n addOptions() {\n return {\n visible: true,\n builders: [new SpaceCharacter(), new ParagraphNode(), new HardBreakNode()],\n injectCSS: true,\n injectNonce: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n return [InvisibleCharactersPlugin(this.editor.state, this.options)]\n },\n\n addStorage() {\n return {\n visibility: () => this.options.visible,\n }\n },\n\n onBeforeCreate() {\n this.storage.visibility = () => {\n return InvisibleCharactersPluginKey.getState(this.editor.state)?.visible\n }\n },\n\n addCommands() {\n return {\n showInvisibleCharacters:\n (visibility = true) =>\n ({ dispatch, tr }) => {\n if (dispatch) {\n tr.setMeta('setInvisibleCharactersVisible', visibility)\n }\n\n return true\n },\n hideInvisibleCharacters:\n () =>\n ({ dispatch, tr }) => {\n if (dispatch) {\n tr.setMeta('setInvisibleCharactersVisible', false)\n }\n\n return true\n },\n toggleInvisibleCharacters:\n () =>\n ({ dispatch, tr, state }) => {\n const visibility = !InvisibleCharactersPluginKey.getState(state)?.visible\n\n if (dispatch) {\n tr.setMeta('setInvisibleCharactersVisible', visibility)\n }\n\n return true\n },\n }\n },\n})\n\nexport default InvisibleCharacters\n","import type { EditorState } from '@tiptap/pm/state'\nimport { AllSelection, Plugin, PluginKey } from '@tiptap/pm/state'\nimport { DecorationSet } from '@tiptap/pm/view'\n\nimport type { InvisibleCharactersOptions, PluginState } from '../types.js'\nimport { stateReducer } from './reducers.js'\nimport { style } from './style.js'\nimport { createStyleTag } from './utils/create-style-tag.js'\nimport { getUpdatedRanges } from './utils/get-updated-ranges.js'\n\nexport const InvisibleCharactersPluginKey = new PluginKey<PluginState>('invisibleCharacters')\n\nexport const InvisibleCharactersPlugin = (\n state: EditorState,\n options: InvisibleCharactersOptions,\n) => {\n const key = InvisibleCharactersPluginKey\n const emptyDecorationSet = DecorationSet.create(state.doc, [])\n\n const addDecorationsBetweenPositions = (\n from: number,\n to: number,\n editorState: EditorState,\n decorations: DecorationSet,\n ) => {\n return options.builders\n .sort((builderA, builderB) => {\n if (builderA.priority > builderB.priority) {\n return 1\n }\n\n return -1\n })\n .reduce((newDecos, builder) => {\n return builder.createDecoration(from, to, editorState.doc, newDecos)\n }, decorations)\n }\n\n return new Plugin({\n key,\n\n state: {\n init: () => {\n const { $from, $to } = new AllSelection(state.doc)\n\n if (options.injectCSS && document) {\n createStyleTag(style, options.injectNonce)\n }\n\n return {\n visible: options.visible,\n decorations: addDecorationsBetweenPositions(\n $from.pos,\n $to.pos,\n state,\n DecorationSet.empty,\n ),\n }\n },\n apply: (tr, pluginState, _, currentState) => {\n const newPluginState = stateReducer(\n pluginState,\n tr.getMeta('setInvisibleCharactersVisible'),\n )\n\n const decorations = getUpdatedRanges(tr).reduce(\n (nextDecorations, [from, to]) => {\n return addDecorationsBetweenPositions(from, to, currentState, nextDecorations)\n },\n newPluginState.decorations.map(tr.mapping, tr.doc),\n )\n\n return {\n ...newPluginState,\n decorations,\n }\n },\n },\n\n props: {\n decorations(editorState) {\n const pluginState = this.getState(editorState)\n\n const visible = pluginState?.visible\n const decorations = pluginState?.decorations\n\n return visible ? decorations : emptyDecorationSet\n },\n },\n })\n}\n\nexport default InvisibleCharactersPlugin\n","import type { PluginState } from '../types.js'\n\nexport const stateReducer = (state: PluginState, visible: boolean): PluginState => {\n if (visible === undefined) {\n return state\n }\n\n return { ...state, visible }\n}\n\nexport default stateReducer\n","export const style = `.tiptap-invisible-character {\n height: 0;\n padding: 0;\n pointer-events: none;\n user-select: none;\n width: 0;\n}\n\n.tiptap-invisible-character::before {\n caret-color: inherit;\n color: #aaa;\n display: inline-block;\n font-style: normal;\n font-weight: 400;\n line-height: 1em;\n width: 0;\n}\n\n.tiptap-invisible-character--space::before {\n content: '·'\n}\n\n.tiptap-invisible-character--break::before {\n content: '¬'\n}\n\n.tiptap-invisible-character--paragraph::before {\n content: '¶'\n}\n\n.tiptap-invisible-character + img.ProseMirror-separator {\n height: 0 !important;\n pointer-events: none;\n user-select: none;\n width: 0 !important;\n}\n\n.is-empty[data-placeholder].has-focus > .tiptap-invisible-character {\n display: none;\n}\n`\n\nexport default style\n","export const createStyleTag = (style: string, nonce?: string): HTMLStyleElement => {\n const tiptapStyleTag = <HTMLStyleElement>(\n document.querySelector('style[data-tiptap-extension-invisible-characters-style]')\n )\n\n if (tiptapStyleTag !== null) {\n return tiptapStyleTag\n }\n\n const styleNode = document.createElement('style')\n\n if (nonce) {\n styleNode.setAttribute('nonce', nonce)\n }\n\n styleNode.setAttribute('data-tiptap-extension-invisible-characters-style', '')\n styleNode.innerHTML = style\n document.getElementsByTagName('head')[0].appendChild(styleNode)\n\n return styleNode\n}\n\nexport default createStyleTag\n","import type { Transaction } from '@tiptap/pm/state'\n\ntype StepRange = [from: number, to: number]\n\nexport const getUpdatedRanges = ({ mapping }: Transaction): StepRange[] => {\n const ranges: StepRange[] = []\n\n mapping.maps.forEach((stepMap, i) => {\n stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {\n ranges.push([mapping.slice(i + 1).map(newStart), mapping.slice(i + 1).map(newEnd)])\n })\n })\n\n return ranges\n}\n\nexport default getUpdatedRanges\n","import { Decoration } from '@tiptap/pm/view'\n\nexport const createDecorationWidget = (pos: number, type: string, content?: string) => {\n const createElement = () => {\n const newElement = document.createElement('span')\n\n newElement.classList.add('tiptap-invisible-character')\n newElement.classList.add(`tiptap-invisible-character--${type}`)\n\n if (content) {\n newElement.textContent = content\n }\n\n return newElement\n }\n\n return Decoration.widget(pos, createElement, {\n key: type,\n marks: [],\n side: 1000,\n })\n}\n\nexport default createDecorationWidget\n","import type { Node } from '@tiptap/pm/model'\nimport type { DecorationSet } from '@tiptap/pm/view'\n\nimport { createDecorationWidget } from './utils/create-decoration-widget.js'\n\nexport interface InvisibleNodeOptions {\n content?: string\n position?: (node: Node, pos: number) => number\n predicate: (value: Node) => boolean\n priority?: number\n type: string\n}\n\n/** Default position for nodes is always at the end of the node */\nconst defaultPosition = (node: Node, pos: number) => pos + node.nodeSize - 1\n\nexport class InvisibleNode {\n predicate: (value: Node) => boolean\n\n position: (node: Node, pos: number) => number\n\n content?: string\n\n type: string\n\n priority: number\n\n constructor(options: InvisibleNodeOptions) {\n this.predicate = options.predicate\n this.type = options.type\n this.position = options.position || defaultPosition\n this.content = options.content\n this.priority = options.priority || 100\n }\n\n createDecoration(from: number, to: number, doc: Node, decorations: DecorationSet) {\n let newDecorations = decorations\n\n doc.nodesBetween(from, to, (node, pos) => {\n if (this.test(node)) {\n const decorationPosition = this.position(node, pos)\n const oldDecorations = newDecorations.find(\n decorationPosition,\n decorationPosition,\n spec => spec.key === this.type,\n )\n\n newDecorations = newDecorations\n .remove(oldDecorations)\n .add(doc, [createDecorationWidget(decorationPosition, this.type, this.content)])\n }\n })\n return newDecorations\n }\n\n test(value: Node) {\n return this.predicate(value)\n }\n}\n\nexport default InvisibleNode\n","import { InvisibleNode } from '../InvisibleNode.js'\n\nexport class HardBreakNode extends InvisibleNode {\n constructor() {\n super({\n type: 'break',\n predicate: node => node.type === node.type.schema.nodes.hardBreak,\n })\n }\n}\n\nexport default HardBreakNode\n","import { InvisibleNode } from '../InvisibleNode.js'\n\nexport class ParagraphNode extends InvisibleNode {\n constructor() {\n super({\n type: 'paragraph',\n predicate: node => node.type === node.type.schema.nodes.paragraph,\n })\n }\n}\n\nexport default ParagraphNode\n","import type { Node } from '@tiptap/pm/model'\n\nimport type { Position } from '../../types.js'\n\nexport const textBetween = (from: number, to: number, doc: Node) => {\n const positions: Position[] = []\n\n doc.nodesBetween(from, to, (node, pos) => {\n if (node.isText) {\n const offset = Math.max(from, pos) - pos\n\n positions.push({\n pos: pos + offset,\n text: node.text?.slice(offset, to - pos) || '',\n })\n }\n })\n\n return positions\n}\n\nexport default textBetween\n","import type { Node } from '@tiptap/pm/model'\nimport type { DecorationSet } from '@tiptap/pm/view'\n\nimport { createDecorationWidget } from './utils/create-decoration-widget.js'\nimport { textBetween } from './utils/text-between.js'\n\nexport interface InvisibleCharacterOptions {\n type: string\n predicate: (value: string) => boolean\n priority?: number\n content?: string\n}\n\nexport class InvisibleCharacter {\n predicate: (value: string) => boolean\n\n content?: string\n\n type: string\n\n priority: number\n\n constructor(options: InvisibleCharacterOptions) {\n this.predicate = options.predicate\n this.type = options.type\n this.content = options.content\n this.priority = options.priority || 100\n }\n\n createDecoration(from: number, to: number, doc: Node, decorations: DecorationSet) {\n const textContent = textBetween(from, to, doc)\n\n return textContent.reduce((oldDecorations, currentPosition) => {\n return currentPosition.text.split('').reduce((innerDecorations, char, i) => {\n return this.test(char)\n ? innerDecorations.add(doc, [\n createDecorationWidget(currentPosition.pos + i, this.type, this.content),\n ])\n : innerDecorations\n }, oldDecorations)\n }, decorations)\n }\n\n test(value: string) {\n return this.predicate(value)\n }\n}\n\nexport default InvisibleCharacter\n","import { InvisibleCharacter } from '../InvisibleCharacter.js'\n\nexport class SpaceCharacter extends InvisibleCharacter {\n constructor() {\n super({\n type: 'space',\n predicate: (char: string) => char === ' ',\n })\n }\n}\n\nexport default SpaceCharacter\n","import { InvisibleCharacters } from './invisible-characters.js'\n\nexport * from './invisible-characters.js'\nexport * from './plugin/invisible-characters/hardBreak.js'\nexport * from './plugin/invisible-characters/paragraph.js'\nexport * from './plugin/invisible-characters/space.js'\nexport * from './plugin/InvisibleCharacter.js'\nexport * from './plugin/InvisibleNode.js'\nexport * from './types.js'\n\nexport default InvisibleCharacters\n"],"mappings":"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","names":["style"]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/plugin/reducers.ts","../src/plugin/style.ts","../src/plugin/utils/create-style-tag.ts","../src/plugin/utils/get-updated-ranges.ts","../src/plugin/InvisibleCharactersPlugin.ts","../src/plugin/utils/create-decoration-widget.ts","../src/plugin/InvisibleNode.ts","../src/plugin/invisible-characters/hardBreak.ts","../src/plugin/invisible-characters/paragraph.ts","../src/plugin/utils/text-between.ts","../src/plugin/InvisibleCharacter.ts","../src/plugin/invisible-characters/space.ts","../src/invisible-characters.ts","../src/index.ts"],"sourcesContent":["import type { PluginState } from '../types.js'\n\nexport const stateReducer = (state: PluginState, visible: boolean): PluginState => {\n if (visible === undefined) {\n return state\n }\n\n return { ...state, visible }\n}\n\nexport default stateReducer\n","export const style = `.tiptap-invisible-character {\n height: 0;\n padding: 0;\n pointer-events: none;\n user-select: none;\n width: 0;\n}\n\n.tiptap-invisible-character::before {\n caret-color: inherit;\n color: #aaa;\n display: inline-block;\n font-style: normal;\n font-weight: 400;\n line-height: 1em;\n width: 0;\n}\n\n.tiptap-invisible-character--space::before {\n content: '·'\n}\n\n.tiptap-invisible-character--break::before {\n content: '¬'\n}\n\n.tiptap-invisible-character--paragraph::before {\n content: '¶'\n}\n\n.tiptap-invisible-character + img.ProseMirror-separator {\n height: 0 !important;\n pointer-events: none;\n user-select: none;\n width: 0 !important;\n}\n\n.is-empty[data-placeholder].has-focus > .tiptap-invisible-character {\n display: none;\n}\n`\n\nexport default style\n","export const createStyleTag = (style: string, nonce?: string): HTMLStyleElement => {\n const tiptapStyleTag = <HTMLStyleElement>(\n document.querySelector('style[data-tiptap-extension-invisible-characters-style]')\n )\n\n if (tiptapStyleTag !== null) {\n return tiptapStyleTag\n }\n\n const styleNode = document.createElement('style')\n\n if (nonce) {\n styleNode.setAttribute('nonce', nonce)\n }\n\n styleNode.setAttribute('data-tiptap-extension-invisible-characters-style', '')\n styleNode.innerHTML = style\n document.getElementsByTagName('head')[0].appendChild(styleNode)\n\n return styleNode\n}\n\nexport default createStyleTag\n","import type { Transaction } from '@tiptap/pm/state'\n\ntype StepRange = [from: number, to: number]\n\nexport const getUpdatedRanges = ({ mapping }: Transaction): StepRange[] => {\n const ranges: StepRange[] = []\n\n mapping.maps.forEach((stepMap, i) => {\n stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {\n ranges.push([mapping.slice(i + 1).map(newStart), mapping.slice(i + 1).map(newEnd)])\n })\n })\n\n return ranges\n}\n\nexport default getUpdatedRanges\n","import type { EditorState } from '@tiptap/pm/state'\nimport { AllSelection, Plugin, PluginKey } from '@tiptap/pm/state'\nimport { DecorationSet } from '@tiptap/pm/view'\n\nimport type { InvisibleCharactersOptions, PluginState } from '../types.js'\nimport { stateReducer } from './reducers.js'\nimport { style } from './style.js'\nimport { createStyleTag } from './utils/create-style-tag.js'\nimport { getUpdatedRanges } from './utils/get-updated-ranges.js'\n\nexport const InvisibleCharactersPluginKey = new PluginKey<PluginState>('invisibleCharacters')\n\nexport const InvisibleCharactersPlugin = (\n state: EditorState,\n options: InvisibleCharactersOptions,\n) => {\n const key = InvisibleCharactersPluginKey\n const emptyDecorationSet = DecorationSet.create(state.doc, [])\n\n const addDecorationsBetweenPositions = (\n from: number,\n to: number,\n editorState: EditorState,\n decorations: DecorationSet,\n ) => {\n return options.builders\n .sort((builderA, builderB) => {\n if (builderA.priority > builderB.priority) {\n return 1\n }\n\n return -1\n })\n .reduce((newDecos, builder) => {\n return builder.createDecoration(from, to, editorState.doc, newDecos)\n }, decorations)\n }\n\n return new Plugin({\n key,\n\n state: {\n init: () => {\n const { $from, $to } = new AllSelection(state.doc)\n\n if (options.injectCSS && document) {\n createStyleTag(style, options.injectNonce)\n }\n\n return {\n visible: options.visible,\n decorations: addDecorationsBetweenPositions(\n $from.pos,\n $to.pos,\n state,\n DecorationSet.empty,\n ),\n }\n },\n apply: (tr, pluginState, _, currentState) => {\n const newPluginState = stateReducer(\n pluginState,\n tr.getMeta('setInvisibleCharactersVisible'),\n )\n\n const decorations = getUpdatedRanges(tr).reduce(\n (nextDecorations, [from, to]) => {\n return addDecorationsBetweenPositions(from, to, currentState, nextDecorations)\n },\n newPluginState.decorations.map(tr.mapping, tr.doc),\n )\n\n return {\n ...newPluginState,\n decorations,\n }\n },\n },\n\n props: {\n decorations(editorState) {\n const pluginState = this.getState(editorState)\n\n const visible = pluginState?.visible\n const decorations = pluginState?.decorations\n\n return visible ? decorations : emptyDecorationSet\n },\n },\n })\n}\n\nexport default InvisibleCharactersPlugin\n","import { Decoration } from '@tiptap/pm/view'\n\nexport const createDecorationWidget = (pos: number, type: string, content?: string) => {\n const createElement = () => {\n const newElement = document.createElement('span')\n\n newElement.classList.add('tiptap-invisible-character')\n newElement.classList.add(`tiptap-invisible-character--${type}`)\n\n if (content) {\n newElement.textContent = content\n }\n\n return newElement\n }\n\n return Decoration.widget(pos, createElement, {\n key: type,\n marks: [],\n side: 1000,\n })\n}\n\nexport default createDecorationWidget\n","import type { Node } from '@tiptap/pm/model'\nimport type { DecorationSet } from '@tiptap/pm/view'\n\nimport { createDecorationWidget } from './utils/create-decoration-widget.js'\n\nexport interface InvisibleNodeOptions {\n content?: string\n position?: (node: Node, pos: number) => number\n predicate: (value: Node) => boolean\n priority?: number\n type: string\n}\n\n/** Default position for nodes is always at the end of the node */\nconst defaultPosition = (node: Node, pos: number) => pos + node.nodeSize - 1\n\nexport class InvisibleNode {\n predicate: (value: Node) => boolean\n\n position: (node: Node, pos: number) => number\n\n content?: string\n\n type: string\n\n priority: number\n\n constructor(options: InvisibleNodeOptions) {\n this.predicate = options.predicate\n this.type = options.type\n this.position = options.position || defaultPosition\n this.content = options.content\n this.priority = options.priority || 100\n }\n\n createDecoration(from: number, to: number, doc: Node, decorations: DecorationSet) {\n let newDecorations = decorations\n\n doc.nodesBetween(from, to, (node, pos) => {\n if (this.test(node)) {\n const decorationPosition = this.position(node, pos)\n const oldDecorations = newDecorations.find(\n decorationPosition,\n decorationPosition,\n spec => spec.key === this.type,\n )\n\n newDecorations = newDecorations\n .remove(oldDecorations)\n .add(doc, [createDecorationWidget(decorationPosition, this.type, this.content)])\n }\n })\n return newDecorations\n }\n\n test(value: Node) {\n return this.predicate(value)\n }\n}\n\nexport default InvisibleNode\n","import { InvisibleNode } from '../InvisibleNode.js'\n\nexport class HardBreakNode extends InvisibleNode {\n constructor() {\n super({\n type: 'break',\n predicate: node => node.type === node.type.schema.nodes.hardBreak,\n })\n }\n}\n\nexport default HardBreakNode\n","import { InvisibleNode } from '../InvisibleNode.js'\n\nexport class ParagraphNode extends InvisibleNode {\n constructor() {\n super({\n type: 'paragraph',\n predicate: node => node.type === node.type.schema.nodes.paragraph,\n })\n }\n}\n\nexport default ParagraphNode\n","import type { Node } from '@tiptap/pm/model'\n\nimport type { Position } from '../../types.js'\n\nexport const textBetween = (from: number, to: number, doc: Node) => {\n const positions: Position[] = []\n\n doc.nodesBetween(from, to, (node, pos) => {\n if (node.isText) {\n const offset = Math.max(from, pos) - pos\n\n positions.push({\n pos: pos + offset,\n text: node.text?.slice(offset, to - pos) || '',\n })\n }\n })\n\n return positions\n}\n\nexport default textBetween\n","import type { Node } from '@tiptap/pm/model'\nimport type { DecorationSet } from '@tiptap/pm/view'\n\nimport { createDecorationWidget } from './utils/create-decoration-widget.js'\nimport { textBetween } from './utils/text-between.js'\n\nexport interface InvisibleCharacterOptions {\n type: string\n predicate: (value: string) => boolean\n priority?: number\n content?: string\n}\n\nexport class InvisibleCharacter {\n predicate: (value: string) => boolean\n\n content?: string\n\n type: string\n\n priority: number\n\n constructor(options: InvisibleCharacterOptions) {\n this.predicate = options.predicate\n this.type = options.type\n this.content = options.content\n this.priority = options.priority || 100\n }\n\n createDecoration(from: number, to: number, doc: Node, decorations: DecorationSet) {\n const textContent = textBetween(from, to, doc)\n\n return textContent.reduce((oldDecorations, currentPosition) => {\n return currentPosition.text.split('').reduce((innerDecorations, char, i) => {\n return this.test(char)\n ? innerDecorations.add(doc, [\n createDecorationWidget(currentPosition.pos + i, this.type, this.content),\n ])\n : innerDecorations\n }, oldDecorations)\n }, decorations)\n }\n\n test(value: string) {\n return this.predicate(value)\n }\n}\n\nexport default InvisibleCharacter\n","import { InvisibleCharacter } from '../InvisibleCharacter.js'\n\nexport class SpaceCharacter extends InvisibleCharacter {\n constructor() {\n super({\n type: 'space',\n predicate: (char: string) => char === ' ',\n })\n }\n}\n\nexport default SpaceCharacter\n","import { Extension } from '@tiptap/core'\n\nimport { InvisibleCharactersPlugin, InvisibleCharactersPluginKey } from './plugin/index.js'\nimport { HardBreakNode } from './plugin/invisible-characters/hardBreak.js'\nimport { ParagraphNode } from './plugin/invisible-characters/paragraph.js'\nimport { SpaceCharacter } from './plugin/invisible-characters/space.js'\nimport type { InvisibleCharactersOptions } from './types.js'\n\nexport { HardBreakNode, ParagraphNode, SpaceCharacter }\n\ndeclare module '@tiptap/core' {\n interface Commands<ReturnType> {\n invisibleCharacters: {\n /**\n * Show invisible characters\n */\n showInvisibleCharacters: (show?: boolean) => ReturnType\n\n /**\n * Hide invisible characters\n */\n hideInvisibleCharacters: () => ReturnType\n\n /**\n * Toggle invisible characters\n */\n toggleInvisibleCharacters: () => ReturnType\n }\n }\n}\n\nexport const InvisibleCharacters = Extension.create<InvisibleCharactersOptions>({\n name: 'invisibleCharacters',\n\n addOptions() {\n return {\n visible: true,\n builders: [new SpaceCharacter(), new ParagraphNode(), new HardBreakNode()],\n injectCSS: true,\n injectNonce: undefined,\n }\n },\n\n addProseMirrorPlugins() {\n return [InvisibleCharactersPlugin(this.editor.state, this.options)]\n },\n\n addStorage() {\n return {\n visibility: () => this.options.visible,\n }\n },\n\n onBeforeCreate() {\n this.storage.visibility = () => {\n return InvisibleCharactersPluginKey.getState(this.editor.state)?.visible\n }\n },\n\n addCommands() {\n return {\n showInvisibleCharacters:\n (visibility = true) =>\n ({ dispatch, tr }) => {\n if (dispatch) {\n tr.setMeta('setInvisibleCharactersVisible', visibility)\n }\n\n return true\n },\n hideInvisibleCharacters:\n () =>\n ({ dispatch, tr }) => {\n if (dispatch) {\n tr.setMeta('setInvisibleCharactersVisible', false)\n }\n\n return true\n },\n toggleInvisibleCharacters:\n () =>\n ({ dispatch, tr, state }) => {\n const visibility = !InvisibleCharactersPluginKey.getState(state)?.visible\n\n if (dispatch) {\n tr.setMeta('setInvisibleCharactersVisible', visibility)\n }\n\n return true\n },\n }\n },\n})\n\nexport default InvisibleCharacters\n","import { InvisibleCharacters } from './invisible-characters.js'\n\nexport * from './invisible-characters.js'\nexport * from './plugin/invisible-characters/hardBreak.js'\nexport * from './plugin/invisible-characters/paragraph.js'\nexport * from './plugin/invisible-characters/space.js'\nexport * from './plugin/InvisibleCharacter.js'\nexport * from './plugin/InvisibleNode.js'\nexport * from './types.js'\n\nexport default InvisibleCharacters\n"],"mappings":"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"}