@intlayer/design-system 9.3.0 → 9.3.1
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/README.md +22 -22
- package/dist/esm/api/hooks/utils.mjs +2 -1
- package/dist/esm/api/hooks/utils.mjs.map +1 -1
- package/dist/esm/api/index.mjs +2 -2
- package/dist/esm/api/useAuth/useOAuth2.mjs +13 -3
- package/dist/esm/api/useAuth/useOAuth2.mjs.map +1 -1
- package/dist/esm/api/useAuth/useSession.mjs +6 -4
- package/dist/esm/api/useAuth/useSession.mjs.map +1 -1
- package/dist/esm/components/Accordion/Accordion.mjs +1 -1
- package/dist/esm/components/Avatar/index.mjs +1 -1
- package/dist/esm/components/Badge/index.mjs +1 -1
- package/dist/esm/components/Breadcrumb/index.mjs +1 -1
- package/dist/esm/components/Browser/Browser.mjs +1 -1
- package/dist/esm/components/Button/Button.mjs +1 -1
- package/dist/esm/components/Carousel/index.mjs +1 -1
- package/dist/esm/components/CollapsibleTable/CollapsibleTable.mjs +1 -1
- package/dist/esm/components/Command/index.mjs +1 -1
- package/dist/esm/components/Container/index.mjs +1 -1
- package/dist/esm/components/ContentEditor/ContentEditor.mjs +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorInput.mjs +1 -1
- package/dist/esm/components/ContentEditor/ContentEditorTextArea.mjs +2 -2
- package/dist/esm/components/CopyButton/index.mjs +1 -1
- package/dist/esm/components/CopyToClipboard/index.mjs +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/BooleanWrapper.mjs +2 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/BooleanWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/NumberWrapper.mjs +2 -1
- package/dist/esm/components/DictionaryEditor/NodeWrapper/NumberWrapper.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/ContentEditor.mjs +2 -2
- package/dist/esm/components/DictionaryFieldEditor/ContentEditorView/TextEditor.mjs +3 -3
- package/dist/esm/components/DictionaryFieldEditor/DictionaryCreationForm/DictionaryCreationForm.mjs +1 -1
- package/dist/esm/components/DictionaryFieldEditor/DictionaryDetails/DictionaryDetailsForm.mjs +7 -7
- package/dist/esm/components/DictionaryFieldEditor/DictionaryFieldEditor.mjs +2 -2
- package/dist/esm/components/DictionaryFieldEditor/KeyPathBreadcrumb.mjs +8 -7
- package/dist/esm/components/DictionaryFieldEditor/KeyPathBreadcrumb.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs +8 -5
- package/dist/esm/components/DictionaryFieldEditor/NavigationView/NavigationViewNode.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/NodeTypeSelector.mjs +2 -1
- package/dist/esm/components/DictionaryFieldEditor/NodeTypeSelector.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/SaveForm/SaveForm.mjs +3 -3
- package/dist/esm/components/DictionaryFieldEditor/StructureEditor.mjs +2 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureEditor.mjs.map +1 -1
- package/dist/esm/components/DictionaryFieldEditor/StructureView/StructureView.mjs +2 -2
- package/dist/esm/components/DictionaryFieldEditor/VersionSwitcherDropDown/VersionSwitcher.mjs +1 -1
- package/dist/esm/components/EditableField/EditableFieldInput.mjs +6 -5
- package/dist/esm/components/EditableField/EditableFieldInput.mjs.map +1 -1
- package/dist/esm/components/EditableField/EditableFieldLayout.mjs +1 -1
- package/dist/esm/components/EditableField/EditableFieldTextArea.mjs +2 -1
- package/dist/esm/components/EditableField/EditableFieldTextArea.mjs.map +1 -1
- package/dist/esm/components/Form/elements/OTPElement.mjs +1 -1
- package/dist/esm/components/HTMLRender/HTMLRender.mjs +5 -3
- package/dist/esm/components/HTMLRender/HTMLRender.mjs.map +1 -1
- package/dist/esm/components/HideShow/index.mjs +1 -1
- package/dist/esm/components/IDE/Code.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockClient.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockHighlight.mjs +3 -14
- package/dist/esm/components/IDE/CodeBlockHighlight.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockServer.mjs +14 -12
- package/dist/esm/components/IDE/CodeBlockServer.mjs.map +1 -1
- package/dist/esm/components/IDE/CodeBlockShiki.mjs +32 -86
- package/dist/esm/components/IDE/CodeBlockShiki.mjs.map +1 -1
- package/dist/esm/components/IDE/FileTree.mjs +3 -2
- package/dist/esm/components/IDE/FileTree.mjs.map +1 -1
- package/dist/esm/components/IDE/MarkDownRender.mjs.map +1 -1
- package/dist/esm/components/IDE/shikiLanguages.mjs +122 -0
- package/dist/esm/components/IDE/shikiLanguages.mjs.map +1 -0
- package/dist/esm/components/Input/Checkbox.mjs +1 -1
- package/dist/esm/components/Input/Input.mjs +1 -1
- package/dist/esm/components/Input/InputPassword.mjs +1 -1
- package/dist/esm/components/Input/OTPInput.mjs +5 -4
- package/dist/esm/components/Input/OTPInput.mjs.map +1 -1
- package/dist/esm/components/Input/Radio.mjs +1 -1
- package/dist/esm/components/Input/SearchInput.mjs +1 -1
- package/dist/esm/components/LanguageBackground/LanguageBackground.mjs +2 -1
- package/dist/esm/components/LanguageBackground/LanguageBackground.mjs.map +1 -1
- package/dist/esm/components/Link/Link.mjs +1 -1
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs +7 -6
- package/dist/esm/components/LocaleSwitcherContentDropDown/LocaleSwitcherContent.mjs.map +1 -1
- package/dist/esm/components/LocaleSwitcherDropDown/LocaleSwitcher.mjs +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownIframe.mjs +1 -1
- package/dist/esm/components/MarkDownRender/MarkDownRender.mjs +12 -7
- package/dist/esm/components/MarkDownRender/MarkDownRender.mjs.map +1 -1
- package/dist/esm/components/MarkdownEditor/generative/AICompletionCommands.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/generative/AISelector.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/generative/AISelectorCommands.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/generative/GenerativeMenuSwitch.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/selectors/ColorSelector.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/selectors/LinkSelector.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/selectors/NodeSelector.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/selectors/TextButtons.mjs +1 -1
- package/dist/esm/components/MarkdownEditor/slashCommand.mjs +1 -1
- package/dist/esm/components/Modal/Modal.mjs +3 -3
- package/dist/esm/components/Navbar/MobileNavbar.mjs +1 -1
- package/dist/esm/components/Pagination/Pagination.mjs +2 -2
- package/dist/esm/components/PressableSpan/PressableSpan.mjs +0 -2
- package/dist/esm/components/PressableSpan/PressableSpan.mjs.map +1 -1
- package/dist/esm/components/RightDrawer/RightDrawer.mjs +4 -4
- package/dist/esm/components/Select/Multiselect.mjs +3 -5
- package/dist/esm/components/Select/Multiselect.mjs.map +1 -1
- package/dist/esm/components/Select/Select.mjs +1 -1
- package/dist/esm/components/SwitchSelector/SwitchSelector.mjs +1 -1
- package/dist/esm/components/SwitchSelector/VerticalSwitchSelector.mjs +1 -1
- package/dist/esm/components/Tab/Tab.mjs +2 -2
- package/dist/esm/components/TabSelector/TabSelector.mjs +1 -1
- package/dist/esm/components/Table/ExpandButton.mjs +1 -1
- package/dist/esm/components/Tag/index.mjs +1 -1
- package/dist/esm/components/Terminal/Terminal.mjs +7 -5
- package/dist/esm/components/Terminal/Terminal.mjs.map +1 -1
- package/dist/esm/components/TextArea/AutocompleteTextArea.mjs +6 -3
- package/dist/esm/components/TextArea/AutocompleteTextArea.mjs.map +1 -1
- package/dist/esm/components/ThemeSwitcherDropDown/DesktopThemeSwitcher.mjs +1 -1
- package/dist/esm/components/ThemeSwitcherDropDown/MobileThemeSwitcher.mjs +1 -1
- package/dist/esm/components/Toaster/Toast.mjs +1 -1
- package/dist/esm/components/Toaster/useToast.mjs +1 -1
- package/dist/esm/components/Toaster/useToast.mjs.map +1 -1
- package/dist/esm/hooks/index.mjs +8 -8
- package/dist/esm/hooks/useScrollDetection.mjs +4 -2
- package/dist/esm/hooks/useScrollDetection.mjs.map +1 -1
- package/dist/esm/providers/DeferredAuthProvider.mjs +75 -0
- package/dist/esm/providers/DeferredAuthProvider.mjs.map +1 -0
- package/dist/esm/providers/ReactQueryProvider.mjs +4 -4
- package/dist/esm/providers/ReactQueryProvider.mjs.map +1 -1
- package/dist/esm/providers/index.mjs +2 -1
- package/dist/esm/routes.mjs +12 -11
- package/dist/esm/routes.mjs.map +1 -1
- package/dist/esm/structured-data/buildAuthorJsonLd.mjs +6 -3
- package/dist/esm/structured-data/buildAuthorJsonLd.mjs.map +1 -1
- package/dist/esm/structured-data/buildBreadcrumbsJsonLd.mjs +4 -1
- package/dist/esm/structured-data/buildBreadcrumbsJsonLd.mjs.map +1 -1
- package/dist/esm/structured-data/buildCreativeWorkJsonLd.mjs +7 -5
- package/dist/esm/structured-data/buildCreativeWorkJsonLd.mjs.map +1 -1
- package/dist/esm/structured-data/buildOrganizationJsonLd.mjs +27 -21
- package/dist/esm/structured-data/buildOrganizationJsonLd.mjs.map +1 -1
- package/dist/esm/structured-data/buildProductJsonLd.mjs +5 -2
- package/dist/esm/structured-data/buildProductJsonLd.mjs.map +1 -1
- package/dist/esm/structured-data/buildSoftwareApplicationJsonLd.mjs +59 -51
- package/dist/esm/structured-data/buildSoftwareApplicationJsonLd.mjs.map +1 -1
- package/dist/esm/structured-data/buildWebsiteJsonLd.mjs +31 -25
- package/dist/esm/structured-data/buildWebsiteJsonLd.mjs.map +1 -1
- package/dist/esm/structured-data/index.mjs +2 -1
- package/dist/esm/structured-data/normalizeJsonLdUrl.mjs +34 -0
- package/dist/esm/structured-data/normalizeJsonLdUrl.mjs.map +1 -0
- package/dist/esm/tailwind.config.mjs +4 -2
- package/dist/esm/tailwind.config.mjs.map +1 -1
- package/dist/types/api/index.d.ts +2 -2
- package/dist/types/api/useAuth/index.d.ts +2 -2
- package/dist/types/api/useAuth/useOAuth2.d.ts +12 -3
- package/dist/types/api/useAuth/useOAuth2.d.ts.map +1 -1
- package/dist/types/api/useAuth/useSession.d.ts.map +1 -1
- package/dist/types/components/IDE/Code.d.ts +2 -2
- package/dist/types/components/IDE/CodeBlockClient.d.ts +2 -2
- package/dist/types/components/IDE/CodeBlockHighlight.d.ts +2 -2
- package/dist/types/components/IDE/CodeBlockHighlight.d.ts.map +1 -1
- package/dist/types/components/IDE/CodeBlockShiki.d.ts +2 -2
- package/dist/types/components/IDE/CodeBlockShiki.d.ts.map +1 -1
- package/dist/types/components/IDE/index.d.ts +2 -1
- package/dist/types/components/IDE/shikiLanguages.d.ts +138 -0
- package/dist/types/components/IDE/shikiLanguages.d.ts.map +1 -0
- package/dist/types/components/index.d.ts +2 -1
- package/dist/types/providers/DeferredAuthProvider.d.ts +33 -0
- package/dist/types/providers/DeferredAuthProvider.d.ts.map +1 -0
- package/dist/types/providers/index.d.ts +2 -1
- package/dist/types/routes.d.ts +17 -16
- package/dist/types/routes.d.ts.map +1 -1
- package/dist/types/structured-data/buildAuthorJsonLd.d.ts.map +1 -1
- package/dist/types/structured-data/buildBreadcrumbsJsonLd.d.ts.map +1 -1
- package/dist/types/structured-data/buildCreativeWorkJsonLd.d.ts.map +1 -1
- package/dist/types/structured-data/buildOrganizationJsonLd.d.ts.map +1 -1
- package/dist/types/structured-data/buildProductJsonLd.d.ts.map +1 -1
- package/dist/types/structured-data/buildSoftwareApplicationJsonLd.d.ts.map +1 -1
- package/dist/types/structured-data/buildWebsiteJsonLd.d.ts.map +1 -1
- package/dist/types/structured-data/index.d.ts +2 -1
- package/dist/types/structured-data/normalizeJsonLdUrl.d.ts +28 -0
- package/dist/types/structured-data/normalizeJsonLdUrl.d.ts.map +1 -0
- package/package.json +43 -43
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlockHighlight.mjs","names":[],"sources":["../../../../src/components/IDE/CodeBlockHighlight.tsx"],"sourcesContent":["'use client';\n\n/**\n * Client-side Shiki highlighter that also handles TypeScript→ESM/CJS transformation.\n *\n * Everything runs inside a single useEffect so that:\n * - The transformer is only dynamically imported when a non-TypeScript format is selected.\n * - The previous highlighted HTML stays visible while the new one loads (no white-text flash).\n */\n\nimport { type ReactNode, useEffect, useRef, useState } from 'react';\nimport type {
|
|
1
|
+
{"version":3,"file":"CodeBlockHighlight.mjs","names":[],"sources":["../../../../src/components/IDE/CodeBlockHighlight.tsx"],"sourcesContent":["'use client';\n\n/**\n * Client-side Shiki highlighter that also handles TypeScript→ESM/CJS transformation.\n *\n * Everything runs inside a single useEffect so that:\n * - The transformer is only dynamically imported when a non-TypeScript format is selected.\n * - The previous highlighted HTML stays visible while the new one loads (no white-text flash).\n */\n\nimport { type ReactNode, useEffect, useRef, useState } from 'react';\nimport type { CodeFormat } from './CodeContext';\nimport { type CodeLanguage, resolveCodeLanguage } from './shikiLanguages';\n\ntype Props = {\n /** Raw TypeScript source code (the canonical \"source of truth\"). */\n children: ReactNode;\n /** Language of the source (e.g. 'tsx', 'typescript'). */\n originalLang: CodeLanguage;\n /** Currently selected format: 'typescript' | 'esm' | 'commonjs'. */\n targetFormat: Exclude<CodeFormat, 'json'>;\n isDarkMode?: boolean;\n};\n\nexport const CodeBlockHighlight = ({\n children,\n originalLang,\n targetFormat,\n isDarkMode,\n}: Props) => {\n const [html, setHtml] = useState<string | null>(null);\n const prevHtml = useRef<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n\n (async () => {\n try {\n let code = children;\n let shikiLang = resolveCodeLanguage(originalLang).id;\n\n // Only import the transformer when we actually need it.\n if (targetFormat !== 'typescript') {\n const { transformCode, deriveLanguage } = await import(\n './codeTransformer'\n );\n if (cancelled) return;\n code = transformCode(String(children), targetFormat);\n shikiLang = resolveCodeLanguage(\n deriveLanguage(originalLang, targetFormat)\n ).id;\n }\n\n const { codeToHtml } = await import('shiki/bundle/web');\n if (cancelled) return;\n\n const out = await codeToHtml(String(code), {\n lang: shikiLang,\n theme: isDarkMode ? 'github-dark' : 'github-light',\n });\n\n if (!cancelled) {\n prevHtml.current = out;\n setHtml(out);\n }\n } catch {\n // Shiki failed (unknown language, etc.) — fall through to plain-text.\n if (!cancelled) setHtml('');\n }\n })();\n\n return () => {\n cancelled = true;\n };\n }, [children, originalLang, targetFormat, isDarkMode]);\n\n // Keep the previous highlighted output visible while the new one is loading.\n // This prevents the white-text flash on format switches.\n const display = html ?? prevHtml.current;\n\n if (!display) {\n return (\n <pre className=\"min-w-0 max-w-full overflow-x-auto\">\n <code>{children}</code>\n </pre>\n );\n }\n\n return (\n <div\n dangerouslySetInnerHTML={{ __html: display }}\n style={{ backgroundColor: 'transparent' }}\n />\n );\n};\n"],"mappings":";;;;;;;;;;;;;;AAwBA,MAAa,sBAAsB,EACjC,UACA,cACA,cACA,iBACW;CACX,MAAM,CAAC,MAAM,WAAW,SAAwB,IAAI;CACpD,MAAM,WAAW,OAAsB,IAAI;CAE3C,gBAAgB;EACd,IAAI,YAAY;EAEhB,CAAC,YAAY;GACX,IAAI;IACF,IAAI,OAAO;IACX,IAAI,YAAY,oBAAoB,YAAY,CAAC,CAAC;IAGlD,IAAI,iBAAiB,cAAc;KACjC,MAAM,EAAE,eAAe,mBAAmB,MAAM,OAC9C;KAEF,IAAI,WAAW;KACf,OAAO,cAAc,OAAO,QAAQ,GAAG,YAAY;KACnD,YAAY,oBACV,eAAe,cAAc,YAAY,CAC3C,CAAC,CAAC;IACJ;IAEA,MAAM,EAAE,eAAe,MAAM,OAAO;IACpC,IAAI,WAAW;IAEf,MAAM,MAAM,MAAM,WAAW,OAAO,IAAI,GAAG;KACzC,MAAM;KACN,OAAO,aAAa,gBAAgB;IACtC,CAAC;IAED,IAAI,CAAC,WAAW;KACd,SAAS,UAAU;KACnB,QAAQ,GAAG;IACb;GACF,QAAQ;IAEN,IAAI,CAAC,WAAW,QAAQ,EAAE;GAC5B;EACF,EAAC,CAAE;EAEH,aAAa;GACX,YAAY;EACd;CACF,GAAG;EAAC;EAAU;EAAc;EAAc;CAAU,CAAC;CAIrD,MAAM,UAAU,QAAQ,SAAS;CAEjC,IAAI,CAAC,SACH,OACE,oBAAC,OAAD;EAAK,WAAU;YACb,oBAAC,QAAD,EAAO,SAAe;CACnB;CAIT,OACE,oBAAC,OAAD;EACE,yBAAyB,EAAE,QAAQ,QAAQ;EAC3C,OAAO,EAAE,iBAAiB,cAAc;CACzC;AAEL"}
|
|
@@ -6,19 +6,21 @@ import { codeToHtml } from "shiki/bundle/web";
|
|
|
6
6
|
|
|
7
7
|
//#region src/components/IDE/CodeBlockServer.tsx
|
|
8
8
|
const CodeBlockShiki = (async ({ children, lang, isDarkMode, onChange, ...props }) => {
|
|
9
|
+
const shikiOptions = {
|
|
10
|
+
lang,
|
|
11
|
+
theme: isDarkMode ? "github-dark" : "github-light",
|
|
12
|
+
transformers: [
|
|
13
|
+
transformerNotationDiff(),
|
|
14
|
+
transformerNotationHighlight(),
|
|
15
|
+
transformerNotationWordHighlight(),
|
|
16
|
+
transformerNotationErrorLevel(),
|
|
17
|
+
transformerMetaHighlight(),
|
|
18
|
+
transformerMetaWordHighlight()
|
|
19
|
+
]
|
|
20
|
+
};
|
|
21
|
+
const out = await codeToHtml(children, shikiOptions);
|
|
9
22
|
return /* @__PURE__ */ jsx("div", {
|
|
10
|
-
dangerouslySetInnerHTML: { __html:
|
|
11
|
-
lang,
|
|
12
|
-
theme: isDarkMode ? "github-dark" : "github-light",
|
|
13
|
-
transformers: [
|
|
14
|
-
transformerNotationDiff(),
|
|
15
|
-
transformerNotationHighlight(),
|
|
16
|
-
transformerNotationWordHighlight(),
|
|
17
|
-
transformerNotationErrorLevel(),
|
|
18
|
-
transformerMetaHighlight(),
|
|
19
|
-
transformerMetaWordHighlight()
|
|
20
|
-
]
|
|
21
|
-
}) },
|
|
23
|
+
dangerouslySetInnerHTML: { __html: out },
|
|
22
24
|
...props,
|
|
23
25
|
style: { backgroundColor: "transparent" }
|
|
24
26
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlockServer.mjs","names":[],"sources":["../../../../src/components/IDE/CodeBlockServer.tsx"],"sourcesContent":["import {\n transformerMetaHighlight,\n transformerMetaWordHighlight,\n transformerNotationDiff,\n transformerNotationErrorLevel,\n transformerNotationHighlight,\n transformerNotationWordHighlight,\n} from '@shikijs/transformers';\nimport { cn } from '@utils/cn';\nimport { type FC, type HTMLAttributes, Suspense } from 'react';\nimport {\n type BundledLanguage,\n type BundledTheme,\n type CodeToHastOptions,\n codeToHtml,\n} from 'shiki/bundle/web';\n\nexport const CodeBlockShiki = (async ({\n children,\n lang,\n isDarkMode,\n onChange,\n ...props\n}: CodeBlockProps) => {\n const shikiOptions: CodeToHastOptions<BundledLanguage, BundledTheme> = {\n lang,\n theme: isDarkMode ? 'github-dark' : 'github-light',\n transformers: [\n transformerNotationDiff(),\n transformerNotationHighlight(),\n transformerNotationWordHighlight(),\n transformerNotationErrorLevel(),\n transformerMetaHighlight(),\n transformerMetaWordHighlight(),\n ],\n };\n\n const out = await codeToHtml(children, shikiOptions);\n\n return (\n <div\n dangerouslySetInnerHTML={{ __html: out }}\n {...props}\n style={{ backgroundColor: 'transparent' }}\n />\n );\n}) as unknown as FC<CodeBlockProps>;\n\nconst CodeDefault: FC<CodeBlockProps> = ({\n children,\n isEditable,\n isDarkMode,\n onChange,\n ...props\n}) => (\n <div contentEditable={isEditable} {...props}>\n <pre>\n <code>\n {typeof children === 'string'\n ? children.split('\\n').map((line, index) => (\n <span className=\"line block w-full\" key={index}>\n {line}\n </span>\n ))\n : children}\n </code>\n </pre>\n </div>\n);\n\nexport type CodeBlockProps = {\n children: string;\n lang: BundledLanguage;\n isDarkMode?: boolean;\n isEditable?: boolean;\n onChange?: (content: string) => void;\n} & Omit<HTMLAttributes<HTMLDivElement>, 'onChange'>;\n\nexport const CodeBlock: FC<CodeBlockProps> = ({\n className,\n onChange,\n isEditable,\n ...props\n}) => (\n <Suspense fallback={<CodeDefault {...props} />}>\n <CodeBlockShiki\n className={cn('flex w-full', className)}\n contentEditable={isEditable}\n onInput={(e) => onChange?.(e.currentTarget.textContent ?? '')}\n {...props}\n />\n </Suspense>\n);\n"],"mappings":";;;;;;;AAiBA,MAAa,kBAAkB,OAAO,EACpC,UACA,MACA,YACA,UACA,GAAG,YACiB;
|
|
1
|
+
{"version":3,"file":"CodeBlockServer.mjs","names":[],"sources":["../../../../src/components/IDE/CodeBlockServer.tsx"],"sourcesContent":["import {\n transformerMetaHighlight,\n transformerMetaWordHighlight,\n transformerNotationDiff,\n transformerNotationErrorLevel,\n transformerNotationHighlight,\n transformerNotationWordHighlight,\n} from '@shikijs/transformers';\nimport { cn } from '@utils/cn';\nimport { type FC, type HTMLAttributes, Suspense } from 'react';\nimport {\n type BundledLanguage,\n type BundledTheme,\n type CodeToHastOptions,\n codeToHtml,\n} from 'shiki/bundle/web';\n\nexport const CodeBlockShiki = (async ({\n children,\n lang,\n isDarkMode,\n onChange,\n ...props\n}: CodeBlockProps) => {\n const shikiOptions: CodeToHastOptions<BundledLanguage, BundledTheme> = {\n lang,\n theme: isDarkMode ? 'github-dark' : 'github-light',\n transformers: [\n transformerNotationDiff(),\n transformerNotationHighlight(),\n transformerNotationWordHighlight(),\n transformerNotationErrorLevel(),\n transformerMetaHighlight(),\n transformerMetaWordHighlight(),\n ],\n };\n\n const out = await codeToHtml(children, shikiOptions);\n\n return (\n <div\n dangerouslySetInnerHTML={{ __html: out }}\n {...props}\n style={{ backgroundColor: 'transparent' }}\n />\n );\n}) as unknown as FC<CodeBlockProps>;\n\nconst CodeDefault: FC<CodeBlockProps> = ({\n children,\n isEditable,\n isDarkMode,\n onChange,\n ...props\n}) => (\n <div contentEditable={isEditable} {...props}>\n <pre>\n <code>\n {typeof children === 'string'\n ? children.split('\\n').map((line, index) => (\n <span className=\"line block w-full\" key={index}>\n {line}\n </span>\n ))\n : children}\n </code>\n </pre>\n </div>\n);\n\nexport type CodeBlockProps = {\n children: string;\n lang: BundledLanguage;\n isDarkMode?: boolean;\n isEditable?: boolean;\n onChange?: (content: string) => void;\n} & Omit<HTMLAttributes<HTMLDivElement>, 'onChange'>;\n\nexport const CodeBlock: FC<CodeBlockProps> = ({\n className,\n onChange,\n isEditable,\n ...props\n}) => (\n <Suspense fallback={<CodeDefault {...props} />}>\n <CodeBlockShiki\n className={cn('flex w-full', className)}\n contentEditable={isEditable}\n onInput={(e) => onChange?.(e.currentTarget.textContent ?? '')}\n {...props}\n />\n </Suspense>\n);\n"],"mappings":";;;;;;;AAiBA,MAAa,kBAAkB,OAAO,EACpC,UACA,MACA,YACA,UACA,GAAG,YACiB;CACpB,MAAM,eAAiE;EACrE;EACA,OAAO,aAAa,gBAAgB;EACpC,cAAc;GACZ,wBAAwB;GACxB,6BAA6B;GAC7B,iCAAiC;GACjC,8BAA8B;GAC9B,yBAAyB;GACzB,6BAA6B;EAC/B;CACF;CAEA,MAAM,MAAM,MAAM,WAAW,UAAU,YAAY;CAEnD,OACE,oBAAC,OAAD;EACE,yBAAyB,EAAE,QAAQ,IAAI;EACvC,GAAI;EACJ,OAAO,EAAE,iBAAiB,cAAc;CACzC;AAEL;AAEA,MAAM,eAAmC,EACvC,UACA,YACA,YACA,UACA,GAAG,YAEH,oBAAC,OAAD;CAAK,iBAAiB;CAAY,GAAI;WACpC,oBAAC,OAAD,YACE,oBAAC,QAAD,YACG,OAAO,aAAa,WACjB,SAAS,MAAM,IAAI,CAAC,CAAC,KAAK,MAAM,UAC9B,oBAAC,QAAD;EAAM,WAAU;YACb;CACG,GAFmC,KAEnC,CACP,IACD,SACA,GACH;AACF;AAWP,MAAa,aAAiC,EAC5C,WACA,UACA,YACA,GAAG,YAEH,oBAAC,UAAD;CAAU,UAAU,oBAAC,aAAD,EAAa,GAAI,MAAQ;WAC3C,oBAAC,gBAAD;EACE,WAAW,GAAG,eAAe,SAAS;EACtC,iBAAiB;EACjB,UAAU,MAAM,WAAW,EAAE,cAAc,eAAe,EAAE;EAC5D,GAAI;CACL;AACO"}
|
|
@@ -1,97 +1,36 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { CodeDefault } from "./CodeBlockClient.mjs";
|
|
4
|
+
import { resolveCodeLanguage } from "./shikiLanguages.mjs";
|
|
4
5
|
import { useEffect, useState } from "react";
|
|
5
6
|
import { jsx } from "react/jsx-runtime";
|
|
6
7
|
|
|
7
8
|
//#region src/components/IDE/CodeBlockShiki.tsx
|
|
8
9
|
const languageCache = /* @__PURE__ */ new Map();
|
|
9
10
|
const themeCache = /* @__PURE__ */ new Map();
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
case "typescript":
|
|
24
|
-
case "ts":
|
|
25
|
-
languageModule = await import("shiki/langs/typescript.mjs");
|
|
26
|
-
break;
|
|
27
|
-
case "javascript":
|
|
28
|
-
case "js":
|
|
29
|
-
case "cjs":
|
|
30
|
-
case "mjs":
|
|
31
|
-
languageModule = await import("shiki/langs/javascript.mjs");
|
|
32
|
-
break;
|
|
33
|
-
case "bash":
|
|
34
|
-
case "sh":
|
|
35
|
-
case "shell":
|
|
36
|
-
languageModule = await import("shiki/langs/bash.mjs");
|
|
37
|
-
break;
|
|
38
|
-
case "json":
|
|
39
|
-
languageModule = await import("shiki/langs/json.mjs");
|
|
40
|
-
break;
|
|
41
|
-
case "jsonc":
|
|
42
|
-
case "json5":
|
|
43
|
-
languageModule = await import("shiki/langs/json5.mjs");
|
|
44
|
-
break;
|
|
45
|
-
case "tsx":
|
|
46
|
-
case "jsx":
|
|
47
|
-
languageModule = await import("shiki/langs/tsx.mjs");
|
|
48
|
-
break;
|
|
49
|
-
case "vue":
|
|
50
|
-
languageModule = await import("shiki/langs/vue.mjs");
|
|
51
|
-
break;
|
|
52
|
-
case "svelte":
|
|
53
|
-
languageModule = await import("shiki/langs/svelte.mjs");
|
|
54
|
-
break;
|
|
55
|
-
case "markdown":
|
|
56
|
-
case "md":
|
|
57
|
-
case "mdx":
|
|
58
|
-
languageModule = await import("shiki/langs/markdown.mjs");
|
|
59
|
-
break;
|
|
60
|
-
case "css":
|
|
61
|
-
languageModule = await import("shiki/langs/css.mjs");
|
|
62
|
-
break;
|
|
63
|
-
case "html":
|
|
64
|
-
languageModule = await import("shiki/langs/html.mjs");
|
|
65
|
-
break;
|
|
66
|
-
case "xml":
|
|
67
|
-
languageModule = await import("shiki/langs/xml.mjs");
|
|
68
|
-
break;
|
|
69
|
-
case "yml":
|
|
70
|
-
case "yaml":
|
|
71
|
-
languageModule = await import("shiki/langs/yaml.mjs");
|
|
72
|
-
break;
|
|
73
|
-
default:
|
|
74
|
-
languageModule = await import("shiki/langs/typescript.mjs");
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
const language = languageModule.default;
|
|
78
|
-
languageCache.set(lang, language);
|
|
79
|
-
return language;
|
|
11
|
+
/**
|
|
12
|
+
* Lazy load the grammar of an already resolved language.
|
|
13
|
+
*
|
|
14
|
+
* @returns The grammar registrations, or `null` for languages Shiki renders
|
|
15
|
+
* without a grammar (plain text).
|
|
16
|
+
*/
|
|
17
|
+
const loadLanguage = async ({ id, loadGrammar }) => {
|
|
18
|
+
if (!loadGrammar) return null;
|
|
19
|
+
const cachedLanguage = languageCache.get(id);
|
|
20
|
+
if (cachedLanguage) return cachedLanguage;
|
|
21
|
+
const languagePromise = loadGrammar().then((module) => module.default);
|
|
22
|
+
languageCache.set(id, languagePromise);
|
|
23
|
+
return languagePromise;
|
|
80
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* Lazy load a theme module.
|
|
27
|
+
*/
|
|
81
28
|
const loadTheme = async (themeName) => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
break;
|
|
88
|
-
default:
|
|
89
|
-
themeModule = await import("shiki/themes/github-light.mjs");
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
const theme = themeModule.default;
|
|
93
|
-
themeCache.set(themeName, theme);
|
|
94
|
-
return theme;
|
|
29
|
+
const cachedTheme = themeCache.get(themeName);
|
|
30
|
+
if (cachedTheme) return cachedTheme;
|
|
31
|
+
const themePromise = (themeName === "github-dark" ? import("shiki/themes/github-dark.mjs") : import("shiki/themes/github-light.mjs")).then((module) => module.default);
|
|
32
|
+
themeCache.set(themeName, themePromise);
|
|
33
|
+
return themePromise;
|
|
95
34
|
};
|
|
96
35
|
let highlighterPromise = null;
|
|
97
36
|
const getHighlighterInstance = async () => {
|
|
@@ -101,17 +40,24 @@ const getHighlighterInstance = async () => {
|
|
|
101
40
|
}));
|
|
102
41
|
return highlighterPromise;
|
|
103
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* Highlight a snippet, lazily loading only the grammar and theme it needs.
|
|
45
|
+
*
|
|
46
|
+
* The language is resolved to a canonical Shiki id first, so that the id passed
|
|
47
|
+
* to `codeToHtml` always matches the grammar that was loaded.
|
|
48
|
+
*/
|
|
104
49
|
const highlightCode = async (code, lang, isDarkMode) => {
|
|
105
50
|
const themeName = isDarkMode ? "github-dark" : "github-light";
|
|
51
|
+
const resolvedLanguage = resolveCodeLanguage(lang);
|
|
106
52
|
const [highlighter, languageModule, themeModule] = await Promise.all([
|
|
107
53
|
getHighlighterInstance(),
|
|
108
|
-
loadLanguage(
|
|
54
|
+
loadLanguage(resolvedLanguage),
|
|
109
55
|
loadTheme(themeName)
|
|
110
56
|
]);
|
|
111
|
-
if (!highlighter.getLoadedLanguages().includes(
|
|
57
|
+
if (languageModule && !highlighter.getLoadedLanguages().includes(resolvedLanguage.id)) await highlighter.loadLanguage(languageModule);
|
|
112
58
|
if (!highlighter.getLoadedThemes().includes(themeName)) await highlighter.loadTheme(themeModule);
|
|
113
59
|
return highlighter.codeToHtml(String(code), {
|
|
114
|
-
lang,
|
|
60
|
+
lang: resolvedLanguage.id,
|
|
115
61
|
theme: themeName
|
|
116
62
|
});
|
|
117
63
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeBlockShiki.mjs","names":[],"sources":["../../../../src/components/IDE/CodeBlockShiki.tsx"],"sourcesContent":["'use client';\n\nimport { type FC, type ReactNode, useEffect, useState } from 'react';\nimport type {
|
|
1
|
+
{"version":3,"file":"CodeBlockShiki.mjs","names":[],"sources":["../../../../src/components/IDE/CodeBlockShiki.tsx"],"sourcesContent":["'use client';\n\nimport { type FC, type ReactNode, useEffect, useState } from 'react';\nimport type { BundledTheme } from 'shiki/bundle/web';\nimport { CodeDefault } from './CodeBlockClient';\nimport {\n type CodeLanguage,\n type LanguageGrammar,\n type ResolvedCodeLanguage,\n resolveCodeLanguage,\n} from './shikiLanguages';\n\n/** Theme registration, as default-exported by the `shiki/themes/*` modules. */\ntype ThemeRegistration =\n typeof import('shiki/themes/github-dark.mjs')['default'];\n\n/** Minimal Shiki highlighter surface used here, with unrestricted language ids. */\ntype CodeHighlighter = {\n getLoadedLanguages(): string[];\n getLoadedThemes(): string[];\n loadLanguage(grammar: LanguageGrammar): Promise<void>;\n loadTheme(theme: ThemeRegistration): Promise<void>;\n codeToHtml(code: string, options: { lang: string; theme: string }): string;\n};\n\n// Map of in-flight/loaded modules to avoid re-importing\nconst languageCache = new Map<string, Promise<LanguageGrammar>>();\nconst themeCache = new Map<BundledTheme, Promise<ThemeRegistration>>();\n\n/**\n * Lazy load the grammar of an already resolved language.\n *\n * @returns The grammar registrations, or `null` for languages Shiki renders\n * without a grammar (plain text).\n */\nconst loadLanguage = async ({\n id,\n loadGrammar,\n}: ResolvedCodeLanguage): Promise<LanguageGrammar | null> => {\n if (!loadGrammar) return null;\n\n const cachedLanguage = languageCache.get(id);\n if (cachedLanguage) return cachedLanguage;\n\n const languagePromise = loadGrammar().then((module) => module.default);\n languageCache.set(id, languagePromise);\n\n return languagePromise;\n};\n\n/**\n * Lazy load a theme module.\n */\nconst loadTheme = async (\n themeName: BundledTheme\n): Promise<ThemeRegistration> => {\n const cachedTheme = themeCache.get(themeName);\n if (cachedTheme) return cachedTheme;\n\n const themePromise = (\n themeName === 'github-dark'\n ? import('shiki/themes/github-dark.mjs')\n : import('shiki/themes/github-light.mjs')\n ).then((module) => module.default);\n\n themeCache.set(themeName, themePromise);\n\n return themePromise;\n};\n\n// Singleton Highlighter Instance\nlet highlighterPromise: Promise<CodeHighlighter> | null = null;\n\nconst getHighlighterInstance = async () => {\n if (!highlighterPromise) {\n highlighterPromise = import('shiki/bundle/web').then(\n ({ createHighlighter }) =>\n createHighlighter({\n langs: [],\n themes: [],\n })\n );\n }\n return highlighterPromise;\n};\n\n/**\n * Highlight a snippet, lazily loading only the grammar and theme it needs.\n *\n * The language is resolved to a canonical Shiki id first, so that the id passed\n * to `codeToHtml` always matches the grammar that was loaded.\n */\nconst highlightCode = async (\n code: ReactNode,\n lang: CodeLanguage,\n isDarkMode?: boolean\n): Promise<string> => {\n const themeName: BundledTheme = isDarkMode ? 'github-dark' : 'github-light';\n const resolvedLanguage = resolveCodeLanguage(lang);\n\n // Load highlighter, language, and theme in parallel\n const [highlighter, languageModule, themeModule] = await Promise.all([\n getHighlighterInstance(),\n loadLanguage(resolvedLanguage),\n loadTheme(themeName),\n ]);\n\n // Load into the singleton instance if not already loaded\n if (\n languageModule &&\n !highlighter.getLoadedLanguages().includes(resolvedLanguage.id)\n ) {\n await highlighter.loadLanguage(languageModule);\n }\n if (!highlighter.getLoadedThemes().includes(themeName)) {\n await highlighter.loadTheme(themeModule);\n }\n\n return highlighter.codeToHtml(String(code), {\n lang: resolvedLanguage.id,\n theme: themeName,\n });\n};\n\nexport type CodeBlockShikiProps = {\n children: ReactNode;\n lang: CodeLanguage;\n isDarkMode?: boolean;\n};\n\nexport const CodeBlockShiki: FC<CodeBlockShikiProps> = ({\n children,\n lang,\n isDarkMode,\n}) => {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let isCancelled = false;\n\n highlightCode(children, lang, isDarkMode)\n .then((result) => {\n if (!isCancelled) setHtml(result);\n })\n .catch((error) => {\n console.error('Failed to highlight code:', error);\n if (!isCancelled && html === null) setHtml('');\n });\n\n return () => {\n isCancelled = true;\n };\n }, [children, lang, isDarkMode]);\n\n return (\n <div className=\"[&_pre.shiki]:!bg-transparent min-w-0 max-w-full overflow-auto bg-transparent [-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden [&_pre.shiki]:max-w-full [&_pre.shiki]:overflow-x-auto [&_pre::-webkit-scrollbar]:hidden [&_pre]:[-ms-overflow-style:none] [&_pre]:[scrollbar-width:none]\">\n {html ? (\n // biome-ignore lint/security/noDangerouslySetInnerHtml: Shiki generates safe HTML for code highlighting\n <div dangerouslySetInnerHTML={{ __html: html }} />\n ) : (\n <CodeDefault>{children}</CodeDefault>\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;AA0BA,MAAM,gCAAgB,IAAI,IAAsC;AAChE,MAAM,6BAAa,IAAI,IAA8C;;;;;;;AAQrE,MAAM,eAAe,OAAO,EAC1B,IACA,kBAC2D;CAC3D,IAAI,CAAC,aAAa,OAAO;CAEzB,MAAM,iBAAiB,cAAc,IAAI,EAAE;CAC3C,IAAI,gBAAgB,OAAO;CAE3B,MAAM,kBAAkB,YAAY,CAAC,CAAC,MAAM,WAAW,OAAO,OAAO;CACrE,cAAc,IAAI,IAAI,eAAe;CAErC,OAAO;AACT;;;;AAKA,MAAM,YAAY,OAChB,cAC+B;CAC/B,MAAM,cAAc,WAAW,IAAI,SAAS;CAC5C,IAAI,aAAa,OAAO;CAExB,MAAM,gBACJ,cAAc,gBACV,OAAO,kCACP,OAAO,iCAAgC,CAC3C,MAAM,WAAW,OAAO,OAAO;CAEjC,WAAW,IAAI,WAAW,YAAY;CAEtC,OAAO;AACT;AAGA,IAAI,qBAAsD;AAE1D,MAAM,yBAAyB,YAAY;CACzC,IAAI,CAAC,oBACH,qBAAqB,OAAO,mBAAmB,CAAC,MAC7C,EAAE,wBACD,kBAAkB;EAChB,OAAO,CAAC;EACR,QAAQ,CAAC;CACX,CAAC,CACL;CAEF,OAAO;AACT;;;;;;;AAQA,MAAM,gBAAgB,OACpB,MACA,MACA,eACoB;CACpB,MAAM,YAA0B,aAAa,gBAAgB;CAC7D,MAAM,mBAAmB,oBAAoB,IAAI;CAGjD,MAAM,CAAC,aAAa,gBAAgB,eAAe,MAAM,QAAQ,IAAI;EACnE,uBAAuB;EACvB,aAAa,gBAAgB;EAC7B,UAAU,SAAS;CACrB,CAAC;CAGD,IACE,kBACA,CAAC,YAAY,mBAAmB,CAAC,CAAC,SAAS,iBAAiB,EAAE,GAE9D,MAAM,YAAY,aAAa,cAAc;CAE/C,IAAI,CAAC,YAAY,gBAAgB,CAAC,CAAC,SAAS,SAAS,GACnD,MAAM,YAAY,UAAU,WAAW;CAGzC,OAAO,YAAY,WAAW,OAAO,IAAI,GAAG;EAC1C,MAAM,iBAAiB;EACvB,OAAO;CACT,CAAC;AACH;AAQA,MAAa,kBAA2C,EACtD,UACA,MACA,iBACI;CACJ,MAAM,CAAC,MAAM,WAAW,SAAwB,IAAI;CAEpD,gBAAgB;EACd,IAAI,cAAc;EAElB,cAAc,UAAU,MAAM,UAAU,CAAC,CACtC,MAAM,WAAW;GAChB,IAAI,CAAC,aAAa,QAAQ,MAAM;EAClC,CAAC,CAAC,CACD,OAAO,UAAU;GAChB,QAAQ,MAAM,6BAA6B,KAAK;GAChD,IAAI,CAAC,eAAe,SAAS,MAAM,QAAQ,EAAE;EAC/C,CAAC;EAEH,aAAa;GACX,cAAc;EAChB;CACF,GAAG;EAAC;EAAU;EAAM;CAAU,CAAC;CAE/B,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,OAEC,oBAAC,OAAD,EAAK,yBAAyB,EAAE,QAAQ,KAAK,EAAI,KAEjD,oBAAC,aAAD,EAAc,SAAsB;CAEnC;AAET"}
|
|
@@ -4,8 +4,8 @@ import { cn } from "../../utils/cn.mjs";
|
|
|
4
4
|
import { MaxHeightSmoother } from "../MaxHeightSmoother/index.mjs";
|
|
5
5
|
import { createFileTree } from "./createFileTree.mjs";
|
|
6
6
|
import { useState } from "react";
|
|
7
|
-
import { ChevronRight } from "lucide-react";
|
|
8
7
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
8
|
+
import { ChevronRight } from "lucide-react";
|
|
9
9
|
|
|
10
10
|
//#region src/components/IDE/FileTree.tsx
|
|
11
11
|
const concatFilePath = (paths) => paths.join("/");
|
|
@@ -46,9 +46,10 @@ const FileItem = ({ filesPaths, path, subPath, onClickFile, activeFile, prePaths
|
|
|
46
46
|
})] });
|
|
47
47
|
};
|
|
48
48
|
const FileTree = ({ filesPaths, activeFile, onClickFile, prePaths = [] }) => {
|
|
49
|
+
const fileTree = createFileTree(filesPaths);
|
|
49
50
|
return /* @__PURE__ */ jsx("div", {
|
|
50
51
|
className: "flex size-full flex-col items-start justify-start py-1 text-neutral",
|
|
51
|
-
children:
|
|
52
|
+
children: fileTree.map(({ path, subPath, isFile }) => /* @__PURE__ */ jsx(FileItem, {
|
|
52
53
|
isFile,
|
|
53
54
|
subPath,
|
|
54
55
|
path,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileTree.mjs","names":[],"sources":["../../../../src/components/IDE/FileTree.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { ChevronRight } from 'lucide-react';\nimport { type FC, useState } from 'react';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\nimport { createFileTree, type FilePath } from './createFileTree';\n\ntype FileTreeProps = {\n filesPaths: string[];\n activeFile?: string;\n onClickFile?: (filePath: string) => void;\n prePaths?: string[];\n};\n\nconst concatFilePath = (paths: string[]) => paths.join('/');\n\ntype FileItemProps = {\n filesPaths: string[];\n subPath?: FilePath[];\n path: string;\n onClickFile?: (title: string) => void;\n activeFile?: string;\n prePaths: string[];\n isFile: boolean;\n};\n\nconst FileItem: FC<FileItemProps> = ({\n filesPaths,\n path,\n subPath,\n onClickFile,\n activeFile,\n prePaths,\n isFile,\n}) => {\n const [subPathOpen, setSubPathOpen] = useState(true);\n\n const level = prePaths.length + 1;\n const currentPath = concatFilePath([\n ...prePaths.slice(level - 1, level),\n path,\n ]);\n const totalPath = concatFilePath([...prePaths, path]);\n\n const filteredFilePaths = filesPaths\n .map(\n (path) => path.replace(/^\\/?/, '') // This regex matches the first slash, if it exists, at the start of the string)\n )\n .filter((filePath) => filePath.startsWith(currentPath));\n\n const newPath = filteredFilePaths.map((path) =>\n path.replace(currentPath, '').replace(/^\\/?/, '')\n );\n\n const isActive = totalPath === activeFile;\n\n const indentation = new Array(level).fill(' ').join('');\n\n return (\n <>\n <button\n className={cn(\n 'flex w-full items-start justify-start whitespace-pre text-nowrap px-2 py-1 text-xs transition',\n isActive\n ? 'bg-neutral-200 dark:bg-neutral-800'\n : 'cursor-pointer hover:bg-neutral-300 dark:hover:bg-neutral-900'\n )}\n key={path}\n onClick={() => {\n if (isFile) {\n onClickFile?.(totalPath);\n } else {\n setSubPathOpen(!subPathOpen);\n }\n }}\n >\n <span className={cn('whitespace-pre', isFile && 'ml-2')}>\n {indentation}\n </span>\n\n {!isFile && (\n <ChevronRight\n className={cn(`transition`, subPathOpen && `rotate-90 transform`)}\n size={16}\n />\n )}\n {path}\n </button>\n {subPath && (\n <MaxHeightSmoother\n isHidden={!subPathOpen}\n className=\"overflow-x-hidden\"\n >\n <FileTree\n filesPaths={newPath}\n activeFile={activeFile}\n onClickFile={onClickFile}\n prePaths={[...prePaths, path]}\n />\n </MaxHeightSmoother>\n )}\n </>\n );\n};\n\nexport const FileTree: FC<FileTreeProps> = ({\n filesPaths,\n activeFile,\n onClickFile,\n prePaths = [],\n}) => {\n const fileTree = createFileTree(filesPaths);\n\n return (\n <div className=\"flex size-full flex-col items-start justify-start py-1 text-neutral\">\n {fileTree.map(({ path, subPath, isFile }) => (\n <FileItem\n key={path}\n isFile={isFile}\n subPath={subPath}\n path={path}\n onClickFile={onClickFile}\n activeFile={activeFile}\n prePaths={prePaths}\n filesPaths={filesPaths}\n />\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAeA,MAAM,kBAAkB,UAAoB,MAAM,KAAK,GAAG;AAY1D,MAAM,YAA+B,EACnC,YACA,MACA,SACA,aACA,YACA,UACA,aACI;CACJ,MAAM,CAAC,aAAa,kBAAkB,SAAS,IAAI;CAEnD,MAAM,QAAQ,SAAS,SAAS;CAChC,MAAM,cAAc,eAAe,CACjC,GAAG,SAAS,MAAM,QAAQ,GAAG,KAAK,GAClC,IACF,CAAC;CACD,MAAM,YAAY,eAAe,CAAC,GAAG,UAAU,IAAI,CAAC;CAQpD,MAAM,UANoB,WACvB,KACE,SAAS,KAAK,QAAQ,QAAQ,EAAE,CACnC,CAAC,CACA,QAAQ,aAAa,SAAS,WAAW,WAAW,CAEvB,CAAC,CAAC,KAAK,SACrC,KAAK,QAAQ,aAAa,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE,CAClD;CAEA,MAAM,WAAW,cAAc;CAE/B,MAAM,cAAc,IAAI,MAAM,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE;CAEvD,OACE,8CACE,qBAAC,UAAD;EACE,WAAW,GACT,iGACA,WACI,uCACA,+DACN;EAEA,eAAe;GACb,IAAI,QACF,cAAc,SAAS;QAEvB,eAAe,CAAC,WAAW;EAE/B;YAdF;GAgBE,oBAAC,QAAD;IAAM,WAAW,GAAG,kBAAkB,UAAU,MAAM;cACnD;GACG;GAEL,CAAC,UACA,oBAAC,cAAD;IACE,WAAW,GAAG,cAAc,eAAe,qBAAqB;IAChE,MAAM;GACP;GAEF;EACK;IApBD,IAoBC,GACP,WACC,oBAAC,mBAAD;EACE,UAAU,CAAC;EACX,WAAU;YAEV,oBAAC,UAAD;GACE,YAAY;GACA;GACC;GACb,UAAU,CAAC,GAAG,UAAU,IAAI;EAC7B;CACgB,EAErB;AAEN;AAEA,MAAa,YAA+B,EAC1C,YACA,YACA,aACA,WAAW,CAAC,QACR;
|
|
1
|
+
{"version":3,"file":"FileTree.mjs","names":[],"sources":["../../../../src/components/IDE/FileTree.tsx"],"sourcesContent":["'use client';\n\nimport { cn } from '@utils/cn';\nimport { ChevronRight } from 'lucide-react';\nimport { type FC, useState } from 'react';\nimport { MaxHeightSmoother } from '../MaxHeightSmoother';\nimport { createFileTree, type FilePath } from './createFileTree';\n\ntype FileTreeProps = {\n filesPaths: string[];\n activeFile?: string;\n onClickFile?: (filePath: string) => void;\n prePaths?: string[];\n};\n\nconst concatFilePath = (paths: string[]) => paths.join('/');\n\ntype FileItemProps = {\n filesPaths: string[];\n subPath?: FilePath[];\n path: string;\n onClickFile?: (title: string) => void;\n activeFile?: string;\n prePaths: string[];\n isFile: boolean;\n};\n\nconst FileItem: FC<FileItemProps> = ({\n filesPaths,\n path,\n subPath,\n onClickFile,\n activeFile,\n prePaths,\n isFile,\n}) => {\n const [subPathOpen, setSubPathOpen] = useState(true);\n\n const level = prePaths.length + 1;\n const currentPath = concatFilePath([\n ...prePaths.slice(level - 1, level),\n path,\n ]);\n const totalPath = concatFilePath([...prePaths, path]);\n\n const filteredFilePaths = filesPaths\n .map(\n (path) => path.replace(/^\\/?/, '') // This regex matches the first slash, if it exists, at the start of the string)\n )\n .filter((filePath) => filePath.startsWith(currentPath));\n\n const newPath = filteredFilePaths.map((path) =>\n path.replace(currentPath, '').replace(/^\\/?/, '')\n );\n\n const isActive = totalPath === activeFile;\n\n const indentation = new Array(level).fill(' ').join('');\n\n return (\n <>\n <button\n className={cn(\n 'flex w-full items-start justify-start whitespace-pre text-nowrap px-2 py-1 text-xs transition',\n isActive\n ? 'bg-neutral-200 dark:bg-neutral-800'\n : 'cursor-pointer hover:bg-neutral-300 dark:hover:bg-neutral-900'\n )}\n key={path}\n onClick={() => {\n if (isFile) {\n onClickFile?.(totalPath);\n } else {\n setSubPathOpen(!subPathOpen);\n }\n }}\n >\n <span className={cn('whitespace-pre', isFile && 'ml-2')}>\n {indentation}\n </span>\n\n {!isFile && (\n <ChevronRight\n className={cn(`transition`, subPathOpen && `rotate-90 transform`)}\n size={16}\n />\n )}\n {path}\n </button>\n {subPath && (\n <MaxHeightSmoother\n isHidden={!subPathOpen}\n className=\"overflow-x-hidden\"\n >\n <FileTree\n filesPaths={newPath}\n activeFile={activeFile}\n onClickFile={onClickFile}\n prePaths={[...prePaths, path]}\n />\n </MaxHeightSmoother>\n )}\n </>\n );\n};\n\nexport const FileTree: FC<FileTreeProps> = ({\n filesPaths,\n activeFile,\n onClickFile,\n prePaths = [],\n}) => {\n const fileTree = createFileTree(filesPaths);\n\n return (\n <div className=\"flex size-full flex-col items-start justify-start py-1 text-neutral\">\n {fileTree.map(({ path, subPath, isFile }) => (\n <FileItem\n key={path}\n isFile={isFile}\n subPath={subPath}\n path={path}\n onClickFile={onClickFile}\n activeFile={activeFile}\n prePaths={prePaths}\n filesPaths={filesPaths}\n />\n ))}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;AAeA,MAAM,kBAAkB,UAAoB,MAAM,KAAK,GAAG;AAY1D,MAAM,YAA+B,EACnC,YACA,MACA,SACA,aACA,YACA,UACA,aACI;CACJ,MAAM,CAAC,aAAa,kBAAkB,SAAS,IAAI;CAEnD,MAAM,QAAQ,SAAS,SAAS;CAChC,MAAM,cAAc,eAAe,CACjC,GAAG,SAAS,MAAM,QAAQ,GAAG,KAAK,GAClC,IACF,CAAC;CACD,MAAM,YAAY,eAAe,CAAC,GAAG,UAAU,IAAI,CAAC;CAQpD,MAAM,UANoB,WACvB,KACE,SAAS,KAAK,QAAQ,QAAQ,EAAE,CACnC,CAAC,CACA,QAAQ,aAAa,SAAS,WAAW,WAAW,CAEvB,CAAC,CAAC,KAAK,SACrC,KAAK,QAAQ,aAAa,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE,CAClD;CAEA,MAAM,WAAW,cAAc;CAE/B,MAAM,cAAc,IAAI,MAAM,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,EAAE;CAEvD,OACE,8CACE,qBAAC,UAAD;EACE,WAAW,GACT,iGACA,WACI,uCACA,+DACN;EAEA,eAAe;GACb,IAAI,QACF,cAAc,SAAS;QAEvB,eAAe,CAAC,WAAW;EAE/B;YAdF;GAgBE,oBAAC,QAAD;IAAM,WAAW,GAAG,kBAAkB,UAAU,MAAM;cACnD;GACG;GAEL,CAAC,UACA,oBAAC,cAAD;IACE,WAAW,GAAG,cAAc,eAAe,qBAAqB;IAChE,MAAM;GACP;GAEF;EACK;IApBD,IAoBC,GACP,WACC,oBAAC,mBAAD;EACE,UAAU,CAAC;EACX,WAAU;YAEV,oBAAC,UAAD;GACE,YAAY;GACA;GACC;GACb,UAAU,CAAC,GAAG,UAAU,IAAI;EAC7B;CACgB,EAErB;AAEN;AAEA,MAAa,YAA+B,EAC1C,YACA,YACA,aACA,WAAW,CAAC,QACR;CACJ,MAAM,WAAW,eAAe,UAAU;CAE1C,OACE,oBAAC,OAAD;EAAK,WAAU;YACZ,SAAS,KAAK,EAAE,MAAM,SAAS,aAC9B,oBAAC,UAAD;GAEU;GACC;GACH;GACO;GACD;GACF;GACE;EACb,GARM,IAQN,CACF;CACE;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MarkDownRender.mjs","names":["MarkdownRendererIntlayer"],"sources":["../../../../src/components/IDE/MarkDownRender.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { MarkdownRenderer as MarkdownRendererIntlayer } from 'react-intlayer';\nimport
|
|
1
|
+
{"version":3,"file":"MarkDownRender.mjs","names":["MarkdownRendererIntlayer"],"sources":["../../../../src/components/IDE/MarkDownRender.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { MarkdownRenderer as MarkdownRendererIntlayer } from 'react-intlayer';\nimport { Code } from './Code';\nimport type { CodeLanguage } from './shikiLanguages';\n\ntype MarkdownRendererProps = {\n isDarkMode?: boolean;\n children: string;\n};\n\nexport const MarkdownRenderer: FC<MarkdownRendererProps> = ({\n children,\n isDarkMode,\n}) => (\n <MarkdownRendererIntlayer\n components={{\n code: (props) => (\n <Code\n {...props}\n isDarkMode={isDarkMode}\n language={props.className?.replace('lang-', '') as CodeLanguage}\n showHeader={false}\n className=\"text-xs leading-5\"\n >\n {props.children as string}\n </Code>\n ),\n pre: (props) => props.children,\n }}\n >\n {children ?? ''}\n </MarkdownRendererIntlayer>\n);\n"],"mappings":";;;;;AAUA,MAAa,oBAA+C,EAC1D,UACA,iBAEA,oBAACA,oBAAD;CACE,YAAY;EACV,OAAO,UACL,oBAAC,MAAD;GACE,GAAI;GACQ;GACZ,UAAU,MAAM,WAAW,QAAQ,SAAS,EAAE;GAC9C,YAAY;GACZ,WAAU;aAET,MAAM;EACH;EAER,MAAM,UAAU,MAAM;CACxB;WAEC,YAAY;AACW"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
//#region src/components/IDE/shikiLanguages.ts
|
|
2
|
+
/**
|
|
3
|
+
* Shiki grammar loaders, keyed by the canonical Shiki language id.
|
|
4
|
+
*
|
|
5
|
+
* Import specifiers are written as literals (never template strings) so that
|
|
6
|
+
* bundlers can statically analyse them and emit one lazily fetched chunk per
|
|
7
|
+
* grammar instead of bundling every language up front.
|
|
8
|
+
*/
|
|
9
|
+
const grammarLoaders = {
|
|
10
|
+
"angular-html": () => import("shiki/langs/angular-html.mjs"),
|
|
11
|
+
"angular-ts": () => import("shiki/langs/angular-ts.mjs"),
|
|
12
|
+
astro: () => import("shiki/langs/astro.mjs"),
|
|
13
|
+
bash: () => import("shiki/langs/bash.mjs"),
|
|
14
|
+
c: () => import("shiki/langs/c.mjs"),
|
|
15
|
+
cpp: () => import("shiki/langs/cpp.mjs"),
|
|
16
|
+
csharp: () => import("shiki/langs/csharp.mjs"),
|
|
17
|
+
css: () => import("shiki/langs/css.mjs"),
|
|
18
|
+
csv: () => import("shiki/langs/csv.mjs"),
|
|
19
|
+
dart: () => import("shiki/langs/dart.mjs"),
|
|
20
|
+
diff: () => import("shiki/langs/diff.mjs"),
|
|
21
|
+
docker: () => import("shiki/langs/docker.mjs"),
|
|
22
|
+
go: () => import("shiki/langs/go.mjs"),
|
|
23
|
+
graphql: () => import("shiki/langs/graphql.mjs"),
|
|
24
|
+
html: () => import("shiki/langs/html.mjs"),
|
|
25
|
+
http: () => import("shiki/langs/http.mjs"),
|
|
26
|
+
ini: () => import("shiki/langs/ini.mjs"),
|
|
27
|
+
java: () => import("shiki/langs/java.mjs"),
|
|
28
|
+
javascript: () => import("shiki/langs/javascript.mjs"),
|
|
29
|
+
json: () => import("shiki/langs/json.mjs"),
|
|
30
|
+
json5: () => import("shiki/langs/json5.mjs"),
|
|
31
|
+
kotlin: () => import("shiki/langs/kotlin.mjs"),
|
|
32
|
+
less: () => import("shiki/langs/less.mjs"),
|
|
33
|
+
lua: () => import("shiki/langs/lua.mjs"),
|
|
34
|
+
markdown: () => import("shiki/langs/markdown.mjs"),
|
|
35
|
+
nginx: () => import("shiki/langs/nginx.mjs"),
|
|
36
|
+
php: () => import("shiki/langs/php.mjs"),
|
|
37
|
+
powershell: () => import("shiki/langs/powershell.mjs"),
|
|
38
|
+
prisma: () => import("shiki/langs/prisma.mjs"),
|
|
39
|
+
python: () => import("shiki/langs/python.mjs"),
|
|
40
|
+
ruby: () => import("shiki/langs/ruby.mjs"),
|
|
41
|
+
rust: () => import("shiki/langs/rust.mjs"),
|
|
42
|
+
scss: () => import("shiki/langs/scss.mjs"),
|
|
43
|
+
sql: () => import("shiki/langs/sql.mjs"),
|
|
44
|
+
svelte: () => import("shiki/langs/svelte.mjs"),
|
|
45
|
+
swift: () => import("shiki/langs/swift.mjs"),
|
|
46
|
+
toml: () => import("shiki/langs/toml.mjs"),
|
|
47
|
+
tsx: () => import("shiki/langs/tsx.mjs"),
|
|
48
|
+
typescript: () => import("shiki/langs/typescript.mjs"),
|
|
49
|
+
vue: () => import("shiki/langs/vue.mjs"),
|
|
50
|
+
xml: () => import("shiki/langs/xml.mjs"),
|
|
51
|
+
yaml: () => import("shiki/langs/yaml.mjs")
|
|
52
|
+
};
|
|
53
|
+
/** Every canonical language id that ships with a grammar loader. */
|
|
54
|
+
const shikiLanguageIds = Object.keys(grammarLoaders);
|
|
55
|
+
/**
|
|
56
|
+
* Code fence names that are rendered by another grammar, mapped to the
|
|
57
|
+
* canonical id that actually owns the grammar.
|
|
58
|
+
*/
|
|
59
|
+
const grammarAliases = {
|
|
60
|
+
"c#": "csharp",
|
|
61
|
+
"c++": "cpp",
|
|
62
|
+
cjs: "javascript",
|
|
63
|
+
console: "bash",
|
|
64
|
+
cs: "csharp",
|
|
65
|
+
cts: "typescript",
|
|
66
|
+
dockerfile: "docker",
|
|
67
|
+
golang: "go",
|
|
68
|
+
gql: "graphql",
|
|
69
|
+
htm: "html",
|
|
70
|
+
js: "javascript",
|
|
71
|
+
jsonc: "json5",
|
|
72
|
+
jsx: "tsx",
|
|
73
|
+
kt: "kotlin",
|
|
74
|
+
md: "markdown",
|
|
75
|
+
mdx: "markdown",
|
|
76
|
+
mjs: "javascript",
|
|
77
|
+
mts: "typescript",
|
|
78
|
+
postcss: "css",
|
|
79
|
+
ps1: "powershell",
|
|
80
|
+
pwsh: "powershell",
|
|
81
|
+
py: "python",
|
|
82
|
+
rb: "ruby",
|
|
83
|
+
rs: "rust",
|
|
84
|
+
sh: "bash",
|
|
85
|
+
shell: "bash",
|
|
86
|
+
shellscript: "bash",
|
|
87
|
+
ts: "typescript",
|
|
88
|
+
yml: "yaml",
|
|
89
|
+
zsh: "bash"
|
|
90
|
+
};
|
|
91
|
+
const PLAIN_TEXT_LANGUAGE = "plaintext";
|
|
92
|
+
/**
|
|
93
|
+
* Resolve a code fence language name to a canonical Shiki id and its grammar
|
|
94
|
+
* loader.
|
|
95
|
+
*
|
|
96
|
+
* Unknown names resolve to plain text rather than to an arbitrary grammar, so
|
|
97
|
+
* that `codeToHtml` never receives a language it has not loaded.
|
|
98
|
+
*
|
|
99
|
+
* @param language - Language name coming from a code fence or a `lang` prop.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* resolveCodeLanguage('ts'); // { id: 'typescript', loadGrammar: fn }
|
|
103
|
+
* resolveCodeLanguage('toml'); // { id: 'toml', loadGrammar: fn }
|
|
104
|
+
* resolveCodeLanguage('brainfuck'); // { id: 'plaintext', loadGrammar: null }
|
|
105
|
+
*/
|
|
106
|
+
const resolveCodeLanguage = (language) => {
|
|
107
|
+
const normalizedLanguage = (language ?? "").trim().toLowerCase();
|
|
108
|
+
const canonicalId = grammarAliases[normalizedLanguage] ?? normalizedLanguage;
|
|
109
|
+
const loadGrammar = grammarLoaders[canonicalId];
|
|
110
|
+
if (!loadGrammar) return {
|
|
111
|
+
id: PLAIN_TEXT_LANGUAGE,
|
|
112
|
+
loadGrammar: null
|
|
113
|
+
};
|
|
114
|
+
return {
|
|
115
|
+
id: canonicalId,
|
|
116
|
+
loadGrammar
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
//#endregion
|
|
121
|
+
export { resolveCodeLanguage, shikiLanguageIds };
|
|
122
|
+
//# sourceMappingURL=shikiLanguages.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shikiLanguages.mjs","names":[],"sources":["../../../../src/components/IDE/shikiLanguages.ts"],"sourcesContent":["/**\n * Grammar registrations, as default-exported by the `shiki/langs/*` modules.\n */\nexport type LanguageGrammar =\n typeof import('shiki/langs/typescript.mjs')['default'];\n\n/**\n * Loads a single Shiki grammar (and its embedded dependencies).\n */\nexport type GrammarLoader = () => Promise<{ default: LanguageGrammar }>;\n\n/**\n * Shiki grammar loaders, keyed by the canonical Shiki language id.\n *\n * Import specifiers are written as literals (never template strings) so that\n * bundlers can statically analyse them and emit one lazily fetched chunk per\n * grammar instead of bundling every language up front.\n */\nconst grammarLoaders = {\n 'angular-html': () => import('shiki/langs/angular-html.mjs'),\n 'angular-ts': () => import('shiki/langs/angular-ts.mjs'),\n astro: () => import('shiki/langs/astro.mjs'),\n bash: () => import('shiki/langs/bash.mjs'),\n c: () => import('shiki/langs/c.mjs'),\n cpp: () => import('shiki/langs/cpp.mjs'),\n csharp: () => import('shiki/langs/csharp.mjs'),\n css: () => import('shiki/langs/css.mjs'),\n csv: () => import('shiki/langs/csv.mjs'),\n dart: () => import('shiki/langs/dart.mjs'),\n diff: () => import('shiki/langs/diff.mjs'),\n docker: () => import('shiki/langs/docker.mjs'),\n go: () => import('shiki/langs/go.mjs'),\n graphql: () => import('shiki/langs/graphql.mjs'),\n html: () => import('shiki/langs/html.mjs'),\n http: () => import('shiki/langs/http.mjs'),\n ini: () => import('shiki/langs/ini.mjs'),\n java: () => import('shiki/langs/java.mjs'),\n javascript: () => import('shiki/langs/javascript.mjs'),\n json: () => import('shiki/langs/json.mjs'),\n json5: () => import('shiki/langs/json5.mjs'),\n kotlin: () => import('shiki/langs/kotlin.mjs'),\n less: () => import('shiki/langs/less.mjs'),\n lua: () => import('shiki/langs/lua.mjs'),\n markdown: () => import('shiki/langs/markdown.mjs'),\n nginx: () => import('shiki/langs/nginx.mjs'),\n php: () => import('shiki/langs/php.mjs'),\n powershell: () => import('shiki/langs/powershell.mjs'),\n prisma: () => import('shiki/langs/prisma.mjs'),\n python: () => import('shiki/langs/python.mjs'),\n ruby: () => import('shiki/langs/ruby.mjs'),\n rust: () => import('shiki/langs/rust.mjs'),\n scss: () => import('shiki/langs/scss.mjs'),\n sql: () => import('shiki/langs/sql.mjs'),\n svelte: () => import('shiki/langs/svelte.mjs'),\n swift: () => import('shiki/langs/swift.mjs'),\n toml: () => import('shiki/langs/toml.mjs'),\n tsx: () => import('shiki/langs/tsx.mjs'),\n typescript: () => import('shiki/langs/typescript.mjs'),\n vue: () => import('shiki/langs/vue.mjs'),\n xml: () => import('shiki/langs/xml.mjs'),\n yaml: () => import('shiki/langs/yaml.mjs'),\n} satisfies Record<string, GrammarLoader>;\n\n/** Canonical Shiki language ids this package can highlight. */\nexport type ShikiLanguageId = keyof typeof grammarLoaders;\n\n/** Every canonical language id that ships with a grammar loader. */\nexport const shikiLanguageIds = Object.keys(\n grammarLoaders\n) as ShikiLanguageId[];\n\n/**\n * Code fence names that are rendered by another grammar, mapped to the\n * canonical id that actually owns the grammar.\n */\nconst grammarAliases = {\n 'c#': 'csharp',\n 'c++': 'cpp',\n cjs: 'javascript',\n console: 'bash',\n cs: 'csharp',\n cts: 'typescript',\n dockerfile: 'docker',\n golang: 'go',\n gql: 'graphql',\n htm: 'html',\n js: 'javascript',\n jsonc: 'json5',\n jsx: 'tsx',\n kt: 'kotlin',\n md: 'markdown',\n mdx: 'markdown',\n mjs: 'javascript',\n mts: 'typescript',\n postcss: 'css',\n ps1: 'powershell',\n pwsh: 'powershell',\n py: 'python',\n rb: 'ruby',\n rs: 'rust',\n sh: 'bash',\n shell: 'bash',\n shellscript: 'bash',\n ts: 'typescript',\n yml: 'yaml',\n zsh: 'bash',\n} satisfies Record<string, ShikiLanguageId>;\n\n/** Code fence names accepted as aliases of a canonical language id. */\nexport type ShikiLanguageAlias = keyof typeof grammarAliases;\n\n/**\n * Languages Shiki renders without any grammar. They are also used as the\n * fallback for languages this package does not ship a grammar for.\n */\nexport type PlainTextLanguage = 'plaintext' | 'text' | 'txt';\n\nconst PLAIN_TEXT_LANGUAGE = 'plaintext' satisfies PlainTextLanguage;\n\n/** Every language name accepted by the code block components. */\nexport type CodeLanguage =\n | ShikiLanguageId\n | ShikiLanguageAlias\n | PlainTextLanguage;\n\n/**\n * A language name resolved to what Shiki actually needs to highlight it.\n */\nexport type ResolvedCodeLanguage = {\n /** Canonical language id to pass to `codeToHtml` / `codeToHast`. */\n id: ShikiLanguageId | PlainTextLanguage;\n /** Grammar loader, or `null` when the language needs no grammar. */\n loadGrammar: GrammarLoader | null;\n};\n\n/**\n * Resolve a code fence language name to a canonical Shiki id and its grammar\n * loader.\n *\n * Unknown names resolve to plain text rather than to an arbitrary grammar, so\n * that `codeToHtml` never receives a language it has not loaded.\n *\n * @param language - Language name coming from a code fence or a `lang` prop.\n *\n * @example\n * resolveCodeLanguage('ts'); // { id: 'typescript', loadGrammar: fn }\n * resolveCodeLanguage('toml'); // { id: 'toml', loadGrammar: fn }\n * resolveCodeLanguage('brainfuck'); // { id: 'plaintext', loadGrammar: null }\n */\nexport const resolveCodeLanguage = (\n language: CodeLanguage | string | undefined | null\n): ResolvedCodeLanguage => {\n const normalizedLanguage = (language ?? '').trim().toLowerCase();\n\n const canonicalId =\n grammarAliases[normalizedLanguage as ShikiLanguageAlias] ??\n (normalizedLanguage as ShikiLanguageId);\n\n const loadGrammar = grammarLoaders[canonicalId] as GrammarLoader | undefined;\n\n if (!loadGrammar) {\n return { id: PLAIN_TEXT_LANGUAGE, loadGrammar: null };\n }\n\n return { id: canonicalId, loadGrammar };\n};\n"],"mappings":";;;;;;;;AAkBA,MAAM,iBAAiB;CACrB,sBAAsB,OAAO;CAC7B,oBAAoB,OAAO;CAC3B,aAAa,OAAO;CACpB,YAAY,OAAO;CACnB,SAAS,OAAO;CAChB,WAAW,OAAO;CAClB,cAAc,OAAO;CACrB,WAAW,OAAO;CAClB,WAAW,OAAO;CAClB,YAAY,OAAO;CACnB,YAAY,OAAO;CACnB,cAAc,OAAO;CACrB,UAAU,OAAO;CACjB,eAAe,OAAO;CACtB,YAAY,OAAO;CACnB,YAAY,OAAO;CACnB,WAAW,OAAO;CAClB,YAAY,OAAO;CACnB,kBAAkB,OAAO;CACzB,YAAY,OAAO;CACnB,aAAa,OAAO;CACpB,cAAc,OAAO;CACrB,YAAY,OAAO;CACnB,WAAW,OAAO;CAClB,gBAAgB,OAAO;CACvB,aAAa,OAAO;CACpB,WAAW,OAAO;CAClB,kBAAkB,OAAO;CACzB,cAAc,OAAO;CACrB,cAAc,OAAO;CACrB,YAAY,OAAO;CACnB,YAAY,OAAO;CACnB,YAAY,OAAO;CACnB,WAAW,OAAO;CAClB,cAAc,OAAO;CACrB,aAAa,OAAO;CACpB,YAAY,OAAO;CACnB,WAAW,OAAO;CAClB,kBAAkB,OAAO;CACzB,WAAW,OAAO;CAClB,WAAW,OAAO;CAClB,YAAY,OAAO;AACrB;;AAMA,MAAa,mBAAmB,OAAO,KACrC,cACF;;;;;AAMA,MAAM,iBAAiB;CACrB,MAAM;CACN,OAAO;CACP,KAAK;CACL,SAAS;CACT,IAAI;CACJ,KAAK;CACL,YAAY;CACZ,QAAQ;CACR,KAAK;CACL,KAAK;CACL,IAAI;CACJ,OAAO;CACP,KAAK;CACL,IAAI;CACJ,IAAI;CACJ,KAAK;CACL,KAAK;CACL,KAAK;CACL,SAAS;CACT,KAAK;CACL,MAAM;CACN,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,aAAa;CACb,IAAI;CACJ,KAAK;CACL,KAAK;AACP;AAWA,MAAM,sBAAsB;;;;;;;;;;;;;;;AAgC5B,MAAa,uBACX,aACyB;CACzB,MAAM,sBAAsB,YAAY,GAAE,CAAE,KAAK,CAAC,CAAC,YAAY;CAE/D,MAAM,cACJ,eAAe,uBACd;CAEH,MAAM,cAAc,eAAe;CAEnC,IAAI,CAAC,aACH,OAAO;EAAE,IAAI;EAAqB,aAAa;CAAK;CAGtD,OAAO;EAAE,IAAI;EAAa;CAAY;AACxC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { cn } from "../../utils/cn.mjs";
|
|
2
|
-
import { cva } from "class-variance-authority";
|
|
3
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
4
|
|
|
5
5
|
//#region src/components/Input/Checkbox.tsx
|
|
6
6
|
const checkboxVariants = cva([
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { Input } from "./Input.mjs";
|
|
4
4
|
import { useState } from "react";
|
|
5
|
-
import { EyeIcon, EyeOffIcon } from "lucide-react";
|
|
6
5
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
+
import { EyeIcon, EyeOffIcon } from "lucide-react";
|
|
7
7
|
|
|
8
8
|
//#region src/components/Input/InputPassword.tsx
|
|
9
9
|
const InputPassword = (props) => {
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
import { cn } from "../../utils/cn.mjs";
|
|
4
4
|
import { Button } from "../Button/Button.mjs";
|
|
5
5
|
import { createContext, useContext, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
7
|
import { cva } from "class-variance-authority";
|
|
7
8
|
import { MinusIcon } from "lucide-react";
|
|
8
|
-
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
|
|
10
10
|
//#region src/components/Input/OTPInput.tsx
|
|
11
11
|
/**
|
|
@@ -201,9 +201,10 @@ const OTPInput = ({ value: uncheckedValue, onChange: uncheckedOnChange, maxLengt
|
|
|
201
201
|
const finalSelectionStart = calculatedStart !== -1 ? calculatedStart : selectionStart;
|
|
202
202
|
const finalSelectionEnd = calculatedEnd !== -1 ? calculatedEnd : selectionEnd;
|
|
203
203
|
const finalDirection = calculatedDirection;
|
|
204
|
-
if (selectionStart !== null && selectionEnd !== null)
|
|
205
|
-
|
|
206
|
-
|
|
204
|
+
if (selectionStart !== null && selectionEnd !== null) {
|
|
205
|
+
if (selectionStart === selectionEnd) setActualCaretPosition(selectionStart);
|
|
206
|
+
else setActualCaretPosition(finalSelectionStart);
|
|
207
|
+
} else setActualCaretPosition(null);
|
|
207
208
|
setMirrorSelectionStart(finalSelectionStart);
|
|
208
209
|
setMirrorSelectionEnd(finalSelectionEnd);
|
|
209
210
|
inputMetadataRef.current.prev = [
|