@pixerate/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/dist/extensions/index.cjs +616 -0
- package/dist/extensions/index.cjs.map +1 -0
- package/dist/extensions/index.d.cts +84 -0
- package/dist/extensions/index.d.ts +84 -0
- package/dist/extensions/index.js +571 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/grammar/index.cjs +401 -0
- package/dist/grammar/index.cjs.map +1 -0
- package/dist/grammar/index.d.cts +65 -0
- package/dist/grammar/index.d.ts +65 -0
- package/dist/grammar/index.js +359 -0
- package/dist/grammar/index.js.map +1 -0
- package/dist/index.cjs +1149 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +1082 -0
- package/dist/index.js.map +1 -0
- package/dist/serializers/index.cjs +83 -0
- package/dist/serializers/index.cjs.map +1 -0
- package/dist/serializers/index.d.cts +20 -0
- package/dist/serializers/index.d.ts +20 -0
- package/dist/serializers/index.js +53 -0
- package/dist/serializers/index.js.map +1 -0
- package/dist/tokens-CE6SS_hd.d.cts +37 -0
- package/dist/tokens-CE6SS_hd.d.ts +37 -0
- package/package.json +66 -0
|
@@ -0,0 +1,571 @@
|
|
|
1
|
+
// src/extensions/gradient-text.ts
|
|
2
|
+
import { Mark } from "@tiptap/core";
|
|
3
|
+
import { Plugin } from "@tiptap/pm/state";
|
|
4
|
+
import { Decoration, DecorationSet } from "@tiptap/pm/view";
|
|
5
|
+
|
|
6
|
+
// src/grammar/tokens.ts
|
|
7
|
+
var TEMPLATE_REGEX = /{{\s*([^}]+?)\s*}}/g;
|
|
8
|
+
var VARIABLE_REGEX = /(?<!\{)\{([^{}]+)\}(?!\})/g;
|
|
9
|
+
var INSTRUCTION_REGEX = /__(.+?)__/g;
|
|
10
|
+
|
|
11
|
+
// src/extensions/gradient-text.ts
|
|
12
|
+
var createGradientDecorations = (doc, options) => {
|
|
13
|
+
const decorations = [];
|
|
14
|
+
const speed = options.speed ?? 1;
|
|
15
|
+
const jsonVarSet = options.jsonVariables ? options.jsonVariables instanceof Set ? options.jsonVariables : new Set(options.jsonVariables) : null;
|
|
16
|
+
doc.descendants((node, pos) => {
|
|
17
|
+
if (node.isText) {
|
|
18
|
+
const text = node.text || "";
|
|
19
|
+
let match;
|
|
20
|
+
const tmplRegex = new RegExp(TEMPLATE_REGEX.source, TEMPLATE_REGEX.flags);
|
|
21
|
+
while ((match = tmplRegex.exec(text)) !== null) {
|
|
22
|
+
const templateName = match[1].trim();
|
|
23
|
+
const colors = options.templateColorMap?.get(templateName);
|
|
24
|
+
if (colors) {
|
|
25
|
+
const start = pos + match.index;
|
|
26
|
+
const end = start + match[0].length;
|
|
27
|
+
const { from: colorFrom, to: colorTo } = colors;
|
|
28
|
+
const style = `--bg-size: ${speed * 300}%; --color-from: ${colorFrom}; --color-to: ${colorTo}; caret-color: #111 !important;`;
|
|
29
|
+
decorations.push(
|
|
30
|
+
Decoration.inline(start, end, {
|
|
31
|
+
class: "inline animate-gradient bg-gradient-to-r from-[var(--color-from)] via-[var(--color-to)] to-[var(--color-from)] bg-[length:var(--bg-size)_100%] bg-clip-text text-transparent border border-(--color-to)/20 px-1 py-0.5 rounded-sm cursor-pointer",
|
|
32
|
+
style,
|
|
33
|
+
"data-template": templateName
|
|
34
|
+
})
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const instRegex = new RegExp(
|
|
39
|
+
INSTRUCTION_REGEX.source,
|
|
40
|
+
INSTRUCTION_REGEX.flags
|
|
41
|
+
);
|
|
42
|
+
while ((match = instRegex.exec(text)) !== null) {
|
|
43
|
+
const content = match[1].trim();
|
|
44
|
+
const colors = options.templateColorMap?.get(content) || {
|
|
45
|
+
from: "#ffaa40",
|
|
46
|
+
to: "#9c40ff"
|
|
47
|
+
};
|
|
48
|
+
const start = pos + match.index;
|
|
49
|
+
const end = start + match[0].length;
|
|
50
|
+
const { from: colorFrom, to: colorTo } = colors;
|
|
51
|
+
const style = `--bg-size: ${speed * 300}%; --color-from: ${colorFrom}; --color-to: ${colorTo}; caret-color: #111 !important;`;
|
|
52
|
+
decorations.push(
|
|
53
|
+
Decoration.inline(start, end, {
|
|
54
|
+
class: "italic animate-gradient bg-gradient-to-r from-rose-400 from-50% to-violet-500 to-50% bg-size-[200%_100%] bg-clip-text text-transparent inline-flex items-baseline gap-0.5",
|
|
55
|
+
style
|
|
56
|
+
})
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
const varRegex = new RegExp(
|
|
60
|
+
VARIABLE_REGEX.source,
|
|
61
|
+
VARIABLE_REGEX.flags
|
|
62
|
+
);
|
|
63
|
+
while ((match = varRegex.exec(text)) !== null) {
|
|
64
|
+
const variableName = match[1].trim();
|
|
65
|
+
const start = pos + match.index;
|
|
66
|
+
const end = start + match[0].length;
|
|
67
|
+
const isJsonVar = jsonVarSet?.has(variableName);
|
|
68
|
+
decorations.push(
|
|
69
|
+
Decoration.inline(start, end, {
|
|
70
|
+
class: isJsonVar ? "bg-violet-400/40 border-b-4 border-rose-300 dark:border-rose-800 inline-flex items-baseline px-1 py-0 text-foreground/80 gap-0.5 rounded-xs" : "bg-rose-400/40 border-b-4 border-violet-300 dark:border-violet-800 inline-flex items-baseline px-1 py-0 text-foreground/80 gap-0.5 rounded-xs",
|
|
71
|
+
"data-variable": variableName
|
|
72
|
+
})
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return decorations;
|
|
78
|
+
};
|
|
79
|
+
var GradientText = Mark.create({
|
|
80
|
+
name: "gradientText",
|
|
81
|
+
addOptions() {
|
|
82
|
+
return {
|
|
83
|
+
templateColorMap: /* @__PURE__ */ new Map(),
|
|
84
|
+
speed: 1,
|
|
85
|
+
jsonVariables: void 0,
|
|
86
|
+
onTemplateClick: void 0
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
renderHTML({ HTMLAttributes }) {
|
|
90
|
+
const defaultColors = {
|
|
91
|
+
from: "#ffaa40",
|
|
92
|
+
to: "#9c40ff"
|
|
93
|
+
};
|
|
94
|
+
const speed = this.options.speed ?? 1;
|
|
95
|
+
const style = `--bg-size: ${speed * 300}%; --color-from: ${defaultColors.from}; --color-to: ${defaultColors.to}; caret-color: #111 !important;`;
|
|
96
|
+
return [
|
|
97
|
+
"span",
|
|
98
|
+
{
|
|
99
|
+
class: "inline animate-gradient bg-gradient-to-r from-[var(--color-from)] via-[var(--color-to)] to-[var(--color-from)] bg-[length:var(--bg-size)_100%] bg-clip-text text-transparent",
|
|
100
|
+
style,
|
|
101
|
+
...HTMLAttributes
|
|
102
|
+
},
|
|
103
|
+
0
|
|
104
|
+
];
|
|
105
|
+
},
|
|
106
|
+
parseHTML() {
|
|
107
|
+
return [
|
|
108
|
+
{
|
|
109
|
+
tag: "span",
|
|
110
|
+
getAttrs: (node) => node.classList.contains("animate-gradient") && node.classList.contains("bg-clip-text") && null
|
|
111
|
+
}
|
|
112
|
+
];
|
|
113
|
+
},
|
|
114
|
+
addProseMirrorPlugins() {
|
|
115
|
+
const markOptions = this.options;
|
|
116
|
+
return [
|
|
117
|
+
new Plugin({
|
|
118
|
+
state: {
|
|
119
|
+
init(_, { doc }) {
|
|
120
|
+
return DecorationSet.create(
|
|
121
|
+
doc,
|
|
122
|
+
createGradientDecorations(doc, markOptions)
|
|
123
|
+
);
|
|
124
|
+
},
|
|
125
|
+
apply(tr, value) {
|
|
126
|
+
const newDoc = tr.doc;
|
|
127
|
+
if (tr.docChanged) {
|
|
128
|
+
return DecorationSet.create(
|
|
129
|
+
newDoc,
|
|
130
|
+
createGradientDecorations(newDoc, markOptions)
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
return value.map(tr.mapping, newDoc);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
props: {
|
|
137
|
+
decorations(state) {
|
|
138
|
+
return this.getState(state);
|
|
139
|
+
},
|
|
140
|
+
handleClickOn(view, pos, _node, _nodePos, event) {
|
|
141
|
+
const decorationSet = this.getState(
|
|
142
|
+
view.state
|
|
143
|
+
);
|
|
144
|
+
const decorations = decorationSet.find(pos, pos + 1);
|
|
145
|
+
for (const decoration of decorations) {
|
|
146
|
+
const decorationWithAttrs = decoration;
|
|
147
|
+
const templateName = decorationWithAttrs.type?.attrs?.["data-template"];
|
|
148
|
+
if (templateName) {
|
|
149
|
+
if (markOptions.onTemplateClick) {
|
|
150
|
+
markOptions.onTemplateClick(templateName, event);
|
|
151
|
+
}
|
|
152
|
+
if (typeof window !== "undefined") {
|
|
153
|
+
window.dispatchEvent(
|
|
154
|
+
new CustomEvent("show-gradient-popover", {
|
|
155
|
+
detail: {
|
|
156
|
+
templateName,
|
|
157
|
+
target: event.target
|
|
158
|
+
}
|
|
159
|
+
})
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
// src/extensions/slash-commands.ts
|
|
174
|
+
import { Extension } from "@tiptap/core";
|
|
175
|
+
import { Plugin as Plugin2 } from "@tiptap/pm/state";
|
|
176
|
+
var SlashCommands = Extension.create({
|
|
177
|
+
name: "slashCommands",
|
|
178
|
+
addOptions() {
|
|
179
|
+
return {
|
|
180
|
+
trigger: "/",
|
|
181
|
+
onMatch: void 0,
|
|
182
|
+
onClear: void 0,
|
|
183
|
+
containerId: void 0
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
addProseMirrorPlugins() {
|
|
187
|
+
const opts = this.options;
|
|
188
|
+
return [
|
|
189
|
+
new Plugin2({
|
|
190
|
+
view() {
|
|
191
|
+
return {
|
|
192
|
+
update(view) {
|
|
193
|
+
const { state } = view;
|
|
194
|
+
const { selection } = state;
|
|
195
|
+
const { $from } = selection;
|
|
196
|
+
if (!$from.parent.isTextblock) {
|
|
197
|
+
opts.onClear?.();
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const textBeforeCursor = $from.parent.textBetween(
|
|
201
|
+
0,
|
|
202
|
+
$from.parentOffset
|
|
203
|
+
);
|
|
204
|
+
const slashMatch = textBeforeCursor.match(
|
|
205
|
+
/(?:^|\s)\/([a-zA-Z0-9_-]*)$/
|
|
206
|
+
);
|
|
207
|
+
if (slashMatch) {
|
|
208
|
+
const matchIndex = slashMatch.index ?? 0;
|
|
209
|
+
const offsetInParent = matchIndex + (slashMatch[0].startsWith(" ") ? 1 : 0);
|
|
210
|
+
const matchFrom = $from.start() + offsetInParent;
|
|
211
|
+
const matchTo = $from.pos;
|
|
212
|
+
const coords = view.coordsAtPos($from.pos);
|
|
213
|
+
let relativeCoords = {
|
|
214
|
+
top: coords.top,
|
|
215
|
+
left: coords.left,
|
|
216
|
+
bottom: coords.bottom,
|
|
217
|
+
right: coords.right
|
|
218
|
+
};
|
|
219
|
+
if (opts.containerId && typeof document !== "undefined") {
|
|
220
|
+
const container = document.getElementById(opts.containerId);
|
|
221
|
+
if (container) {
|
|
222
|
+
const rect = container.getBoundingClientRect();
|
|
223
|
+
relativeCoords = {
|
|
224
|
+
top: coords.bottom - rect.top + 5,
|
|
225
|
+
left: coords.left - rect.left,
|
|
226
|
+
bottom: coords.bottom - rect.top,
|
|
227
|
+
right: coords.right - rect.left
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
opts.onMatch?.({
|
|
232
|
+
match: slashMatch,
|
|
233
|
+
query: slashMatch[1] || "",
|
|
234
|
+
from: matchFrom,
|
|
235
|
+
to: matchTo,
|
|
236
|
+
coords: relativeCoords
|
|
237
|
+
});
|
|
238
|
+
} else {
|
|
239
|
+
opts.onClear?.();
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
];
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// src/extensions/template-suggestions.ts
|
|
250
|
+
import { Extension as Extension2 } from "@tiptap/core";
|
|
251
|
+
import Suggestion from "@tiptap/suggestion";
|
|
252
|
+
var TemplateSuggestions = Extension2.create({
|
|
253
|
+
name: "templateSuggestions",
|
|
254
|
+
addOptions() {
|
|
255
|
+
return {
|
|
256
|
+
templates: [],
|
|
257
|
+
char: "{{",
|
|
258
|
+
onSuggestion: void 0
|
|
259
|
+
};
|
|
260
|
+
},
|
|
261
|
+
addProseMirrorPlugins() {
|
|
262
|
+
const opts = this.options;
|
|
263
|
+
const suggestionConfig = {
|
|
264
|
+
char: opts.char || "{{",
|
|
265
|
+
items: ({ query }) => {
|
|
266
|
+
const lower = query.toLowerCase();
|
|
267
|
+
return (opts.templates || []).filter(
|
|
268
|
+
(t) => t.name.toLowerCase().includes(lower)
|
|
269
|
+
);
|
|
270
|
+
},
|
|
271
|
+
command: ({ editor, range, props }) => {
|
|
272
|
+
editor.chain().focus().deleteRange(range).insertContent(`{{${props.name}}}`).run();
|
|
273
|
+
},
|
|
274
|
+
render: () => {
|
|
275
|
+
return {
|
|
276
|
+
onStart: (props) => {
|
|
277
|
+
opts.onSuggestion?.(props);
|
|
278
|
+
},
|
|
279
|
+
onUpdate: (props) => {
|
|
280
|
+
opts.onSuggestion?.(props);
|
|
281
|
+
},
|
|
282
|
+
onExit: () => {
|
|
283
|
+
opts.onSuggestion?.({
|
|
284
|
+
query: "",
|
|
285
|
+
range: { from: 0, to: 0 },
|
|
286
|
+
items: [],
|
|
287
|
+
command: () => {
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
return [
|
|
295
|
+
Suggestion({
|
|
296
|
+
editor: this.editor,
|
|
297
|
+
...suggestionConfig
|
|
298
|
+
})
|
|
299
|
+
];
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// src/extensions/loading-node.ts
|
|
304
|
+
import { Node, mergeAttributes } from "@tiptap/core";
|
|
305
|
+
var LoadingNode = Node.create({
|
|
306
|
+
name: "loadingNode",
|
|
307
|
+
group: "inline",
|
|
308
|
+
inline: true,
|
|
309
|
+
selectable: true,
|
|
310
|
+
atom: true,
|
|
311
|
+
addAttributes() {
|
|
312
|
+
return {
|
|
313
|
+
id: {
|
|
314
|
+
default: null,
|
|
315
|
+
parseHTML: (element) => element.getAttribute("data-id"),
|
|
316
|
+
renderHTML: (attributes) => {
|
|
317
|
+
if (!attributes.id) return {};
|
|
318
|
+
return { "data-id": attributes.id };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
},
|
|
323
|
+
parseHTML() {
|
|
324
|
+
return [
|
|
325
|
+
{
|
|
326
|
+
tag: 'span[data-type="loading"]'
|
|
327
|
+
}
|
|
328
|
+
];
|
|
329
|
+
},
|
|
330
|
+
renderHTML({ HTMLAttributes }) {
|
|
331
|
+
return [
|
|
332
|
+
"span",
|
|
333
|
+
mergeAttributes(HTMLAttributes, {
|
|
334
|
+
"data-type": "loading",
|
|
335
|
+
class: "inline-flex items-center px-1.5 py-0.5 text-xs text-muted-foreground animate-pulse"
|
|
336
|
+
}),
|
|
337
|
+
"\u23F3"
|
|
338
|
+
];
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// src/extensions/SmilieReplacer.ts
|
|
343
|
+
import { Extension as Extension3, textInputRule } from "@tiptap/core";
|
|
344
|
+
var SmilieReplacer = Extension3.create({
|
|
345
|
+
name: "smilieReplacer",
|
|
346
|
+
addInputRules() {
|
|
347
|
+
return [
|
|
348
|
+
textInputRule({ find: /-___- $/, replace: "\u{1F611} " }),
|
|
349
|
+
textInputRule({ find: /:'-\) $/, replace: "\u{1F602} " }),
|
|
350
|
+
textInputRule({ find: /':-\) $/, replace: "\u{1F605} " }),
|
|
351
|
+
textInputRule({ find: /':-D $/, replace: "\u{1F605} " }),
|
|
352
|
+
textInputRule({ find: />:-\) $/, replace: "\u{1F606} " }),
|
|
353
|
+
textInputRule({ find: /-__- $/, replace: "\u{1F611} " }),
|
|
354
|
+
textInputRule({ find: /':-\( $/, replace: "\u{1F613} " }),
|
|
355
|
+
textInputRule({ find: /:'-\( $/, replace: "\u{1F622} " }),
|
|
356
|
+
textInputRule({ find: />:-\( $/, replace: "\u{1F620} " }),
|
|
357
|
+
textInputRule({ find: /O:-\) $/, replace: "\u{1F607} " }),
|
|
358
|
+
textInputRule({ find: /:'\) $/, replace: "\u{1F602} " }),
|
|
359
|
+
textInputRule({ find: /:-D $/, replace: "\u{1F603} " }),
|
|
360
|
+
textInputRule({ find: /':\) $/, replace: "\u{1F605} " }),
|
|
361
|
+
textInputRule({ find: /;-\) $/, replace: "\u{1F609} " }),
|
|
362
|
+
textInputRule({ find: /B-\) $/, replace: "\u{1F60E} " }),
|
|
363
|
+
textInputRule({ find: /:-\* $/, replace: "\u{1F618} " }),
|
|
364
|
+
textInputRule({ find: /:-\) $/, replace: "\u{1F642} " }),
|
|
365
|
+
textInputRule({ find: /-_- $/, replace: "\u{1F611} " }),
|
|
366
|
+
textInputRule({ find: /:-O $/, replace: "\u{1F62E} " }),
|
|
367
|
+
textInputRule({ find: /:-P $/, replace: "\u{1F61B} " }),
|
|
368
|
+
textInputRule({ find: /:-p $/, replace: "\u{1F61B} " }),
|
|
369
|
+
textInputRule({ find: /:-\/ $/, replace: "\u{1F615} " }),
|
|
370
|
+
textInputRule({ find: /:-\( $/, replace: "\u{1F61E} " }),
|
|
371
|
+
textInputRule({ find: /:'\( $/, replace: "\u{1F622} " }),
|
|
372
|
+
textInputRule({ find: /:D $/, replace: "\u{1F603} " }),
|
|
373
|
+
textInputRule({ find: /=D $/, replace: "\u{1F603} " }),
|
|
374
|
+
textInputRule({ find: /;\) $/, replace: "\u{1F609} " }),
|
|
375
|
+
textInputRule({ find: /B\) $/, replace: "\u{1F60E} " }),
|
|
376
|
+
textInputRule({ find: /:\) $/, replace: "\u{1F642} " }),
|
|
377
|
+
textInputRule({ find: /=\) $/, replace: "\u{1F642} " }),
|
|
378
|
+
textInputRule({ find: /:O $/, replace: "\u{1F62E} " }),
|
|
379
|
+
textInputRule({ find: /:P $/, replace: "\u{1F61B} " }),
|
|
380
|
+
textInputRule({ find: /:p $/, replace: "\u{1F61B} " }),
|
|
381
|
+
textInputRule({ find: /:\/ $/, replace: "\u{1F615} " }),
|
|
382
|
+
textInputRule({ find: /:\( $/, replace: "\u{1F61E} " }),
|
|
383
|
+
textInputRule({ find: /<3 $/, replace: "\u2764\uFE0F " }),
|
|
384
|
+
textInputRule({ find: /<\/3 $/, replace: "\u{1F494} " }),
|
|
385
|
+
textInputRule({ find: /\/shrug $/, replace: "\xAF\\_(\u30C4)_/\xAF " })
|
|
386
|
+
];
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
// src/extensions/ColorHighlighter.ts
|
|
391
|
+
import { Extension as Extension4 } from "@tiptap/core";
|
|
392
|
+
import { Plugin as Plugin3 } from "@tiptap/pm/state";
|
|
393
|
+
import { Decoration as Decoration2, DecorationSet as DecorationSet2 } from "@tiptap/pm/view";
|
|
394
|
+
function findHexColors(doc) {
|
|
395
|
+
const hexColorRegex = /(#[0-9a-fA-F]{3,8})\b/g;
|
|
396
|
+
const decorations = [];
|
|
397
|
+
doc.descendants((node, position) => {
|
|
398
|
+
if (!node.text) return;
|
|
399
|
+
let match;
|
|
400
|
+
while ((match = hexColorRegex.exec(node.text)) !== null) {
|
|
401
|
+
const color = match[0];
|
|
402
|
+
const from = position + match.index;
|
|
403
|
+
const to = from + color.length;
|
|
404
|
+
decorations.push(
|
|
405
|
+
Decoration2.inline(from, to, {
|
|
406
|
+
class: "color-highlight px-1 py-0.5 rounded text-xs font-mono border",
|
|
407
|
+
style: `--color: ${color}; background-color: ${color}20; border-color: ${color}; color: ${color};`
|
|
408
|
+
})
|
|
409
|
+
);
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
return DecorationSet2.create(doc, decorations);
|
|
413
|
+
}
|
|
414
|
+
var ColorHighlighter = Extension4.create({
|
|
415
|
+
name: "colorHighlighter",
|
|
416
|
+
addProseMirrorPlugins() {
|
|
417
|
+
return [
|
|
418
|
+
new Plugin3({
|
|
419
|
+
state: {
|
|
420
|
+
init(_, { doc }) {
|
|
421
|
+
return findHexColors(doc);
|
|
422
|
+
},
|
|
423
|
+
apply(transaction, oldState) {
|
|
424
|
+
return transaction.docChanged ? findHexColors(transaction.doc) : oldState;
|
|
425
|
+
}
|
|
426
|
+
},
|
|
427
|
+
props: {
|
|
428
|
+
decorations(state) {
|
|
429
|
+
return this.getState(state);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
})
|
|
433
|
+
];
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
// src/extensions/FontSize.ts
|
|
438
|
+
import { Extension as Extension5 } from "@tiptap/core";
|
|
439
|
+
import "@tiptap/extension-text-style";
|
|
440
|
+
var FontSize = Extension5.create({
|
|
441
|
+
name: "fontSize",
|
|
442
|
+
addOptions() {
|
|
443
|
+
return {
|
|
444
|
+
types: ["textStyle"]
|
|
445
|
+
};
|
|
446
|
+
},
|
|
447
|
+
addGlobalAttributes() {
|
|
448
|
+
return [
|
|
449
|
+
{
|
|
450
|
+
types: this.options.types,
|
|
451
|
+
attributes: {
|
|
452
|
+
fontSize: {
|
|
453
|
+
default: null,
|
|
454
|
+
parseHTML: (element) => element.style.fontSize.replace(/['"]+/g, ""),
|
|
455
|
+
renderHTML: (attributes) => {
|
|
456
|
+
if (!attributes.fontSize) {
|
|
457
|
+
return {};
|
|
458
|
+
}
|
|
459
|
+
return {
|
|
460
|
+
style: `font-size: ${attributes.fontSize}`
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
];
|
|
467
|
+
},
|
|
468
|
+
addCommands() {
|
|
469
|
+
return {
|
|
470
|
+
setFontSize: (fontSize) => ({ chain }) => chain().setMark("textStyle", { fontSize }).run(),
|
|
471
|
+
unsetFontSize: () => ({ chain }) => chain().setMark("textStyle", { fontSize: null }).removeEmptyTextStyle().run()
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
// src/extensions/rich-text-preset.ts
|
|
477
|
+
import StarterKit from "@tiptap/starter-kit";
|
|
478
|
+
import Color from "@tiptap/extension-color";
|
|
479
|
+
import Highlight from "@tiptap/extension-highlight";
|
|
480
|
+
import Link from "@tiptap/extension-link";
|
|
481
|
+
import TaskList from "@tiptap/extension-task-list";
|
|
482
|
+
import TaskItem from "@tiptap/extension-task-item";
|
|
483
|
+
import TextAlign from "@tiptap/extension-text-align";
|
|
484
|
+
import TextStyle from "@tiptap/extension-text-style";
|
|
485
|
+
import Typography from "@tiptap/extension-typography";
|
|
486
|
+
import Underline from "@tiptap/extension-underline";
|
|
487
|
+
import Placeholder from "@tiptap/extension-placeholder";
|
|
488
|
+
import CharacterCount from "@tiptap/extension-character-count";
|
|
489
|
+
function createRichTextPreset(options = {}) {
|
|
490
|
+
const {
|
|
491
|
+
placeholder = "Start typing...",
|
|
492
|
+
characterLimit,
|
|
493
|
+
openLinksOnClick = false,
|
|
494
|
+
enableSmilies = true,
|
|
495
|
+
enableColorHighlighter = true,
|
|
496
|
+
headingLevels = [1, 2, 3, 4]
|
|
497
|
+
} = options;
|
|
498
|
+
const extensions = [
|
|
499
|
+
StarterKit.configure({
|
|
500
|
+
orderedList: {
|
|
501
|
+
HTMLAttributes: {
|
|
502
|
+
class: "list-decimal pl-4"
|
|
503
|
+
}
|
|
504
|
+
},
|
|
505
|
+
bulletList: {
|
|
506
|
+
HTMLAttributes: {
|
|
507
|
+
class: "list-disc pl-4"
|
|
508
|
+
}
|
|
509
|
+
},
|
|
510
|
+
heading: {
|
|
511
|
+
levels: headingLevels,
|
|
512
|
+
HTMLAttributes: {
|
|
513
|
+
class: "font-bold tracking-tight"
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}),
|
|
517
|
+
TextStyle,
|
|
518
|
+
Color,
|
|
519
|
+
Highlight.configure({ multicolor: true }),
|
|
520
|
+
Underline,
|
|
521
|
+
Typography,
|
|
522
|
+
TextAlign.configure({
|
|
523
|
+
types: ["heading", "paragraph"]
|
|
524
|
+
}),
|
|
525
|
+
Link.configure({
|
|
526
|
+
openOnClick: openLinksOnClick,
|
|
527
|
+
autolink: true,
|
|
528
|
+
defaultProtocol: "https",
|
|
529
|
+
HTMLAttributes: {
|
|
530
|
+
target: "_blank",
|
|
531
|
+
rel: "noopener noreferrer",
|
|
532
|
+
class: "text-blue-500 underline underline-offset-2"
|
|
533
|
+
}
|
|
534
|
+
}),
|
|
535
|
+
TaskList,
|
|
536
|
+
TaskItem.configure({
|
|
537
|
+
nested: true
|
|
538
|
+
}),
|
|
539
|
+
FontSize,
|
|
540
|
+
Placeholder.configure({
|
|
541
|
+
emptyEditorClass: "is-empty",
|
|
542
|
+
placeholder: typeof placeholder === "function" ? placeholder : () => placeholder
|
|
543
|
+
})
|
|
544
|
+
];
|
|
545
|
+
if (characterLimit) {
|
|
546
|
+
extensions.push(
|
|
547
|
+
CharacterCount.configure({
|
|
548
|
+
limit: characterLimit
|
|
549
|
+
})
|
|
550
|
+
);
|
|
551
|
+
}
|
|
552
|
+
if (enableSmilies) {
|
|
553
|
+
extensions.push(SmilieReplacer);
|
|
554
|
+
}
|
|
555
|
+
if (enableColorHighlighter) {
|
|
556
|
+
extensions.push(ColorHighlighter);
|
|
557
|
+
}
|
|
558
|
+
return extensions;
|
|
559
|
+
}
|
|
560
|
+
export {
|
|
561
|
+
ColorHighlighter,
|
|
562
|
+
FontSize,
|
|
563
|
+
GradientText,
|
|
564
|
+
LoadingNode,
|
|
565
|
+
SlashCommands,
|
|
566
|
+
SmilieReplacer,
|
|
567
|
+
TemplateSuggestions,
|
|
568
|
+
createRichTextPreset,
|
|
569
|
+
findHexColors
|
|
570
|
+
};
|
|
571
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/extensions/gradient-text.ts","../../src/grammar/tokens.ts","../../src/extensions/slash-commands.ts","../../src/extensions/template-suggestions.ts","../../src/extensions/loading-node.ts","../../src/extensions/SmilieReplacer.ts","../../src/extensions/ColorHighlighter.ts","../../src/extensions/FontSize.ts","../../src/extensions/rich-text-preset.ts"],"sourcesContent":["import { Mark } from \"@tiptap/core\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport type { Node as ProsemirrorNode } from \"@tiptap/pm/model\";\nimport type { EditorState } from \"@tiptap/pm/state\";\nimport { TEMPLATE_REGEX, VARIABLE_REGEX, INSTRUCTION_REGEX, ColorGradient } from \"../grammar/tokens\";\n\nexport interface GradientTextOptions {\n templateColorMap: Map<string, ColorGradient>;\n speed?: number;\n jsonVariables?: string[] | Set<string>;\n onTemplateClick?: (templateName: string, event: MouseEvent) => void;\n}\n\nconst createGradientDecorations = (\n doc: ProsemirrorNode,\n options: GradientTextOptions,\n): Decoration[] => {\n const decorations: Decoration[] = [];\n const speed = options.speed ?? 1;\n const jsonVarSet = options.jsonVariables\n ? options.jsonVariables instanceof Set\n ? options.jsonVariables\n : new Set(options.jsonVariables)\n : null;\n\n doc.descendants((node, pos) => {\n if (node.isText) {\n const text = node.text || \"\";\n let match: RegExpExecArray | null;\n\n // 1. Template: {{templateName}}\n const tmplRegex = new RegExp(TEMPLATE_REGEX.source, TEMPLATE_REGEX.flags);\n while ((match = tmplRegex.exec(text)) !== null) {\n const templateName = match[1].trim();\n const colors = options.templateColorMap?.get(templateName);\n\n if (colors) {\n const start = pos + match.index;\n const end = start + match[0].length;\n const { from: colorFrom, to: colorTo } = colors;\n\n const style = `--bg-size: ${\n speed * 300\n }%; --color-from: ${colorFrom}; --color-to: ${colorTo}; caret-color: #111 !important;`;\n\n decorations.push(\n Decoration.inline(start, end, {\n class:\n \"inline animate-gradient bg-gradient-to-r from-[var(--color-from)] via-[var(--color-to)] to-[var(--color-from)] bg-[length:var(--bg-size)_100%] bg-clip-text text-transparent border border-(--color-to)/20 px-1 py-0.5 rounded-sm cursor-pointer\",\n style,\n \"data-template\": templateName,\n }),\n );\n }\n }\n\n // 2. Instruction: __text__\n const instRegex = new RegExp(\n INSTRUCTION_REGEX.source,\n INSTRUCTION_REGEX.flags,\n );\n while ((match = instRegex.exec(text)) !== null) {\n const content = match[1].trim();\n const colors = options.templateColorMap?.get(content) || {\n from: \"#ffaa40\",\n to: \"#9c40ff\",\n };\n\n const start = pos + match.index;\n const end = start + match[0].length;\n const { from: colorFrom, to: colorTo } = colors;\n\n const style = `--bg-size: ${\n speed * 300\n }%; --color-from: ${colorFrom}; --color-to: ${colorTo}; caret-color: #111 !important;`;\n\n decorations.push(\n Decoration.inline(start, end, {\n class:\n \"italic animate-gradient bg-gradient-to-r from-rose-400 from-50% to-violet-500 to-50% bg-size-[200%_100%] bg-clip-text text-transparent inline-flex items-baseline gap-0.5\",\n style,\n }),\n );\n }\n\n // 3. Variable: {variableName}\n const varRegex = new RegExp(\n VARIABLE_REGEX.source,\n VARIABLE_REGEX.flags,\n );\n while ((match = varRegex.exec(text)) !== null) {\n const variableName = match[1].trim();\n const start = pos + match.index;\n const end = start + match[0].length;\n const isJsonVar = jsonVarSet?.has(variableName);\n\n decorations.push(\n Decoration.inline(start, end, {\n class: isJsonVar\n ? \"bg-violet-400/40 border-b-4 border-rose-300 dark:border-rose-800 inline-flex items-baseline px-1 py-0 text-foreground/80 gap-0.5 rounded-xs\"\n : \"bg-rose-400/40 border-b-4 border-violet-300 dark:border-violet-800 inline-flex items-baseline px-1 py-0 text-foreground/80 gap-0.5 rounded-xs\",\n \"data-variable\": variableName,\n }),\n );\n }\n }\n });\n\n return decorations;\n};\n\nexport const GradientText = Mark.create<GradientTextOptions>({\n name: \"gradientText\",\n\n addOptions() {\n return {\n templateColorMap: new Map(),\n speed: 1,\n jsonVariables: undefined,\n onTemplateClick: undefined,\n };\n },\n\n renderHTML({ HTMLAttributes }) {\n const defaultColors = {\n from: \"#ffaa40\",\n to: \"#9c40ff\",\n };\n const speed = this.options.speed ?? 1;\n const style = `--bg-size: ${speed * 300}%; --color-from: ${\n defaultColors.from\n }; --color-to: ${defaultColors.to}; caret-color: #111 !important;`;\n\n return [\n \"span\",\n {\n class:\n \"inline animate-gradient bg-gradient-to-r from-[var(--color-from)] via-[var(--color-to)] to-[var(--color-from)] bg-[length:var(--bg-size)_100%] bg-clip-text text-transparent\",\n style,\n ...HTMLAttributes,\n },\n 0,\n ];\n },\n\n parseHTML() {\n return [\n {\n tag: \"span\",\n getAttrs: (node) =>\n (node as HTMLElement).classList.contains(\"animate-gradient\") &&\n (node as HTMLElement).classList.contains(\"bg-clip-text\") &&\n null,\n },\n ];\n },\n\n addProseMirrorPlugins() {\n const markOptions = this.options;\n\n return [\n new Plugin({\n state: {\n init(_, { doc }) {\n return DecorationSet.create(\n doc,\n createGradientDecorations(doc, markOptions),\n );\n },\n apply(tr, value: DecorationSet) {\n const newDoc = tr.doc;\n if (tr.docChanged) {\n return DecorationSet.create(\n newDoc,\n createGradientDecorations(newDoc, markOptions),\n );\n }\n return value.map(tr.mapping, newDoc);\n },\n },\n props: {\n decorations(state: EditorState) {\n return (this as any).getState(state) as DecorationSet;\n },\n handleClickOn(view, pos, _node, _nodePos, event) {\n const decorationSet = (this as any).getState(\n view.state,\n ) as DecorationSet;\n const decorations = decorationSet.find(pos, pos + 1);\n\n for (const decoration of decorations) {\n const decorationWithAttrs = decoration as any;\n const templateName =\n decorationWithAttrs.type?.attrs?.[\"data-template\"];\n if (templateName) {\n if (markOptions.onTemplateClick) {\n markOptions.onTemplateClick(templateName, event as MouseEvent);\n }\n if (typeof window !== \"undefined\") {\n window.dispatchEvent(\n new CustomEvent(\"show-gradient-popover\", {\n detail: {\n templateName,\n target: event.target,\n },\n }),\n );\n }\n return true;\n }\n }\n return false;\n },\n },\n }),\n ];\n },\n});\n","/**\n * Canonical regex patterns for prompt editing tokens.\n */\nexport const TEMPLATE_REGEX = /{{\\s*([^}]+?)\\s*}}/g;\nexport const VARIABLE_REGEX = /(?<!\\{)\\{([^{}]+)\\}(?!\\})/g;\nexport const INSTRUCTION_REGEX = /__(.+?)__/g;\n\n// Backward-compatible camelCase aliases\nexport const templateRegex = TEMPLATE_REGEX;\nexport const variableRegex = VARIABLE_REGEX;\nexport const instructionRegex = INSTRUCTION_REGEX;\n\nexport type TokenType = \"template\" | \"variable\" | \"instruction\" | \"text\";\n\nexport interface Token {\n type: TokenType;\n raw: string;\n value: string;\n start: number;\n end: number;\n}\n\nexport interface TemplateVersion {\n id: string;\n version: string;\n body: string;\n createdAt?: string;\n}\n\nexport interface Template {\n id?: string;\n name: string;\n body?: string;\n latestVersion?: string;\n versions?: TemplateVersion[];\n color?: string;\n}\n\nexport interface ColorGradient {\n from: string;\n to: string;\n}\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"@tiptap/pm/state\";\n\nexport interface SlashCommandMatchData {\n match: RegExpMatchArray;\n query: string;\n from: number;\n to: number;\n coords: { top: number; left: number; bottom: number; right: number };\n}\n\nexport interface SlashCommandsOptions {\n trigger?: string;\n onMatch?: (data: SlashCommandMatchData) => void;\n onClear?: () => void;\n containerId?: string;\n}\n\nexport const SlashCommands = Extension.create<SlashCommandsOptions>({\n name: \"slashCommands\",\n\n addOptions() {\n return {\n trigger: \"/\",\n onMatch: undefined,\n onClear: undefined,\n containerId: undefined,\n };\n },\n\n addProseMirrorPlugins() {\n const opts = this.options;\n\n return [\n new Plugin({\n view() {\n return {\n update(view) {\n const { state } = view;\n const { selection } = state;\n const { $from } = selection;\n\n if (!$from.parent.isTextblock) {\n opts.onClear?.();\n return;\n }\n\n const textBeforeCursor = $from.parent.textBetween(\n 0,\n $from.parentOffset,\n );\n\n const slashMatch = textBeforeCursor.match(\n /(?:^|\\s)\\/([a-zA-Z0-9_-]*)$/,\n );\n\n if (slashMatch) {\n const matchIndex = slashMatch.index ?? 0;\n const offsetInParent =\n matchIndex + (slashMatch[0].startsWith(\" \") ? 1 : 0);\n const matchFrom = $from.start() + offsetInParent;\n const matchTo = $from.pos;\n const coords = view.coordsAtPos($from.pos);\n\n let relativeCoords = {\n top: coords.top,\n left: coords.left,\n bottom: coords.bottom,\n right: coords.right,\n };\n\n if (opts.containerId && typeof document !== \"undefined\") {\n const container = document.getElementById(opts.containerId);\n if (container) {\n const rect = container.getBoundingClientRect();\n relativeCoords = {\n top: coords.bottom - rect.top + 5,\n left: coords.left - rect.left,\n bottom: coords.bottom - rect.top,\n right: coords.right - rect.left,\n };\n }\n }\n\n opts.onMatch?.({\n match: slashMatch,\n query: slashMatch[1] || \"\",\n from: matchFrom,\n to: matchTo,\n coords: relativeCoords,\n });\n } else {\n opts.onClear?.();\n }\n },\n };\n },\n }),\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport Suggestion, { SuggestionOptions } from \"@tiptap/suggestion\";\nimport { Template } from \"../grammar/tokens\";\n\nexport interface TemplateSuggestionsOptions {\n templates: Template[];\n char?: string;\n onSuggestion?: (props: {\n query: string;\n range: { from: number; to: number };\n clientRect?: (() => DOMRect | null) | null;\n items: Template[];\n command: (props: { name: string }) => void;\n }) => void;\n}\n\nexport const TemplateSuggestions = Extension.create<TemplateSuggestionsOptions>({\n name: \"templateSuggestions\",\n\n addOptions() {\n return {\n templates: [],\n char: \"{{\",\n onSuggestion: undefined,\n };\n },\n\n addProseMirrorPlugins() {\n const opts = this.options;\n\n const suggestionConfig: Omit<SuggestionOptions<Template>, \"editor\"> = {\n char: opts.char || \"{{\",\n items: ({ query }) => {\n const lower = query.toLowerCase();\n return (opts.templates || []).filter((t) =>\n t.name.toLowerCase().includes(lower),\n );\n },\n command: ({ editor, range, props }) => {\n editor\n .chain()\n .focus()\n .deleteRange(range)\n .insertContent(`{{${props.name}}}`)\n .run();\n },\n render: () => {\n return {\n onStart: (props) => {\n opts.onSuggestion?.(props as any);\n },\n onUpdate: (props) => {\n opts.onSuggestion?.(props as any);\n },\n onExit: () => {\n opts.onSuggestion?.({\n query: \"\",\n range: { from: 0, to: 0 },\n items: [],\n command: () => {},\n });\n },\n };\n },\n };\n\n return [\n Suggestion({\n editor: this.editor,\n ...suggestionConfig,\n }),\n ];\n },\n});\n","import { Node, mergeAttributes } from \"@tiptap/core\";\n\nexport const LoadingNode = Node.create({\n name: \"loadingNode\",\n group: \"inline\",\n inline: true,\n selectable: true,\n atom: true,\n\n addAttributes() {\n return {\n id: {\n default: null,\n parseHTML: (element) => element.getAttribute(\"data-id\"),\n renderHTML: (attributes) => {\n if (!attributes.id) return {};\n return { \"data-id\": attributes.id };\n },\n },\n };\n },\n\n parseHTML() {\n return [\n {\n tag: 'span[data-type=\"loading\"]',\n },\n ];\n },\n\n renderHTML({ HTMLAttributes }) {\n return [\n \"span\",\n mergeAttributes(HTMLAttributes, {\n \"data-type\": \"loading\",\n class: \"inline-flex items-center px-1.5 py-0.5 text-xs text-muted-foreground animate-pulse\",\n }),\n \"⏳\",\n ];\n },\n});\n","import { Extension, textInputRule } from \"@tiptap/core\";\n\nexport const SmilieReplacer = Extension.create({\n name: \"smilieReplacer\",\n\n addInputRules() {\n return [\n textInputRule({ find: /-___- $/, replace: \"😑 \" }),\n textInputRule({ find: /:'-\\) $/, replace: \"😂 \" }),\n textInputRule({ find: /':-\\) $/, replace: \"😅 \" }),\n textInputRule({ find: /':-D $/, replace: \"😅 \" }),\n textInputRule({ find: />:-\\) $/, replace: \"😆 \" }),\n textInputRule({ find: /-__- $/, replace: \"😑 \" }),\n textInputRule({ find: /':-\\( $/, replace: \"😓 \" }),\n textInputRule({ find: /:'-\\( $/, replace: \"😢 \" }),\n textInputRule({ find: />:-\\( $/, replace: \"😠 \" }),\n textInputRule({ find: /O:-\\) $/, replace: \"😇 \" }),\n textInputRule({ find: /:'\\) $/, replace: \"😂 \" }),\n textInputRule({ find: /:-D $/, replace: \"😃 \" }),\n textInputRule({ find: /':\\) $/, replace: \"😅 \" }),\n textInputRule({ find: /;-\\) $/, replace: \"😉 \" }),\n textInputRule({ find: /B-\\) $/, replace: \"😎 \" }),\n textInputRule({ find: /:-\\* $/, replace: \"😘 \" }),\n textInputRule({ find: /:-\\) $/, replace: \"🙂 \" }),\n textInputRule({ find: /-_- $/, replace: \"😑 \" }),\n textInputRule({ find: /:-O $/, replace: \"😮 \" }),\n textInputRule({ find: /:-P $/, replace: \"😛 \" }),\n textInputRule({ find: /:-p $/, replace: \"😛 \" }),\n textInputRule({ find: /:-\\/ $/, replace: \"😕 \" }),\n textInputRule({ find: /:-\\( $/, replace: \"😞 \" }),\n textInputRule({ find: /:'\\( $/, replace: \"😢 \" }),\n textInputRule({ find: /:D $/, replace: \"😃 \" }),\n textInputRule({ find: /=D $/, replace: \"😃 \" }),\n textInputRule({ find: /;\\) $/, replace: \"😉 \" }),\n textInputRule({ find: /B\\) $/, replace: \"😎 \" }),\n textInputRule({ find: /:\\) $/, replace: \"🙂 \" }),\n textInputRule({ find: /=\\) $/, replace: \"🙂 \" }),\n textInputRule({ find: /:O $/, replace: \"😮 \" }),\n textInputRule({ find: /:P $/, replace: \"😛 \" }),\n textInputRule({ find: /:p $/, replace: \"😛 \" }),\n textInputRule({ find: /:\\/ $/, replace: \"😕 \" }),\n textInputRule({ find: /:\\( $/, replace: \"😞 \" }),\n textInputRule({ find: /<3 $/, replace: \"❤️ \" }),\n textInputRule({ find: /<\\/3 $/, replace: \"💔 \" }),\n textInputRule({ find: /\\/shrug $/, replace: \"¯\\\\_(ツ)_/¯ \" }),\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport { Plugin } from \"@tiptap/pm/state\";\nimport { Decoration, DecorationSet } from \"@tiptap/pm/view\";\nimport type { Node as ProsemirrorNode } from \"@tiptap/pm/model\";\n\nexport function findHexColors(doc: ProsemirrorNode): DecorationSet {\n const hexColorRegex = /(#[0-9a-fA-F]{3,8})\\b/g;\n const decorations: Decoration[] = [];\n\n doc.descendants((node, position) => {\n if (!node.text) return;\n\n let match: RegExpExecArray | null;\n while ((match = hexColorRegex.exec(node.text)) !== null) {\n const color = match[0];\n const from = position + match.index;\n const to = from + color.length;\n\n decorations.push(\n Decoration.inline(from, to, {\n class: \"color-highlight px-1 py-0.5 rounded text-xs font-mono border\",\n style: `--color: ${color}; background-color: ${color}20; border-color: ${color}; color: ${color};`,\n }),\n );\n }\n });\n\n return DecorationSet.create(doc, decorations);\n}\n\nexport const ColorHighlighter = Extension.create({\n name: \"colorHighlighter\",\n\n addProseMirrorPlugins() {\n return [\n new Plugin({\n state: {\n init(_, { doc }) {\n return findHexColors(doc);\n },\n apply(transaction, oldState) {\n return transaction.docChanged ? findHexColors(transaction.doc) : oldState;\n },\n },\n props: {\n decorations(state) {\n return (this as any).getState(state);\n },\n },\n }),\n ];\n },\n});\n","import { Extension } from \"@tiptap/core\";\nimport \"@tiptap/extension-text-style\";\n\ndeclare module \"@tiptap/core\" {\n interface Commands<ReturnType> {\n fontSize: {\n setFontSize: (size: string) => ReturnType;\n unsetFontSize: () => ReturnType;\n };\n }\n}\n\nexport const FontSize = Extension.create({\n name: \"fontSize\",\n\n addOptions() {\n return {\n types: [\"textStyle\"],\n };\n },\n\n addGlobalAttributes() {\n return [\n {\n types: this.options.types,\n attributes: {\n fontSize: {\n default: null,\n parseHTML: (element) =>\n element.style.fontSize.replace(/['\"]+/g, \"\"),\n renderHTML: (attributes) => {\n if (!attributes.fontSize) {\n return {};\n }\n return {\n style: `font-size: ${attributes.fontSize}`,\n };\n },\n },\n },\n },\n ];\n },\n\n addCommands() {\n return {\n setFontSize:\n (fontSize: string) =>\n ({ chain }) =>\n chain().setMark(\"textStyle\", { fontSize }).run(),\n unsetFontSize:\n () =>\n ({ chain }) =>\n chain()\n .setMark(\"textStyle\", { fontSize: null })\n .removeEmptyTextStyle()\n .run(),\n };\n },\n});\n\nexport default FontSize;\n","import type { Extensions } from \"@tiptap/core\";\nimport StarterKit from \"@tiptap/starter-kit\";\nimport Color from \"@tiptap/extension-color\";\nimport Highlight from \"@tiptap/extension-highlight\";\nimport Link from \"@tiptap/extension-link\";\nimport TaskList from \"@tiptap/extension-task-list\";\nimport TaskItem from \"@tiptap/extension-task-item\";\nimport TextAlign from \"@tiptap/extension-text-align\";\nimport TextStyle from \"@tiptap/extension-text-style\";\nimport Typography from \"@tiptap/extension-typography\";\nimport Underline from \"@tiptap/extension-underline\";\nimport Placeholder from \"@tiptap/extension-placeholder\";\nimport CharacterCount from \"@tiptap/extension-character-count\";\n\nimport { SmilieReplacer } from \"./SmilieReplacer\";\nimport { ColorHighlighter } from \"./ColorHighlighter\";\nimport { FontSize } from \"./FontSize\";\n\nexport interface RichTextPresetOptions {\n placeholder?: string | ((props: { node: any }) => string);\n characterLimit?: number;\n openLinksOnClick?: boolean;\n enableSmilies?: boolean;\n enableColorHighlighter?: boolean;\n headingLevels?: (1 | 2 | 3 | 4 | 5 | 6)[];\n}\n\n/**\n * Creates a standard rich-text extensions bundle with full formatting support.\n */\nexport function createRichTextPreset(\n options: RichTextPresetOptions = {},\n): Extensions {\n const {\n placeholder = \"Start typing...\",\n characterLimit,\n openLinksOnClick = false,\n enableSmilies = true,\n enableColorHighlighter = true,\n headingLevels = [1, 2, 3, 4],\n } = options;\n\n const extensions: Extensions = [\n StarterKit.configure({\n orderedList: {\n HTMLAttributes: {\n class: \"list-decimal pl-4\",\n },\n },\n bulletList: {\n HTMLAttributes: {\n class: \"list-disc pl-4\",\n },\n },\n heading: {\n levels: headingLevels,\n HTMLAttributes: {\n class: \"font-bold tracking-tight\",\n },\n },\n }),\n TextStyle,\n Color,\n Highlight.configure({ multicolor: true }),\n Underline,\n Typography,\n TextAlign.configure({\n types: [\"heading\", \"paragraph\"],\n }),\n Link.configure({\n openOnClick: openLinksOnClick,\n autolink: true,\n defaultProtocol: \"https\",\n HTMLAttributes: {\n target: \"_blank\",\n rel: \"noopener noreferrer\",\n class: \"text-blue-500 underline underline-offset-2\",\n },\n }),\n TaskList,\n TaskItem.configure({\n nested: true,\n }),\n FontSize,\n Placeholder.configure({\n emptyEditorClass: \"is-empty\",\n placeholder:\n typeof placeholder === \"function\"\n ? placeholder\n : () => placeholder,\n }),\n ];\n\n if (characterLimit) {\n extensions.push(\n CharacterCount.configure({\n limit: characterLimit,\n }),\n );\n }\n\n if (enableSmilies) {\n extensions.push(SmilieReplacer);\n }\n\n if (enableColorHighlighter) {\n extensions.push(ColorHighlighter);\n }\n\n return extensions;\n}\n"],"mappings":"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","names":["Plugin","Extension","Extension","Extension","Plugin","Decoration","DecorationSet","Extension"]}
|