@haklex/rich-ext-embed 0.0.80 → 0.0.82

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.
@@ -0,0 +1,689 @@
1
+ import { $getNodeByKey, DecoratorNode } from "lexical";
2
+ import { Component, Suspense, createContext, createElement, lazy, use, useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ import { useColorScheme } from "@haklex/rich-editor";
4
+ import { ExternalLink, Github, Trash2 } from "lucide-react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { ActionBar, ActionButton } from "@haklex/rich-editor-ui";
7
+ import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
8
+ //#region src/styles.css.ts
9
+ var semanticClassNames$1 = {
10
+ wrapper: "rich-embed-link-wrapper",
11
+ embed: "rich-embed",
12
+ embedGeneric: "rich-embed--generic",
13
+ embedTweet: "rich-embed--tweet",
14
+ embedYoutube: "rich-embed--youtube",
15
+ embedCodesandbox: "rich-embed--codesandbox",
16
+ embedBilibili: "rich-embed--bilibili",
17
+ embedGithubFile: "rich-embed--github-file",
18
+ embedGithubGist: "rich-embed--github-gist",
19
+ embedThinking: "rich-embed--thinking",
20
+ badge: "rich-embed__badge",
21
+ dot: "rich-embed__dot",
22
+ divider: "rich-embed__divider",
23
+ input: "rich-embed__input"
24
+ };
25
+ var semanticEmbedModifierClass = {
26
+ generic: "rich-embed--generic",
27
+ tweet: "rich-embed--tweet",
28
+ youtube: "rich-embed--youtube",
29
+ codesandbox: "rich-embed--codesandbox",
30
+ bilibili: "rich-embed--bilibili",
31
+ "github-file": "rich-embed--github-file",
32
+ "github-gist": "rich-embed--github-gist",
33
+ thinking: "rich-embed--thinking"
34
+ };
35
+ var wrapper = "_1qucygc1";
36
+ var embed = "_1qucygc2";
37
+ var embedType = {
38
+ generic: "_1qucygc3",
39
+ tweet: "_1qucygc4",
40
+ youtube: "_1qucygc5",
41
+ codesandbox: "_1qucygc6",
42
+ bilibili: "_1qucygc7",
43
+ "github-file": "_1qucygc8",
44
+ "github-gist": "_1qucygc9",
45
+ thinking: "_1qucygca"
46
+ };
47
+ var badge = "_1qucygcb";
48
+ var dot = "_1qucygcc";
49
+ var divider = "_1qucygcd";
50
+ var input = "_1qucygce";
51
+ //#endregion
52
+ //#region src/context/EmbedRendererContext.tsx
53
+ var EmbedRendererCtx = createContext({});
54
+ var EmbedRendererProvider = EmbedRendererCtx.Provider;
55
+ function useEmbedRenderers() {
56
+ return use(EmbedRendererCtx);
57
+ }
58
+ //#endregion
59
+ //#region src/styles-static.css.ts
60
+ var semanticClassNames = {
61
+ ratioContainer: "embed-static-ratio-container",
62
+ ratioInner: "embed-static-ratio-inner",
63
+ iframe: "embed-static-iframe",
64
+ gist: "embed-static-gist",
65
+ gistIframe: "embed-static-gist__iframe",
66
+ sourceLink: "embed-static-source-link",
67
+ githubFile: "embed-static-github-file",
68
+ githubFileCode: "embed-static-github-file__code",
69
+ githubFileCodeLong: "embed-static-github-file__code--long",
70
+ githubFileLine: "embed-static-github-file__line",
71
+ githubFileLineNum: "embed-static-github-file__line-num",
72
+ shiki: "embed-static-shiki",
73
+ fallback: "embed-static-fallback",
74
+ fallbackGeneric: "embed-static-fallback--generic",
75
+ fallbackTweet: "embed-static-fallback--tweet",
76
+ fallbackYoutube: "embed-static-fallback--youtube",
77
+ fallbackCodesandbox: "embed-static-fallback--codesandbox",
78
+ fallbackBilibili: "embed-static-fallback--bilibili",
79
+ fallbackGithubFile: "embed-static-fallback--github-file",
80
+ fallbackGithubGist: "embed-static-fallback--github-gist",
81
+ fallbackThinking: "embed-static-fallback--thinking",
82
+ fallbackBadge: "embed-static-fallback__badge",
83
+ fallbackDot: "embed-static-fallback__dot",
84
+ fallbackLink: "embed-static-fallback__link",
85
+ tweet: "embed-static-tweet",
86
+ loading: "embed-static-loading"
87
+ };
88
+ var semanticFallbackModifierClass = {
89
+ generic: "embed-static-fallback--generic",
90
+ tweet: "embed-static-fallback--tweet",
91
+ youtube: "embed-static-fallback--youtube",
92
+ codesandbox: "embed-static-fallback--codesandbox",
93
+ bilibili: "embed-static-fallback--bilibili",
94
+ "github-file": "embed-static-fallback--github-file",
95
+ "github-gist": "embed-static-fallback--github-gist",
96
+ thinking: "embed-static-fallback--thinking"
97
+ };
98
+ var ratioContainer = "_1xclnej1";
99
+ var ratioInner = "_1xclnej2";
100
+ var iframe = "_1xclnej3";
101
+ var gist = "_1xclnej4";
102
+ var gistIframe = "_1xclnej5";
103
+ var sourceLink = "_1xclnej6";
104
+ var githubFile = "_1xclnej7";
105
+ var githubFileCode = "_1xclnej8";
106
+ var githubFileCodeLong = "_1xclnej9";
107
+ var githubFileLine = "_1xclneja";
108
+ var githubFileLineNum = "_1xclnejb";
109
+ var shiki = "_1xclnejc";
110
+ var fallback = "_1xclnejd";
111
+ var fallbackType = {
112
+ generic: "_1xclneje",
113
+ tweet: "_1xclnejf",
114
+ youtube: "_1xclnejg",
115
+ codesandbox: "_1xclnejh",
116
+ bilibili: "_1xclneji",
117
+ "github-file": "_1xclnejj",
118
+ "github-gist": "_1xclnejk",
119
+ thinking: "_1xclnejl"
120
+ };
121
+ var fallbackBadge = "_1xclnejm";
122
+ var fallbackDot = "_1xclnejn";
123
+ var fallbackLink = "_1xclnejo";
124
+ var tweet = "_1xclnejp";
125
+ var loading = "_1xclnejq";
126
+ //#endregion
127
+ //#region \0@oxc-project+runtime@0.115.0/helpers/typeof.js
128
+ function _typeof(o) {
129
+ "@babel/helpers - typeof";
130
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
131
+ return typeof o;
132
+ } : function(o) {
133
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
134
+ }, _typeof(o);
135
+ }
136
+ //#endregion
137
+ //#region \0@oxc-project+runtime@0.115.0/helpers/toPrimitive.js
138
+ function toPrimitive(t, r) {
139
+ if ("object" != _typeof(t) || !t) return t;
140
+ var e = t[Symbol.toPrimitive];
141
+ if (void 0 !== e) {
142
+ var i = e.call(t, r || "default");
143
+ if ("object" != _typeof(i)) return i;
144
+ throw new TypeError("@@toPrimitive must return a primitive value.");
145
+ }
146
+ return ("string" === r ? String : Number)(t);
147
+ }
148
+ //#endregion
149
+ //#region \0@oxc-project+runtime@0.115.0/helpers/toPropertyKey.js
150
+ function toPropertyKey(t) {
151
+ var i = toPrimitive(t, "string");
152
+ return "symbol" == _typeof(i) ? i : i + "";
153
+ }
154
+ //#endregion
155
+ //#region \0@oxc-project+runtime@0.115.0/helpers/defineProperty.js
156
+ function _defineProperty(e, r, t) {
157
+ return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
158
+ value: t,
159
+ enumerable: !0,
160
+ configurable: !0,
161
+ writable: !0
162
+ }) : e[r] = t, e;
163
+ }
164
+ //#endregion
165
+ //#region src/renderers/EmbedStaticRenderer.tsx
166
+ var extToLang = {
167
+ ".js": "javascript",
168
+ ".ts": "typescript",
169
+ ".mjs": "javascript",
170
+ ".cjs": "javascript",
171
+ ".mts": "typescript",
172
+ ".cts": "typescript",
173
+ ".jsx": "jsx",
174
+ ".tsx": "tsx",
175
+ ".md": "markdown",
176
+ ".css": "css",
177
+ ".scss": "scss",
178
+ ".html": "html",
179
+ ".json": "json",
180
+ ".yml": "yaml",
181
+ ".yaml": "yaml",
182
+ ".toml": "toml",
183
+ ".xml": "xml",
184
+ ".sh": "bash",
185
+ ".bash": "bash",
186
+ ".zsh": "bash",
187
+ ".go": "go",
188
+ ".py": "python",
189
+ ".rb": "ruby",
190
+ ".java": "java",
191
+ ".c": "c",
192
+ ".cpp": "cpp",
193
+ ".cs": "csharp",
194
+ ".rs": "rust",
195
+ ".swift": "swift",
196
+ ".kt": "kotlin",
197
+ ".lua": "lua",
198
+ ".sql": "sql",
199
+ ".graphql": "graphql",
200
+ ".scala": "scala",
201
+ ".dart": "dart",
202
+ ".vue": "vue",
203
+ ".h": "c",
204
+ ".hpp": "cpp",
205
+ ".m": "objectivec",
206
+ ".ex": "elixir",
207
+ ".r": "r"
208
+ };
209
+ function getLangFromPath(path) {
210
+ const dot = path.lastIndexOf(".");
211
+ if (dot === -1) return "text";
212
+ return extToLang[path.slice(dot).toLowerCase()] || "text";
213
+ }
214
+ var shikiPromise = import("shiki/bundle/web").catch(() => null);
215
+ var typeLabels$1 = {
216
+ "tweet": "X / Twitter",
217
+ "youtube": "YouTube",
218
+ "codesandbox": "CodeSandbox",
219
+ "bilibili": "Bilibili",
220
+ "github-file": "GitHub File",
221
+ "github-gist": "GitHub Gist",
222
+ "thinking": "Thinking"
223
+ };
224
+ var LazyTweet = lazy(() => import("react-tweet").then((mod) => ({ default: mod.IsolatedTweet })));
225
+ var EmbedErrorBoundary = class extends Component {
226
+ constructor(..._args) {
227
+ super(..._args);
228
+ _defineProperty(this, "state", { hasError: false });
229
+ }
230
+ static getDerivedStateFromError() {
231
+ return { hasError: true };
232
+ }
233
+ render() {
234
+ return this.state.hasError ? this.props.fallback : this.props.children;
235
+ }
236
+ };
237
+ function GitHubSvg() {
238
+ return /* @__PURE__ */ jsx(Github, { size: 16 });
239
+ }
240
+ function FixedRatioContainer({ children, ratio = 58 }) {
241
+ return /* @__PURE__ */ jsx("div", {
242
+ className: `${ratioContainer} ${semanticClassNames.ratioContainer}`,
243
+ children: /* @__PURE__ */ jsx("div", {
244
+ className: `${ratioInner} ${semanticClassNames.ratioInner}`,
245
+ style: { paddingBottom: `${ratio}%` },
246
+ children
247
+ })
248
+ });
249
+ }
250
+ function FallbackLink({ url, type }) {
251
+ const label = type ? typeLabels$1[type] : "Embed";
252
+ const cssModifier = type || "generic";
253
+ const fallbackTypeClass = fallbackType[cssModifier];
254
+ const semanticModifierClass = semanticFallbackModifierClass[cssModifier];
255
+ return /* @__PURE__ */ jsxs("div", {
256
+ className: `${fallback} ${fallbackTypeClass} ${semanticClassNames.fallback} ${semanticModifierClass}`.trim(),
257
+ children: [/* @__PURE__ */ jsxs("span", {
258
+ className: `${fallbackBadge} ${semanticClassNames.fallbackBadge}`,
259
+ children: [/* @__PURE__ */ jsx("span", { className: `${fallbackDot} ${semanticClassNames.fallbackDot}` }), label]
260
+ }), /* @__PURE__ */ jsx("a", {
261
+ className: `${fallbackLink} ${semanticClassNames.fallbackLink}`,
262
+ href: url,
263
+ rel: "noreferrer",
264
+ target: "_blank",
265
+ children: url
266
+ })]
267
+ });
268
+ }
269
+ function TweetRenderer({ url }) {
270
+ const colorScheme = useColorScheme();
271
+ let parsedUrl;
272
+ try {
273
+ parsedUrl = new URL(url);
274
+ } catch {
275
+ return /* @__PURE__ */ jsx(FallbackLink, {
276
+ type: "tweet",
277
+ url
278
+ });
279
+ }
280
+ const id = parsedUrl.pathname.split("/").pop();
281
+ if (!id) return /* @__PURE__ */ jsx(FallbackLink, {
282
+ type: "tweet",
283
+ url
284
+ });
285
+ return /* @__PURE__ */ jsx(EmbedErrorBoundary, {
286
+ fallback: /* @__PURE__ */ jsx(FallbackLink, {
287
+ type: "tweet",
288
+ url
289
+ }),
290
+ children: /* @__PURE__ */ jsx("div", {
291
+ className: `${tweet} ${semanticClassNames.tweet}`,
292
+ children: /* @__PURE__ */ jsx(Suspense, {
293
+ fallback: /* @__PURE__ */ jsx("div", {
294
+ className: `${loading} ${semanticClassNames.loading}`,
295
+ children: "Loading tweet..."
296
+ }),
297
+ children: /* @__PURE__ */ jsx(LazyTweet, {
298
+ id,
299
+ style: { width: "100%" },
300
+ theme: colorScheme === "dark" ? "dark" : "light"
301
+ })
302
+ })
303
+ })
304
+ });
305
+ }
306
+ function GithubFileEmbed({ url, href }) {
307
+ const shikiTheme = useColorScheme() === "dark" ? "github-dark" : "github-light";
308
+ const [, owner, repo, , ...rest] = url.pathname.split("/");
309
+ const ref = rest[0];
310
+ const path = ref ? rest.slice(1).join("/") : rest.join("/");
311
+ const matchResult = url.hash.match(/L\d+/g);
312
+ let startLine = 0;
313
+ let endLine;
314
+ if (matchResult) if (matchResult.length === 1) {
315
+ startLine = Number.parseInt(matchResult[0].slice(1)) - 1;
316
+ endLine = startLine + 1;
317
+ } else {
318
+ startLine = Number.parseInt(matchResult[0].slice(1)) - 1;
319
+ endLine = Number.parseInt(matchResult[1].slice(1));
320
+ }
321
+ const [content, setContent] = useState(null);
322
+ const [highlightedHtml, setHighlightedHtml] = useState(null);
323
+ const [loading$1, setLoading] = useState(true);
324
+ const [error, setError] = useState(false);
325
+ const lang = useMemo(() => getLangFromPath(path), [path]);
326
+ useEffect(() => {
327
+ let cancelled = false;
328
+ setContent(null);
329
+ setHighlightedHtml(null);
330
+ setLoading(true);
331
+ setError(false);
332
+ const fetchPromise = fetch(`https://cdn.jsdelivr.net/gh/${owner}/${repo}${ref ? `@${ref}` : ""}/${path}`).then((res) => {
333
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
334
+ return res.text();
335
+ });
336
+ Promise.all([fetchPromise, shikiPromise]).then(([text, shikiMod]) => {
337
+ if (cancelled) return;
338
+ setContent(text);
339
+ const lines = text.split("\n");
340
+ const end = endLine ?? lines.length;
341
+ const displayCode = lines.slice(startLine, end).join("\n");
342
+ if (!shikiMod) {
343
+ setLoading(false);
344
+ return;
345
+ }
346
+ shikiMod.codeToHtml(displayCode, {
347
+ lang,
348
+ theme: shikiTheme
349
+ }).then((html) => {
350
+ if (!cancelled) {
351
+ setHighlightedHtml(html);
352
+ setLoading(false);
353
+ }
354
+ }).catch(() => {
355
+ if (!cancelled) setLoading(false);
356
+ });
357
+ }).catch(() => {
358
+ if (!cancelled) {
359
+ setError(true);
360
+ setLoading(false);
361
+ }
362
+ });
363
+ return () => {
364
+ cancelled = true;
365
+ };
366
+ }, [
367
+ owner,
368
+ repo,
369
+ ref,
370
+ path,
371
+ lang,
372
+ startLine,
373
+ endLine,
374
+ shikiTheme
375
+ ]);
376
+ if (loading$1) return /* @__PURE__ */ jsx("div", {
377
+ className: `${loading} ${semanticClassNames.loading}`,
378
+ children: "Loading GitHub File Preview..."
379
+ });
380
+ if (error || content === null) return /* @__PURE__ */ jsx(FallbackLink, {
381
+ type: "github-file",
382
+ url: href
383
+ });
384
+ const lines = content.split("\n");
385
+ const end = endLine ?? lines.length;
386
+ const isLong = end - startLine > 20;
387
+ return /* @__PURE__ */ jsxs("div", {
388
+ className: `${githubFile} ${semanticClassNames.githubFile}`,
389
+ children: [/* @__PURE__ */ jsx("div", {
390
+ className: `${githubFileCode} ${semanticClassNames.githubFileCode} ${isLong ? `${githubFileCodeLong} ${semanticClassNames.githubFileCodeLong}` : ""}`.trim(),
391
+ children: highlightedHtml ? /* @__PURE__ */ jsx("div", {
392
+ className: `${shiki} ${semanticClassNames.shiki}`,
393
+ dangerouslySetInnerHTML: { __html: highlightedHtml },
394
+ style: { "--start-line": startLine }
395
+ }) : /* @__PURE__ */ jsx("pre", { children: /* @__PURE__ */ jsx("code", { children: lines.slice(startLine, end).map((line, i) => /* @__PURE__ */ jsxs("span", {
396
+ className: `${githubFileLine} ${semanticClassNames.githubFileLine}`,
397
+ children: [
398
+ /* @__PURE__ */ jsx("span", {
399
+ className: `${githubFileLineNum} ${semanticClassNames.githubFileLineNum}`,
400
+ children: startLine + i + 1
401
+ }),
402
+ line,
403
+ "\n"
404
+ ]
405
+ }, i)) }) })
406
+ }), /* @__PURE__ */ jsxs("a", {
407
+ className: `${sourceLink} ${semanticClassNames.sourceLink}`,
408
+ href,
409
+ rel: "noreferrer",
410
+ target: "_blank",
411
+ children: [/* @__PURE__ */ jsx(GitHubSvg, {}), /* @__PURE__ */ jsx("span", { children: href })]
412
+ })]
413
+ });
414
+ }
415
+ function EmbedStaticRenderer({ type, url }) {
416
+ const customRenderers = useEmbedRenderers();
417
+ if (!url) return null;
418
+ if (type && customRenderers[type]) {
419
+ const Custom = customRenderers[type];
420
+ return /* @__PURE__ */ jsx(Custom, {
421
+ type,
422
+ url
423
+ });
424
+ }
425
+ let parsedUrl;
426
+ try {
427
+ parsedUrl = new URL(url);
428
+ } catch {
429
+ return /* @__PURE__ */ jsx(FallbackLink, {
430
+ type,
431
+ url
432
+ });
433
+ }
434
+ switch (type) {
435
+ case "tweet": return /* @__PURE__ */ jsx(TweetRenderer, { url });
436
+ case "youtube": {
437
+ const id = parsedUrl.searchParams.get("v");
438
+ if (!id) return /* @__PURE__ */ jsx(FallbackLink, {
439
+ type,
440
+ url
441
+ });
442
+ return /* @__PURE__ */ jsx(FixedRatioContainer, { children: /* @__PURE__ */ jsx("iframe", {
443
+ allowFullScreen: true,
444
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
445
+ className: `${iframe} ${semanticClassNames.iframe}`,
446
+ src: `https://www.youtube.com/embed/${id}`,
447
+ title: "YouTube video player"
448
+ }) });
449
+ }
450
+ case "bilibili": {
451
+ const id = parsedUrl.pathname.split("/")[2];
452
+ if (!id) return /* @__PURE__ */ jsx(FallbackLink, {
453
+ type,
454
+ url
455
+ });
456
+ return /* @__PURE__ */ jsx(FixedRatioContainer, { children: /* @__PURE__ */ jsx("iframe", {
457
+ allowFullScreen: true,
458
+ className: `${iframe} ${semanticClassNames.iframe}`,
459
+ scrolling: "no",
460
+ src: `//player.bilibili.com/player.html?bvid=${id}&autoplay=0`
461
+ }) });
462
+ }
463
+ case "codesandbox": {
464
+ const path = parsedUrl.pathname.slice(2);
465
+ return /* @__PURE__ */ jsx(FixedRatioContainer, { children: /* @__PURE__ */ jsx("iframe", {
466
+ className: `${iframe} ${semanticClassNames.iframe}`,
467
+ src: `https://codesandbox.io/embed/${path}?fontsize=14&hidenavigation=1&theme=dark${parsedUrl.search}`
468
+ }) });
469
+ }
470
+ case "github-gist": {
471
+ const [, owner, id] = parsedUrl.pathname.split("/");
472
+ if (!owner || !id) return /* @__PURE__ */ jsx(FallbackLink, {
473
+ type,
474
+ url
475
+ });
476
+ return /* @__PURE__ */ jsxs("div", {
477
+ className: `${gist} ${semanticClassNames.gist}`,
478
+ children: [/* @__PURE__ */ jsx("iframe", {
479
+ className: `${gistIframe} ${semanticClassNames.gistIframe}`,
480
+ src: `https://gist.github.com/${owner}/${id}.pibb`
481
+ }), /* @__PURE__ */ jsxs("a", {
482
+ className: `${sourceLink} ${semanticClassNames.sourceLink}`,
483
+ href: url,
484
+ rel: "noreferrer",
485
+ target: "_blank",
486
+ children: [/* @__PURE__ */ jsx(GitHubSvg, {}), /* @__PURE__ */ jsx("span", { children: url })]
487
+ })]
488
+ });
489
+ }
490
+ case "github-file": return /* @__PURE__ */ jsx(GithubFileEmbed, {
491
+ href: url,
492
+ url: parsedUrl
493
+ });
494
+ default: return /* @__PURE__ */ jsx(FallbackLink, {
495
+ type,
496
+ url
497
+ });
498
+ }
499
+ }
500
+ //#endregion
501
+ //#region src/nodes/EmbedNode.ts
502
+ var EmbedNode = class EmbedNode extends DecoratorNode {
503
+ static getType() {
504
+ return "embed";
505
+ }
506
+ static clone(node) {
507
+ return new EmbedNode(node.__url, node.__source, node.__key);
508
+ }
509
+ constructor(url, source, key) {
510
+ super(key);
511
+ _defineProperty(this, "__url", void 0);
512
+ _defineProperty(this, "__source", void 0);
513
+ this.__url = url;
514
+ this.__source = source;
515
+ }
516
+ createDOM(_config) {
517
+ const div = document.createElement("div");
518
+ div.className = `${wrapper} ${semanticClassNames$1.wrapper}`;
519
+ return div;
520
+ }
521
+ updateDOM() {
522
+ return false;
523
+ }
524
+ isInline() {
525
+ return false;
526
+ }
527
+ static importJSON(serializedNode) {
528
+ return $createEmbedNode(serializedNode.url, serializedNode.source);
529
+ }
530
+ exportJSON() {
531
+ return {
532
+ ...super.exportJSON(),
533
+ type: "embed",
534
+ url: this.__url,
535
+ source: this.__source,
536
+ version: 1
537
+ };
538
+ }
539
+ getUrl() {
540
+ return this.getLatest().__url;
541
+ }
542
+ setUrl(url) {
543
+ const writable = this.getWritable();
544
+ writable.__url = url;
545
+ }
546
+ getSource() {
547
+ return this.getLatest().__source;
548
+ }
549
+ setSource(source) {
550
+ const writable = this.getWritable();
551
+ writable.__source = source;
552
+ }
553
+ decorate(_editor, _config) {
554
+ return createElement(EmbedStaticRenderer, {
555
+ type: this.__source,
556
+ url: this.__url
557
+ });
558
+ }
559
+ };
560
+ function $createEmbedNode(url, source) {
561
+ return new EmbedNode(url, source);
562
+ }
563
+ function $isEmbedNode(node) {
564
+ return node instanceof EmbedNode;
565
+ }
566
+ //#endregion
567
+ //#region src/url-matchers.ts
568
+ var isTweetUrl = (url) => (url.hostname === "twitter.com" || url.hostname === "x.com") && url.pathname.startsWith("/");
569
+ var isYoutubeUrl = (url) => url.hostname === "www.youtube.com" && url.pathname.startsWith("/watch");
570
+ var isCodesandboxUrl = (url) => url.hostname === "codesandbox.io" && url.pathname.split("/").length === 3;
571
+ var isBilibiliVideoUrl = (url) => url.hostname.includes("bilibili.com") && url.pathname.startsWith("/video/BV");
572
+ var isGithubFilePreviewUrl = (url) => {
573
+ const [, , , type] = url.pathname.split("/");
574
+ return url.hostname === "github.com" && type === "blob";
575
+ };
576
+ var isGistUrl = (url) => url.hostname === "gist.github.com";
577
+ function createSelfThinkingMatcher(hostnames) {
578
+ return (url) => hostnames.includes(url.hostname) && url.pathname.startsWith("/thinking/");
579
+ }
580
+ function matchEmbedUrl(url, selfThinkingMatcher) {
581
+ if (isTweetUrl(url)) return "tweet";
582
+ if (isYoutubeUrl(url)) return "youtube";
583
+ if (isCodesandboxUrl(url)) return "codesandbox";
584
+ if (isBilibiliVideoUrl(url)) return "bilibili";
585
+ if (isGithubFilePreviewUrl(url)) return "github-file";
586
+ if (isGistUrl(url)) return "github-gist";
587
+ if (selfThinkingMatcher?.(url)) return "thinking";
588
+ return null;
589
+ }
590
+ //#endregion
591
+ //#region src/renderers/EmbedLinkRenderer.tsx
592
+ var typeLabels = {
593
+ "tweet": "X / Twitter",
594
+ "youtube": "YouTube",
595
+ "codesandbox": "CodeSandbox",
596
+ "bilibili": "Bilibili",
597
+ "github-file": "GitHub File",
598
+ "github-gist": "GitHub Gist",
599
+ "thinking": "Thinking"
600
+ };
601
+ function EmbedLinkRenderer({ type, url, nodeKey }) {
602
+ const [editor] = useLexicalComposerContext();
603
+ const [editUrl, setEditUrl] = useState(url);
604
+ const inputRef = useRef(null);
605
+ useEffect(() => {
606
+ setEditUrl(url);
607
+ }, [url]);
608
+ useEffect(() => {
609
+ if (!url) inputRef.current?.focus();
610
+ }, [url]);
611
+ const commitUrl = useCallback(() => {
612
+ const trimmed = editUrl.trim();
613
+ if (!trimmed) return;
614
+ editor.update(() => {
615
+ const node = $getNodeByKey(nodeKey);
616
+ if (!node || !("setUrl" in node)) return;
617
+ const n = node;
618
+ if (n.getUrl?.() !== trimmed) n.setUrl(trimmed);
619
+ if (n.setSource) try {
620
+ n.setSource(matchEmbedUrl(new URL(trimmed)));
621
+ } catch {}
622
+ });
623
+ }, [
624
+ editor,
625
+ nodeKey,
626
+ editUrl
627
+ ]);
628
+ const handleKeyDown = useCallback((e) => {
629
+ if (e.key === "Enter") {
630
+ e.preventDefault();
631
+ commitUrl();
632
+ inputRef.current?.blur();
633
+ } else if (e.key === "Escape") {
634
+ e.preventDefault();
635
+ setEditUrl(url);
636
+ inputRef.current?.blur();
637
+ }
638
+ }, [commitUrl, url]);
639
+ const handleDelete = useCallback(() => {
640
+ editor.update(() => {
641
+ const node = $getNodeByKey(nodeKey);
642
+ if (node) node.remove();
643
+ });
644
+ }, [editor, nodeKey]);
645
+ const handleOpen = useCallback(() => {
646
+ if (url) window.open(url, "_blank", "noopener,noreferrer");
647
+ }, [url]);
648
+ const label = type ? typeLabels[type] : "Embed";
649
+ const cssModifier = type || "generic";
650
+ const embedModifierClass = embedType[cssModifier];
651
+ const semanticModifierClass = semanticEmbedModifierClass[cssModifier];
652
+ return /* @__PURE__ */ jsxs("div", {
653
+ className: `${embed} ${embedModifierClass} ${semanticClassNames$1.embed} ${semanticModifierClass}`.trim(),
654
+ children: [
655
+ /* @__PURE__ */ jsxs("span", {
656
+ className: `${badge} ${semanticClassNames$1.badge}`,
657
+ children: [/* @__PURE__ */ jsx("span", { className: `${dot} ${semanticClassNames$1.dot}` }), label]
658
+ }),
659
+ /* @__PURE__ */ jsx("span", { className: `${divider} ${semanticClassNames$1.divider}` }),
660
+ /* @__PURE__ */ jsx("input", {
661
+ className: `${input} ${semanticClassNames$1.input}`,
662
+ placeholder: "https://...",
663
+ ref: inputRef,
664
+ type: "url",
665
+ value: editUrl,
666
+ onBlur: commitUrl,
667
+ onChange: (e) => setEditUrl(e.target.value),
668
+ onKeyDown: handleKeyDown
669
+ }),
670
+ /* @__PURE__ */ jsxs(ActionBar, { children: [/* @__PURE__ */ jsx(ActionButton, {
671
+ icon: true,
672
+ disabled: !url,
673
+ size: "md",
674
+ title: "Open in new tab",
675
+ onClick: handleOpen,
676
+ children: /* @__PURE__ */ jsx(ExternalLink, {})
677
+ }), /* @__PURE__ */ jsx(ActionButton, {
678
+ danger: true,
679
+ icon: true,
680
+ size: "md",
681
+ title: "Delete",
682
+ onClick: handleDelete,
683
+ children: /* @__PURE__ */ jsx(Trash2, {})
684
+ })] })
685
+ ]
686
+ });
687
+ }
688
+ //#endregion
689
+ export { isGistUrl as a, isYoutubeUrl as c, $isEmbedNode as d, EmbedNode as f, useEmbedRenderers as g, EmbedRendererProvider as h, isCodesandboxUrl as i, matchEmbedUrl as l, _defineProperty as m, createSelfThinkingMatcher as n, isGithubFilePreviewUrl as o, EmbedStaticRenderer as p, isBilibiliVideoUrl as r, isTweetUrl as s, EmbedLinkRenderer as t, $createEmbedNode as u };