@pixerate/editor 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/index.cjs +1 -0
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +5 -27
- package/dist/extensions/index.d.ts +5 -27
- package/dist/extensions/index.js +1 -0
- package/dist/extensions/index.js.map +1 -1
- package/dist/index.cjs +200 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +193 -2
- package/dist/index.js.map +1 -1
- package/dist/mention-Dcevh3ff.d.cts +32 -0
- package/dist/mention-Dcevh3ff.d.ts +32 -0
- package/dist/serializers/index.cjs +201 -4
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +89 -2
- package/dist/serializers/index.d.ts +89 -2
- package/dist/serializers/index.js +193 -3
- package/dist/serializers/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -43,6 +43,8 @@ __export(src_exports, {
|
|
|
43
43
|
INSTRUCTION_REGEX: () => INSTRUCTION_REGEX,
|
|
44
44
|
Image: () => Image2,
|
|
45
45
|
LoadingNode: () => LoadingNode,
|
|
46
|
+
MARKDOWN_MENTION_SPLIT_REGEX: () => MARKDOWN_MENTION_SPLIT_REGEX,
|
|
47
|
+
MENTION_REGEX: () => MENTION_REGEX,
|
|
46
48
|
Markdown: () => Markdown2,
|
|
47
49
|
Mention: () => Mention,
|
|
48
50
|
SlashCommands: () => SlashCommands,
|
|
@@ -61,6 +63,7 @@ __export(src_exports, {
|
|
|
61
63
|
escapeHtml: () => escapeHtml,
|
|
62
64
|
extractCellDependencies: () => extractCellDependencies,
|
|
63
65
|
extractInstructionNames: () => extractInstructionNames,
|
|
66
|
+
extractMentions: () => extractMentions,
|
|
64
67
|
extractMentionsFromDoc: () => extractMentionsFromDoc,
|
|
65
68
|
extractTemplateNames: () => extractTemplateNames,
|
|
66
69
|
extractVariableNames: () => extractVariableNames,
|
|
@@ -79,12 +82,16 @@ __export(src_exports, {
|
|
|
79
82
|
markdownToTipTapHtml: () => markdownToTipTapHtml,
|
|
80
83
|
parseCellReference: () => parseCellReference,
|
|
81
84
|
parseFormula: () => parseFormula,
|
|
85
|
+
parseMentionSegments: () => parseMentionSegments,
|
|
82
86
|
parseRange: () => parseRange,
|
|
83
87
|
plainTextToTipTapHtml: () => plainTextToTipTapHtml,
|
|
88
|
+
preprocessMarkdownFileLinks: () => preprocessMarkdownFileLinks,
|
|
89
|
+
preprocessMarkdownMentions: () => preprocessMarkdownMentions,
|
|
84
90
|
removeImageNode: () => removeImageNode,
|
|
85
91
|
resolveTemplates: () => resolveTemplates,
|
|
86
92
|
resolveTemplatesWithMapping: () => resolveTemplatesWithMapping,
|
|
87
93
|
resolveVariables: () => resolveVariables,
|
|
94
|
+
stripMarkdownCode: () => stripMarkdownCode,
|
|
88
95
|
templateRegex: () => templateRegex,
|
|
89
96
|
tokenizeFormula: () => tokenizeFormula,
|
|
90
97
|
tokenizePrompt: () => tokenizePrompt,
|
|
@@ -2205,6 +2212,7 @@ function createRichTextPreset(options = {}) {
|
|
|
2205
2212
|
openOnClick: openLinksOnClick,
|
|
2206
2213
|
autolink: true,
|
|
2207
2214
|
defaultProtocol: "https",
|
|
2215
|
+
protocols: ["file", "vscode", "cursor"],
|
|
2208
2216
|
HTMLAttributes: {
|
|
2209
2217
|
target: "_blank",
|
|
2210
2218
|
rel: "noopener noreferrer",
|
|
@@ -2289,6 +2297,150 @@ function createRichTextPreset(options = {}) {
|
|
|
2289
2297
|
return extensions2;
|
|
2290
2298
|
}
|
|
2291
2299
|
|
|
2300
|
+
// src/serializers/mentions.ts
|
|
2301
|
+
var MENTION_REGEX = /(?:^|[\s>(*_"';\\/[\]{}~`:]|"|>|<|&)@(?:"([^"]+)"|"([^&]+)"|([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*))/g;
|
|
2302
|
+
var MARKDOWN_MENTION_SPLIT_REGEX = /(```[\s\S]*?```|~~~[\s\S]*?~~~|<pre[\s\S]*?<\/pre>|<code[\s\S]*?<\/code>|`[^`\n]+`|<span\b[^>]*\b(?:data-type=["']mention["']|class=["'][^"']*pixerate-mention-node[^"']*["']|data-mention=["'][^"']*["'])[^>]*>[\s\S]*?<\/span>|<[^>]+>|\]\([^)]+\)|(?:https?|file|vscode|cursor|mailto):\/\/[^\s<)]+)/gi;
|
|
2303
|
+
function stripMarkdownCode(content) {
|
|
2304
|
+
if (!content || typeof content !== "string") return "";
|
|
2305
|
+
return content.replace(/```[\s\S]*?```/g, "").replace(/~~~[\s\S]*?~~~/g, "").replace(/<pre[\s\S]*?<\/pre>/gi, "").replace(/<code[\s\S]*?<\/code>/gi, "").replace(/`[^`\n]*`/g, "");
|
|
2306
|
+
}
|
|
2307
|
+
function extractMentions(content) {
|
|
2308
|
+
if (!content || typeof content !== "string") return [];
|
|
2309
|
+
const normalizedMentionNodes = content.replace(
|
|
2310
|
+
/<span\b[^>]*\b(?:data-type=["']mention["']|class=["'][^"']*pixerate-mention-node[^"']*["'])[^>]*>([\s\S]*?)<\/span>/gi,
|
|
2311
|
+
(match2, inner) => {
|
|
2312
|
+
const labelMatch = match2.match(/\bdata-label=["']([^"']+)["']/i);
|
|
2313
|
+
if (labelMatch) return ` @${labelMatch[1]} `;
|
|
2314
|
+
const idMatch = match2.match(/\bdata-id=["']([^"']+)["']/i);
|
|
2315
|
+
if (idMatch) return ` @${idMatch[1]} `;
|
|
2316
|
+
return ` ${inner} `;
|
|
2317
|
+
}
|
|
2318
|
+
);
|
|
2319
|
+
const cleanContent = stripMarkdownCode(normalizedMentionNodes);
|
|
2320
|
+
const withoutUrls = cleanContent.replace(/(?:https?|ftp|file|vscode|cursor|mailto):\/\/[^\s<>()]+/gi, "").replace(/\]\([^)]*\)/g, "]");
|
|
2321
|
+
const textOnly = withoutUrls.replace(/<[^>]+>/g, " ");
|
|
2322
|
+
const mentions = [];
|
|
2323
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2324
|
+
const regex = new RegExp(MENTION_REGEX.source, "g");
|
|
2325
|
+
let match;
|
|
2326
|
+
while ((match = regex.exec(textOnly)) !== null) {
|
|
2327
|
+
const handle = (match[1] ?? match[2] ?? match[3] ?? "").trim();
|
|
2328
|
+
if (handle && !seen.has(handle)) {
|
|
2329
|
+
seen.add(handle);
|
|
2330
|
+
mentions.push(handle);
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
return mentions;
|
|
2334
|
+
}
|
|
2335
|
+
function parseMentionSegments(content) {
|
|
2336
|
+
if (!content) return [];
|
|
2337
|
+
const segments = [];
|
|
2338
|
+
const regex = new RegExp(MENTION_REGEX.source, "g");
|
|
2339
|
+
let lastIndex = 0;
|
|
2340
|
+
let match;
|
|
2341
|
+
while ((match = regex.exec(content)) !== null) {
|
|
2342
|
+
const fullMatch = match[0];
|
|
2343
|
+
const atIndex = fullMatch.indexOf("@");
|
|
2344
|
+
const prefix = atIndex > 0 ? fullMatch.slice(0, atIndex) : "";
|
|
2345
|
+
const mentionToken = fullMatch.slice(atIndex);
|
|
2346
|
+
const handle = match[1] ?? match[2] ?? match[3];
|
|
2347
|
+
const matchStart = match.index + prefix.length;
|
|
2348
|
+
if (matchStart > lastIndex) {
|
|
2349
|
+
segments.push({
|
|
2350
|
+
type: "text",
|
|
2351
|
+
value: content.slice(lastIndex, matchStart)
|
|
2352
|
+
});
|
|
2353
|
+
}
|
|
2354
|
+
segments.push({
|
|
2355
|
+
type: "mention",
|
|
2356
|
+
value: mentionToken,
|
|
2357
|
+
handle
|
|
2358
|
+
});
|
|
2359
|
+
lastIndex = matchStart + mentionToken.length;
|
|
2360
|
+
}
|
|
2361
|
+
if (lastIndex < content.length) {
|
|
2362
|
+
segments.push({
|
|
2363
|
+
type: "text",
|
|
2364
|
+
value: content.slice(lastIndex)
|
|
2365
|
+
});
|
|
2366
|
+
}
|
|
2367
|
+
return segments;
|
|
2368
|
+
}
|
|
2369
|
+
function preprocessMarkdownMentions(content, optionsOrMentionables = []) {
|
|
2370
|
+
if (!content || typeof content !== "string") return "";
|
|
2371
|
+
const options = Array.isArray(optionsOrMentionables) ? { mentionables: optionsOrMentionables } : optionsOrMentionables;
|
|
2372
|
+
const allMentionables = options.mentionables || [];
|
|
2373
|
+
const defaultType = options.defaultType || "user";
|
|
2374
|
+
const resolveMention = options.resolveMention;
|
|
2375
|
+
const parts = content.split(MARKDOWN_MENTION_SPLIT_REGEX);
|
|
2376
|
+
return parts.map((part) => {
|
|
2377
|
+
if (!part) return "";
|
|
2378
|
+
if (part.startsWith("```") || part.startsWith("~~~") || part.startsWith("`") || part.startsWith("](") || /^(?:https?|file|vscode|cursor|mailto):\/\//i.test(part) || /^<pre[\s>]/i.test(part) || /^<code[\s>]/i.test(part) || /^<[^>]+>$/i.test(part) || /^<span\b[^>]*\b(?:data-type=["']mention["']|class=["'][^"']*pixerate-mention-node[^"']*["']|data-mention=["'][^"']*["'])/i.test(
|
|
2379
|
+
part
|
|
2380
|
+
)) {
|
|
2381
|
+
return part;
|
|
2382
|
+
}
|
|
2383
|
+
const regex = new RegExp(MENTION_REGEX.source, "g");
|
|
2384
|
+
return part.replace(regex, (match, quotedHandle, escapedQuotedHandle, standardHandle) => {
|
|
2385
|
+
const atIndex = match.indexOf("@");
|
|
2386
|
+
const prefix = atIndex > 0 ? match.slice(0, atIndex) : "";
|
|
2387
|
+
const rawHandle = (quotedHandle || escapedQuotedHandle || standardHandle || "").trim();
|
|
2388
|
+
if (!rawHandle) return match;
|
|
2389
|
+
const lowerHandle = rawHandle.toLowerCase();
|
|
2390
|
+
const entity = allMentionables.find((e) => {
|
|
2391
|
+
if (e.label?.toLowerCase() === lowerHandle) return true;
|
|
2392
|
+
if (e.handle?.toLowerCase() === lowerHandle) return true;
|
|
2393
|
+
if (e.name?.toLowerCase() === lowerHandle) return true;
|
|
2394
|
+
if (e.id?.toLowerCase() === lowerHandle) return true;
|
|
2395
|
+
if (e.type === "agent" && `agent${(e.handle || e.label || "").toLowerCase()}` === lowerHandle) return true;
|
|
2396
|
+
if (e.aliases?.some(
|
|
2397
|
+
(a) => a.toLowerCase() === lowerHandle || e.type === "agent" && `agent${a.toLowerCase()}` === lowerHandle
|
|
2398
|
+
)) {
|
|
2399
|
+
return true;
|
|
2400
|
+
}
|
|
2401
|
+
return false;
|
|
2402
|
+
});
|
|
2403
|
+
let id = entity?.id;
|
|
2404
|
+
let label = entity?.label || entity?.handle || rawHandle;
|
|
2405
|
+
let type = entity?.type;
|
|
2406
|
+
let avatarUrl = entity?.avatarUrl;
|
|
2407
|
+
let color = entity?.color || entity?.hexColor;
|
|
2408
|
+
if (!entity) {
|
|
2409
|
+
const customResolved = resolveMention?.(rawHandle);
|
|
2410
|
+
if (customResolved) {
|
|
2411
|
+
id = customResolved.id ?? id;
|
|
2412
|
+
label = customResolved.label ?? customResolved.handle ?? label;
|
|
2413
|
+
type = customResolved.type ?? type;
|
|
2414
|
+
avatarUrl = customResolved.avatarUrl ?? avatarUrl;
|
|
2415
|
+
color = customResolved.color ?? customResolved.hexColor ?? color;
|
|
2416
|
+
} else {
|
|
2417
|
+
const stripped = lowerHandle.replace(/^agent[\s\-_]*/i, "");
|
|
2418
|
+
if (["supervisor", "coordinator", "planner", "validator", "executor"].includes(stripped)) {
|
|
2419
|
+
type = "agent";
|
|
2420
|
+
id = stripped;
|
|
2421
|
+
label = stripped;
|
|
2422
|
+
} else if (lowerHandle === "agents") {
|
|
2423
|
+
type = "team";
|
|
2424
|
+
id = "agents";
|
|
2425
|
+
label = "agents";
|
|
2426
|
+
} else {
|
|
2427
|
+
type = defaultType;
|
|
2428
|
+
id = rawHandle;
|
|
2429
|
+
label = rawHandle;
|
|
2430
|
+
}
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
const avatarAttr = avatarUrl ? ` data-avatar-url="${escapeHtml(avatarUrl)}"` : "";
|
|
2434
|
+
const colorAttr = color ? ` data-color="${escapeHtml(color)}"` : "";
|
|
2435
|
+
return `${prefix}<span class="pixerate-mention-node" data-type="mention" data-id="${escapeHtml(
|
|
2436
|
+
id || label
|
|
2437
|
+
)}" data-label="${escapeHtml(label)}" data-mention-suggestion-char="@" data-type-name="${escapeHtml(
|
|
2438
|
+
type || defaultType
|
|
2439
|
+
)}"${avatarAttr}${colorAttr}>@${escapeHtml(label)}</span>`;
|
|
2440
|
+
});
|
|
2441
|
+
}).join("");
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2292
2444
|
// src/serializers/plain-text.ts
|
|
2293
2445
|
function escapeHtml(text) {
|
|
2294
2446
|
if (!text) return "";
|
|
@@ -2413,6 +2565,16 @@ function extractMentionsFromDoc(docOrEditor) {
|
|
|
2413
2565
|
});
|
|
2414
2566
|
}
|
|
2415
2567
|
}
|
|
2568
|
+
if (mentions.length === 0) {
|
|
2569
|
+
const rawHandles = extractMentions(docOrEditor);
|
|
2570
|
+
for (const handle of rawHandles) {
|
|
2571
|
+
mentions.push({
|
|
2572
|
+
id: handle,
|
|
2573
|
+
label: handle,
|
|
2574
|
+
type: "user"
|
|
2575
|
+
});
|
|
2576
|
+
}
|
|
2577
|
+
}
|
|
2416
2578
|
}
|
|
2417
2579
|
return mentions;
|
|
2418
2580
|
}
|
|
@@ -2425,9 +2587,38 @@ var md2 = new import_markdown_it2.default({
|
|
|
2425
2587
|
linkify: true,
|
|
2426
2588
|
breaks: true
|
|
2427
2589
|
}).use(import_markdown_it_task_lists2.default);
|
|
2428
|
-
|
|
2590
|
+
var defaultValidateLink = md2.validateLink;
|
|
2591
|
+
md2.validateLink = (url) => {
|
|
2592
|
+
if (url.startsWith("file://") || url.startsWith("vscode://") || url.startsWith("cursor://")) {
|
|
2593
|
+
return true;
|
|
2594
|
+
}
|
|
2595
|
+
return defaultValidateLink.call(md2, url);
|
|
2596
|
+
};
|
|
2597
|
+
function preprocessMarkdownFileLinks(content) {
|
|
2598
|
+
if (!content) return "";
|
|
2599
|
+
return content.replace(
|
|
2600
|
+
/\[([^\]]+)\]\(((?:file|vscode|cursor):\/\/[^)]+)\)/g,
|
|
2601
|
+
(_match, rawLabel, href) => {
|
|
2602
|
+
const trimmed = rawLabel.trim();
|
|
2603
|
+
const codeMatch = trimmed.match(/^`([^`]+)`$/);
|
|
2604
|
+
const labelContent = codeMatch ? `<code>${codeMatch[1]}</code>` : trimmed;
|
|
2605
|
+
return `<a href="${href}" data-file-link="true" title="Click to copy file path">${labelContent}</a>`;
|
|
2606
|
+
}
|
|
2607
|
+
);
|
|
2608
|
+
}
|
|
2609
|
+
function markdownToTipTapHtml(markdown, options) {
|
|
2429
2610
|
if (!markdown) return "<p></p>";
|
|
2430
|
-
|
|
2611
|
+
let content = markdown;
|
|
2612
|
+
if (options?.preprocessFileLinks) {
|
|
2613
|
+
content = preprocessMarkdownFileLinks(content);
|
|
2614
|
+
}
|
|
2615
|
+
if (options?.preprocessMentions || options?.mentionables || options?.preprocessOptions) {
|
|
2616
|
+
const mentionOpts = options.preprocessOptions || {
|
|
2617
|
+
mentionables: options.mentionables
|
|
2618
|
+
};
|
|
2619
|
+
content = preprocessMarkdownMentions(content, mentionOpts);
|
|
2620
|
+
}
|
|
2621
|
+
return md2.render(content);
|
|
2431
2622
|
}
|
|
2432
2623
|
function getEditorMarkdown(editor) {
|
|
2433
2624
|
if (!editor) return "";
|
|
@@ -4167,6 +4358,8 @@ function createHistoryManager(options = {}) {
|
|
|
4167
4358
|
INSTRUCTION_REGEX,
|
|
4168
4359
|
Image,
|
|
4169
4360
|
LoadingNode,
|
|
4361
|
+
MARKDOWN_MENTION_SPLIT_REGEX,
|
|
4362
|
+
MENTION_REGEX,
|
|
4170
4363
|
Markdown,
|
|
4171
4364
|
Mention,
|
|
4172
4365
|
SlashCommands,
|
|
@@ -4185,6 +4378,7 @@ function createHistoryManager(options = {}) {
|
|
|
4185
4378
|
escapeHtml,
|
|
4186
4379
|
extractCellDependencies,
|
|
4187
4380
|
extractInstructionNames,
|
|
4381
|
+
extractMentions,
|
|
4188
4382
|
extractMentionsFromDoc,
|
|
4189
4383
|
extractTemplateNames,
|
|
4190
4384
|
extractVariableNames,
|
|
@@ -4203,12 +4397,16 @@ function createHistoryManager(options = {}) {
|
|
|
4203
4397
|
markdownToTipTapHtml,
|
|
4204
4398
|
parseCellReference,
|
|
4205
4399
|
parseFormula,
|
|
4400
|
+
parseMentionSegments,
|
|
4206
4401
|
parseRange,
|
|
4207
4402
|
plainTextToTipTapHtml,
|
|
4403
|
+
preprocessMarkdownFileLinks,
|
|
4404
|
+
preprocessMarkdownMentions,
|
|
4208
4405
|
removeImageNode,
|
|
4209
4406
|
resolveTemplates,
|
|
4210
4407
|
resolveTemplatesWithMapping,
|
|
4211
4408
|
resolveVariables,
|
|
4409
|
+
stripMarkdownCode,
|
|
4212
4410
|
templateRegex,
|
|
4213
4411
|
tokenizeFormula,
|
|
4214
4412
|
tokenizePrompt,
|