@haklex/rich-ext-code-snippet 0.0.82 → 0.0.84

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,400 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
+ import { createRendererDecoration } from "@haklex/rich-editor/renderers";
5
+ import { DecoratorNode } from "lexical";
6
+ import { jsxs, jsx } from "react/jsx-runtime";
7
+ import { normalizeLanguage } from "@haklex/rich-renderer-codeblock/constants";
8
+ import { FileIcon } from "@haklex/rich-renderer-codeblock/icons";
9
+ import { getHighlighterWithLang, SHIKI_DUAL_THEMES } from "@haklex/rich-renderer-codeblock/shiki";
10
+ import { Check, Copy } from "lucide-react";
11
+ import { useState, useEffect, useRef, useCallback } from "react";
12
+ function toPrimitive(t, r) {
13
+ if ("object" != typeof t || !t) return t;
14
+ var e = t[Symbol.toPrimitive];
15
+ if (void 0 !== e) {
16
+ var i = e.call(t, r);
17
+ if ("object" != typeof i) return i;
18
+ throw new TypeError("@@toPrimitive must return a primitive value.");
19
+ }
20
+ return ("string" === r ? String : Number)(t);
21
+ }
22
+ function toPropertyKey(t) {
23
+ var i = toPrimitive(t, "string");
24
+ return "symbol" == typeof i ? i : String(i);
25
+ }
26
+ function _defineProperty(obj, key, value) {
27
+ key = toPropertyKey(key);
28
+ if (key in obj) {
29
+ Object.defineProperty(obj, key, {
30
+ value,
31
+ enumerable: true,
32
+ configurable: true,
33
+ writable: true
34
+ });
35
+ } else {
36
+ obj[key] = value;
37
+ }
38
+ return obj;
39
+ }
40
+ function ownKeys(e, r) {
41
+ var t = Object.keys(e);
42
+ if (Object.getOwnPropertySymbols) {
43
+ var o = Object.getOwnPropertySymbols(e);
44
+ r && (o = o.filter(function(r2) {
45
+ return Object.getOwnPropertyDescriptor(e, r2).enumerable;
46
+ })), t.push.apply(t, o);
47
+ }
48
+ return t;
49
+ }
50
+ function _objectSpread2(e) {
51
+ for (var r = 1; r < arguments.length; r++) {
52
+ var t = null != arguments[r] ? arguments[r] : {};
53
+ r % 2 ? ownKeys(Object(t), true).forEach(function(r2) {
54
+ _defineProperty(e, r2, t[r2]);
55
+ }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function(r2) {
56
+ Object.defineProperty(e, r2, Object.getOwnPropertyDescriptor(t, r2));
57
+ });
58
+ }
59
+ return e;
60
+ }
61
+ function mapValues(input, fn) {
62
+ var result = {};
63
+ for (var _key in input) {
64
+ result[_key] = fn(input[_key], _key);
65
+ }
66
+ return result;
67
+ }
68
+ var shouldApplyCompound = (compoundCheck, selections, defaultVariants) => {
69
+ for (var key of Object.keys(compoundCheck)) {
70
+ var _selections$key;
71
+ if (compoundCheck[key] !== ((_selections$key = selections[key]) !== null && _selections$key !== void 0 ? _selections$key : defaultVariants[key])) {
72
+ return false;
73
+ }
74
+ }
75
+ return true;
76
+ };
77
+ var createRuntimeFn = (config) => {
78
+ var runtimeFn = (options) => {
79
+ var className = config.defaultClassName;
80
+ var selections = _objectSpread2(_objectSpread2({}, config.defaultVariants), options);
81
+ for (var variantName in selections) {
82
+ var _selections$variantNa;
83
+ var variantSelection = (_selections$variantNa = selections[variantName]) !== null && _selections$variantNa !== void 0 ? _selections$variantNa : config.defaultVariants[variantName];
84
+ if (variantSelection != null) {
85
+ var selection = variantSelection;
86
+ if (typeof selection === "boolean") {
87
+ selection = selection === true ? "true" : "false";
88
+ }
89
+ var selectionClassName = (
90
+ // @ts-expect-error
91
+ config.variantClassNames[variantName][selection]
92
+ );
93
+ if (selectionClassName) {
94
+ className += " " + selectionClassName;
95
+ }
96
+ }
97
+ }
98
+ for (var [compoundCheck, compoundClassName] of config.compoundVariants) {
99
+ if (shouldApplyCompound(compoundCheck, selections, config.defaultVariants)) {
100
+ className += " " + compoundClassName;
101
+ }
102
+ }
103
+ return className;
104
+ };
105
+ runtimeFn.variants = () => Object.keys(config.variantClassNames);
106
+ runtimeFn.classNames = {
107
+ get base() {
108
+ return config.defaultClassName.split(" ")[0];
109
+ },
110
+ get variants() {
111
+ return mapValues(config.variantClassNames, (classNames) => mapValues(classNames, (className) => className.split(" ")[0]));
112
+ }
113
+ };
114
+ return runtimeFn;
115
+ };
116
+ var semanticClassNames = { container: "rcs-container", header: "rcs-header", tabs: "rcs-tabs", tab: "rcs-tab", tabActive: "rcs-tab-active", titleBar: "rcs-title-bar", headerActions: "rcs-header-actions", copyButton: "rcs-copy-btn", separator: "rcs-separator", codePanelsWrapper: "rcs-code-panels-wrapper", codePanel: "rcs-code-panel", codeScroll: "rcs-code-scroll", codeBody: "rcs-code-body", fileIcon: "rcs-file-icon", editContainer: "rcs-edit-container", editOverlay: "rcs-edit-overlay", editLabel: "rcs-edit-label", modal: "rcs-modal", modalTitlebar: "rcs-modal-titlebar", modalTitle: "rcs-modal-title", modalIconButton: "rcs-modal-icon-btn", modalBody: "rcs-modal-body", modalSidebar: "rcs-modal-sidebar", sidebarHeader: "rcs-sidebar-header", sidebarAddButton: "rcs-sidebar-add-btn", fileList: "rcs-file-list", fileItem: "rcs-file-item", fileItemActive: "rcs-file-item-active", fileItemDragging: "rcs-file-item-dragging", fileDragHandle: "rcs-file-drag-handle", fileName: "rcs-file-name", fileDelete: "rcs-file-delete", renameInput: "rcs-rename-input", modalEditor: "rcs-modal-editor", breadcrumb: "rcs-breadcrumb", breadcrumbLeft: "rcs-breadcrumb-left", breadcrumbName: "rcs-breadcrumb-name", breadcrumbLang: "rcs-breadcrumb-lang", editorContainer: "rcs-editor-container", dragOverlay: "rcs-drag-overlay" };
117
+ var container = "hjkryc0";
118
+ var header = "hjkryc1";
119
+ var tabs = "hjkryc2";
120
+ var tab = createRuntimeFn({ defaultClassName: "hjkryc4 hjkryc3", variantClassNames: { active: { true: "hjkryc5", false: "hjkryc6" } }, defaultVariants: { active: false }, compoundVariants: [] });
121
+ var titleBar = "hjkryc7";
122
+ var headerActions = "hjkryc8";
123
+ var copyButton = "hjkryc9";
124
+ var separator = "hjkryca";
125
+ var codePanelsWrapper = "hjkrycb";
126
+ var codePanel = "hjkrycc";
127
+ var codeScroll = "hjkrycd";
128
+ var codeBody = "hjkryce";
129
+ var fileIcon = "hjkrycf";
130
+ var editContainer = "hjkrycg";
131
+ var editOverlay = "hjkrych";
132
+ var editLabel = "hjkryci";
133
+ var codeSnippetDialogPopup = "hjkrycj";
134
+ var modal = "hjkryck";
135
+ var modalTitlebar = "hjkrycl";
136
+ var modalTitle = "hjkrycm";
137
+ var modalIconButton = "hjkrycn";
138
+ var modalBody = "hjkryco";
139
+ var modalSidebar = "hjkrycp";
140
+ var sidebarHeader = "hjkrycq";
141
+ var sidebarAddButton = "hjkrycr";
142
+ var fileList = "hjkrycs";
143
+ var fileItem = createRuntimeFn({ defaultClassName: "hjkrycu hjkryct", variantClassNames: { active: { true: "hjkrycv", false: "hjkrycw" }, dragging: { true: "hjkrycx", false: "hjkrycy" } }, defaultVariants: { active: false, dragging: false }, compoundVariants: [] });
144
+ var fileDragHandle = "hjkrycz";
145
+ var fileName = "hjkryc10";
146
+ var fileDelete = "hjkryc11";
147
+ var renameInput = "hjkryc12";
148
+ var modalEditor = "hjkryc13";
149
+ var breadcrumb = "hjkryc14";
150
+ var breadcrumbLeft = "hjkryc15";
151
+ var breadcrumbName = "hjkryc16";
152
+ var breadcrumbLang = "hjkryc17";
153
+ var editorContainer = "hjkryc18";
154
+ var dragOverlay = "hjkryc19";
155
+ const EXT_TO_LANG = {
156
+ ts: "typescript",
157
+ tsx: "tsx",
158
+ js: "javascript",
159
+ jsx: "jsx",
160
+ py: "python",
161
+ rs: "rust",
162
+ go: "go",
163
+ java: "java",
164
+ html: "html",
165
+ css: "css",
166
+ scss: "scss",
167
+ json: "json",
168
+ md: "markdown",
169
+ sh: "bash",
170
+ yml: "yaml",
171
+ yaml: "yaml",
172
+ sql: "sql",
173
+ c: "c",
174
+ cpp: "cpp",
175
+ swift: "swift",
176
+ kt: "kotlin",
177
+ rb: "ruby",
178
+ php: "php",
179
+ vue: "vue",
180
+ svelte: "svelte",
181
+ toml: "toml",
182
+ xml: "xml",
183
+ graphql: "graphql",
184
+ gql: "graphql",
185
+ dockerfile: "dockerfile",
186
+ lua: "lua",
187
+ zig: "zig"
188
+ };
189
+ function getLanguageFromFilename(filename) {
190
+ const ext = filename.split(".").pop()?.toLowerCase() ?? "";
191
+ return EXT_TO_LANG[ext] ?? "text";
192
+ }
193
+ const CopyButton = ({ text }) => {
194
+ const [copied, setCopied] = useState(false);
195
+ const timerRef = useRef(void 0);
196
+ const handleCopy = useCallback(() => {
197
+ navigator.clipboard.writeText(text);
198
+ setCopied(true);
199
+ clearTimeout(timerRef.current);
200
+ timerRef.current = setTimeout(() => setCopied(false), 2e3);
201
+ }, [text]);
202
+ return /* @__PURE__ */ jsx(
203
+ "button",
204
+ {
205
+ "aria-label": copied ? "Copied" : "Copy code",
206
+ className: `${copyButton} ${semanticClassNames.copyButton}`,
207
+ type: "button",
208
+ onClick: handleCopy,
209
+ children: copied ? /* @__PURE__ */ jsx(Check, { size: 14 }) : /* @__PURE__ */ jsx(Copy, { size: 14 })
210
+ }
211
+ );
212
+ };
213
+ const CodeSnippetRenderer = ({ files }) => {
214
+ const [activeIndex, setActiveIndex] = useState(0);
215
+ const [htmlMap, setHtmlMap] = useState({});
216
+ const activeFile = files[activeIndex] ?? files[0];
217
+ const isMultiFile = files.length > 1;
218
+ useEffect(() => {
219
+ let cancelled = false;
220
+ (async () => {
221
+ const newHtmlMap = {};
222
+ for (const file of files) {
223
+ const lang = normalizeLanguage(file.language ?? getLanguageFromFilename(file.filename));
224
+ const highlighter = await getHighlighterWithLang(lang);
225
+ if (cancelled) return;
226
+ const loaded = highlighter.getLoadedLanguages();
227
+ const resolvedLang = loaded.includes(lang) ? lang : "text";
228
+ newHtmlMap[file.filename] = highlighter.codeToHtml(file.code, {
229
+ lang: resolvedLang,
230
+ themes: SHIKI_DUAL_THEMES
231
+ });
232
+ }
233
+ if (!cancelled) setHtmlMap(newHtmlMap);
234
+ })();
235
+ return () => {
236
+ cancelled = true;
237
+ };
238
+ }, [files]);
239
+ if (!activeFile) return null;
240
+ return /* @__PURE__ */ jsxs(
241
+ "div",
242
+ {
243
+ "aria-label": "Code snippet",
244
+ className: `${container} ${semanticClassNames.container}`,
245
+ role: "region",
246
+ children: [
247
+ /* @__PURE__ */ jsxs("div", { className: `${header} ${semanticClassNames.header}`, children: [
248
+ isMultiFile ? /* @__PURE__ */ jsx(
249
+ "div",
250
+ {
251
+ "aria-label": "Code file tabs",
252
+ className: `${tabs} ${semanticClassNames.tabs}`,
253
+ role: "tablist",
254
+ children: files.map((file, index) => /* @__PURE__ */ jsxs(
255
+ "button",
256
+ {
257
+ "aria-selected": index === activeIndex,
258
+ className: `${tab({ active: index === activeIndex })} ${semanticClassNames.tab} ${index === activeIndex ? semanticClassNames.tabActive : ""}`.trim(),
259
+ role: "tab",
260
+ type: "button",
261
+ onClick: () => setActiveIndex(index),
262
+ children: [
263
+ /* @__PURE__ */ jsx(
264
+ FileIcon,
265
+ {
266
+ className: `${fileIcon} ${semanticClassNames.fileIcon}`,
267
+ filename: file.filename,
268
+ size: 14
269
+ }
270
+ ),
271
+ /* @__PURE__ */ jsx("span", { children: file.filename })
272
+ ]
273
+ },
274
+ file.filename
275
+ ))
276
+ }
277
+ ) : /* @__PURE__ */ jsxs("div", { className: `${titleBar} ${semanticClassNames.titleBar}`, children: [
278
+ /* @__PURE__ */ jsx(
279
+ FileIcon,
280
+ {
281
+ className: `${fileIcon} ${semanticClassNames.fileIcon}`,
282
+ filename: activeFile.filename,
283
+ size: 14
284
+ }
285
+ ),
286
+ /* @__PURE__ */ jsx("span", { children: activeFile.filename })
287
+ ] }),
288
+ /* @__PURE__ */ jsx("div", { className: `${headerActions} ${semanticClassNames.headerActions}`, children: /* @__PURE__ */ jsx(CopyButton, { text: activeFile.code }) })
289
+ ] }),
290
+ /* @__PURE__ */ jsx("div", { className: `${separator} ${semanticClassNames.separator}` }),
291
+ /* @__PURE__ */ jsx("div", { className: `${codePanelsWrapper} ${semanticClassNames.codePanelsWrapper}`, children: files.map((file, index) => {
292
+ const html = htmlMap[file.filename];
293
+ return /* @__PURE__ */ jsx(
294
+ "div",
295
+ {
296
+ className: `${codePanel} ${semanticClassNames.codePanel}`,
297
+ "data-active": index === activeIndex,
298
+ role: isMultiFile ? "tabpanel" : void 0,
299
+ children: /* @__PURE__ */ jsx("div", { className: `${codeScroll} ${semanticClassNames.codeScroll}`, children: html ? /* @__PURE__ */ jsx(
300
+ "div",
301
+ {
302
+ className: `${codeBody} ${semanticClassNames.codeBody}`,
303
+ dangerouslySetInnerHTML: { __html: html }
304
+ }
305
+ ) : /* @__PURE__ */ jsx("pre", { className: `${codeBody} ${semanticClassNames.codeBody}`, children: /* @__PURE__ */ jsx("code", { children: file.code.split("\n").map((line, i) => /* @__PURE__ */ jsx("span", { className: "line", children: line }, i)) }) }) })
306
+ },
307
+ file.filename
308
+ );
309
+ }) })
310
+ ]
311
+ }
312
+ );
313
+ };
314
+ class CodeSnippetNode extends DecoratorNode {
315
+ constructor(files, key) {
316
+ super(key);
317
+ __publicField(this, "__files");
318
+ this.__files = files;
319
+ }
320
+ static getType() {
321
+ return "code-snippet";
322
+ }
323
+ static clone(node) {
324
+ return new CodeSnippetNode(node.__files, node.__key);
325
+ }
326
+ createDOM(_config) {
327
+ const div = document.createElement("div");
328
+ div.className = "rich-code-snippet";
329
+ return div;
330
+ }
331
+ updateDOM() {
332
+ return false;
333
+ }
334
+ isInline() {
335
+ return false;
336
+ }
337
+ static importJSON(serializedNode) {
338
+ return $createCodeSnippetNode(serializedNode.files);
339
+ }
340
+ exportJSON() {
341
+ return {
342
+ ...super.exportJSON(),
343
+ type: "code-snippet",
344
+ files: this.__files,
345
+ version: 1
346
+ };
347
+ }
348
+ getFiles() {
349
+ return this.getLatest().__files;
350
+ }
351
+ setFiles(files) {
352
+ const writable = this.getWritable();
353
+ writable.__files = files;
354
+ }
355
+ decorate(_editor, _config) {
356
+ return createRendererDecoration("CodeSnippet", CodeSnippetRenderer, {
357
+ files: this.__files
358
+ });
359
+ }
360
+ }
361
+ function $createCodeSnippetNode(files) {
362
+ return new CodeSnippetNode(files);
363
+ }
364
+ function $isCodeSnippetNode(node) {
365
+ return node instanceof CodeSnippetNode;
366
+ }
367
+ export {
368
+ $isCodeSnippetNode as $,
369
+ editOverlay as A,
370
+ editLabel as B,
371
+ CodeSnippetRenderer as C,
372
+ CodeSnippetNode as D,
373
+ $createCodeSnippetNode as E,
374
+ modalTitlebar as a,
375
+ modalTitle as b,
376
+ modalIconButton as c,
377
+ modalBody as d,
378
+ modalSidebar as e,
379
+ sidebarHeader as f,
380
+ getLanguageFromFilename as g,
381
+ sidebarAddButton as h,
382
+ fileList as i,
383
+ dragOverlay as j,
384
+ fileIcon as k,
385
+ fileName as l,
386
+ modal as m,
387
+ fileItem as n,
388
+ modalEditor as o,
389
+ breadcrumb as p,
390
+ breadcrumbLeft as q,
391
+ breadcrumbName as r,
392
+ semanticClassNames as s,
393
+ breadcrumbLang as t,
394
+ editorContainer as u,
395
+ fileDragHandle as v,
396
+ renameInput as w,
397
+ fileDelete as x,
398
+ codeSnippetDialogPopup as y,
399
+ editContainer as z
400
+ };