@mdxeditor/editor 3.52.5 → 3.53.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/dist/index.d.ts CHANGED
@@ -529,16 +529,24 @@ export declare interface CodeBlockEditorProps {
529
529
  }
530
530
 
531
531
  /**
532
- * The codemirror code block languages.
532
+ * A code block language entry with a name and optional aliases/extensions.
533
+ * Compatible with CodeMirror's `LanguageDescription` from `@codemirror/language-data`.
533
534
  * @group CodeMirror
534
535
  */
535
- export declare const codeBlockLanguages$: NodeRef<{
536
- js: string;
537
- ts: string;
538
- tsx: string;
539
- jsx: string;
540
- css: string;
541
- }>;
536
+ export declare interface CodeBlockLanguage {
537
+ /** Display name shown in the language select dropdown. */
538
+ name: string;
539
+ /** Alternative identifiers for this language (e.g. `["js"]` for JavaScript). */
540
+ alias?: readonly string[];
541
+ /** File extensions associated with this language (e.g. `["js", "mjs"]`). */
542
+ extensions?: readonly string[];
543
+ }
544
+
545
+ /**
546
+ * The normalized code block languages used by the CodeMirror editor.
547
+ * @group CodeMirror
548
+ */
549
+ export declare const codeBlockLanguages$: NodeRef<NormalizedCodeBlockLanguages>;
542
550
 
543
551
  /**
544
552
  * A lexical node that represents a fenced code block. Use {@link "$createCodeBlockNode"} to construct one.
@@ -607,7 +615,13 @@ export declare const codeMirrorExtensions$: NodeRef<Extension_2[]>;
607
615
  * @group CodeMirror
608
616
  */
609
617
  export declare const codeMirrorPlugin: (params?: {
610
- codeBlockLanguages: Record<string, string>;
618
+ /**
619
+ * The code block languages to display in the language select dropdown.
620
+ * Accepts either a `Record<string, string>` (key → label) for backwards compatibility,
621
+ * or an array of {@link CodeBlockLanguage} objects (compatible with CodeMirror's `LanguageDescription`
622
+ * from `@codemirror/language-data`), which supports aliases and file extensions.
623
+ */
624
+ codeBlockLanguages: Record<string, string> | CodeBlockLanguage[];
611
625
  /**
612
626
  * Optional, additional CodeMirror extensions to load in the diff/source mode.
613
627
  */
@@ -1190,6 +1204,8 @@ export declare const editorWrapperElementRef$: NodeRef<default_2.RefObject<HTMLD
1190
1204
 
1191
1205
  /* Excluded from this release type: editorWrappers$ */
1192
1206
 
1207
+ /* Excluded from this release type: EMPTY_VALUE */
1208
+
1193
1209
  export declare const EmptyTextNodeIndex: TextNodeIndex;
1194
1210
 
1195
1211
  /* Excluded from this release type: ExportLexicalTreeOptions */
@@ -2501,6 +2517,26 @@ export declare interface NewImageDialogState {
2501
2517
  */
2502
2518
  export declare function noop(): void;
2503
2519
 
2520
+ /**
2521
+ * Normalizes the `codeBlockLanguages` parameter into a canonical form.
2522
+ * Accepts either a `Record<string, string>` (legacy) or a `CodeBlockLanguage[]` array.
2523
+ */
2524
+ export declare function normalizeCodeBlockLanguages(input: Record<string, string> | CodeBlockLanguage[]): NormalizedCodeBlockLanguages;
2525
+
2526
+ /**
2527
+ * Internal normalized representation of code block languages.
2528
+ * @group CodeMirror
2529
+ */
2530
+ export declare interface NormalizedCodeBlockLanguages {
2531
+ /** Items for the language select dropdown. */
2532
+ items: {
2533
+ value: string;
2534
+ label: string;
2535
+ }[];
2536
+ /** Maps any known key (canonical, alias, extension) to the canonical key. */
2537
+ keyMap: Record<string, string>;
2538
+ }
2539
+
2504
2540
  /**
2505
2541
  * Emits when the editor loses focus
2506
2542
  * @group Core
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import { insertJsx$, isMdastJsxNode, jsxPlugin } from "./plugins/jsx/index.js";
18
18
  import { GenericJsxEditor } from "./jsx-editors/GenericJsxEditor.js";
19
19
  import { insertSandpack$, sandpackConfig$, sandpackPlugin } from "./plugins/sandpack/index.js";
20
20
  import { SandpackEditor } from "./plugins/sandpack/SandpackEditor.js";
21
- import { codeBlockLanguages$, codeMirrorAutoLoadLanguageSupport$, codeMirrorExtensions$, codeMirrorPlugin, insertCodeMirror$ } from "./plugins/codemirror/index.js";
21
+ import { EMPTY_VALUE, codeBlockLanguages$, codeMirrorAutoLoadLanguageSupport$, codeMirrorExtensions$, codeMirrorPlugin, insertCodeMirror$, normalizeCodeBlockLanguages } from "./plugins/codemirror/index.js";
22
22
  import { COMMON_STATE_CONFIG_EXTENSIONS, CodeMirrorEditor } from "./plugins/codemirror/CodeMirrorEditor.js";
23
23
  import { appendCodeBlockEditorDescriptor$, codeBlockPlugin, defaultCodeBlockLanguage$, insertCodeBlock$ } from "./plugins/codeblock/index.js";
24
24
  import { directivesPlugin, insertDirective$ } from "./plugins/directives/index.js";
@@ -110,6 +110,7 @@ export {
110
110
  DialogButton,
111
111
  DiffSourceToggleWrapper,
112
112
  DirectiveNode,
113
+ EMPTY_VALUE,
113
114
  EmptyTextNodeIndex,
114
115
  FrontmatterNode,
115
116
  GenericDirectiveEditor,
@@ -305,6 +306,7 @@ export {
305
306
  muteChange$,
306
307
  nestedEditorChildren$,
307
308
  noop,
309
+ normalizeCodeBlockLanguages,
308
310
  onBlur$,
309
311
  onClickLinkCallback$,
310
312
  onReadOnlyClickLinkCallback$,
@@ -10,11 +10,10 @@ import { indentWithTab } from "@codemirror/commands";
10
10
  import { basicLight } from "cm6-theme-basic-light";
11
11
  import { basicSetup } from "codemirror";
12
12
  import { $setSelection } from "lexical";
13
- import { codeMirrorExtensions$, codeMirrorAutoLoadLanguageSupport$, codeBlockLanguages$ } from "./index.js";
13
+ import { codeMirrorExtensions$, codeMirrorAutoLoadLanguageSupport$, codeBlockLanguages$, EMPTY_VALUE } from "./index.js";
14
14
  import { useCodeMirrorRef } from "../sandpack/useCodeMirrorRef.js";
15
15
  import { Select } from "../toolbar/primitives/select.js";
16
16
  const COMMON_STATE_CONFIG_EXTENSIONS = [];
17
- const EMPTY_VALUE = "__EMPTY_VALUE__";
18
17
  const CodeMirrorEditor = ({ language, nodeKey, code, focusEmitter }) => {
19
18
  const t = useTranslation();
20
19
  const { parentEditor, lexicalNode } = useCodeBlockEditorContext();
@@ -89,7 +88,7 @@ const CodeMirrorEditor = ({ language, nodeKey, code, focusEmitter }) => {
89
88
  Select,
90
89
  {
91
90
  disabled: readOnly,
92
- value: language,
91
+ value: codeBlockLanguages.keyMap[language] ?? language,
93
92
  onChange: (language2) => {
94
93
  parentEditor.update(() => {
95
94
  lexicalNode.setLanguage(language2 === EMPTY_VALUE ? "" : language2);
@@ -102,7 +101,7 @@ const CodeMirrorEditor = ({ language, nodeKey, code, focusEmitter }) => {
102
101
  },
103
102
  triggerTitle: t("codeBlock.selectLanguage", "Select code block language"),
104
103
  placeholder: t("codeBlock.inlineLanguage", "Language"),
105
- items: Object.entries(codeBlockLanguages).map(([value, label]) => ({ value: value ? value : EMPTY_VALUE, label }))
104
+ items: codeBlockLanguages.items
106
105
  }
107
106
  ), /* @__PURE__ */ React__default.createElement(
108
107
  "button",
@@ -2,13 +2,49 @@ import { realmPlugin } from "../../RealmWithPlugins.js";
2
2
  import { Cell, Signal, map } from "@mdxeditor/gurx";
3
3
  import { insertCodeBlock$, appendCodeBlockEditorDescriptor$ } from "../codeblock/index.js";
4
4
  import { CodeMirrorEditor } from "./CodeMirrorEditor.js";
5
- const codeBlockLanguages$ = Cell({
6
- js: "JavaScript",
7
- ts: "TypeScript",
8
- tsx: "TypeScript (React)",
9
- jsx: "JavaScript (React)",
10
- css: "CSS"
11
- });
5
+ const EMPTY_VALUE = "__EMPTY_VALUE__";
6
+ function normalizeCodeBlockLanguages(input) {
7
+ var _a;
8
+ const items = [];
9
+ const keyMap = {};
10
+ if (Array.isArray(input)) {
11
+ for (const lang of input) {
12
+ const canonical = ((_a = lang.alias) == null ? void 0 : _a[0]) ?? lang.name.toLowerCase();
13
+ items.push({ value: canonical, label: lang.name });
14
+ keyMap[canonical] = canonical;
15
+ if (lang.alias) {
16
+ for (const alias of lang.alias) {
17
+ keyMap[alias] = canonical;
18
+ }
19
+ }
20
+ if (lang.extensions) {
21
+ for (const ext of lang.extensions) {
22
+ keyMap[ext] = canonical;
23
+ }
24
+ }
25
+ keyMap[lang.name.toLowerCase()] = canonical;
26
+ }
27
+ } else {
28
+ const firstKeyByLabel = {};
29
+ for (const [key, label] of Object.entries(input)) {
30
+ if (!(label in firstKeyByLabel)) {
31
+ firstKeyByLabel[label] = key;
32
+ items.push({ value: key || EMPTY_VALUE, label });
33
+ }
34
+ keyMap[key] = firstKeyByLabel[label] || EMPTY_VALUE;
35
+ }
36
+ }
37
+ return { items, keyMap };
38
+ }
39
+ const codeBlockLanguages$ = Cell(
40
+ normalizeCodeBlockLanguages({
41
+ js: "JavaScript",
42
+ ts: "TypeScript",
43
+ tsx: "TypeScript (React)",
44
+ jsx: "JavaScript (React)",
45
+ css: "CSS"
46
+ })
47
+ );
12
48
  const insertCodeMirror$ = Signal((r) => {
13
49
  r.link(
14
50
  r.pipe(
@@ -29,33 +65,36 @@ const codeMirrorAutoLoadLanguageSupport$ = Cell(true);
29
65
  const codeMirrorPlugin = realmPlugin({
30
66
  update(r, params) {
31
67
  r.pubIn({
32
- [codeBlockLanguages$]: params == null ? void 0 : params.codeBlockLanguages,
68
+ [codeBlockLanguages$]: normalizeCodeBlockLanguages((params == null ? void 0 : params.codeBlockLanguages) ?? {}),
33
69
  [codeMirrorExtensions$]: (params == null ? void 0 : params.codeMirrorExtensions) ?? [],
34
70
  [codeMirrorAutoLoadLanguageSupport$]: (params == null ? void 0 : params.autoLoadLanguageSupport) ?? true
35
71
  });
36
72
  },
37
73
  init(r, params) {
74
+ const normalized = normalizeCodeBlockLanguages((params == null ? void 0 : params.codeBlockLanguages) ?? {});
38
75
  r.pubIn({
39
- [codeBlockLanguages$]: params == null ? void 0 : params.codeBlockLanguages,
76
+ [codeBlockLanguages$]: normalized,
40
77
  [codeMirrorExtensions$]: (params == null ? void 0 : params.codeMirrorExtensions) ?? [],
41
- [appendCodeBlockEditorDescriptor$]: buildCodeBlockDescriptor((params == null ? void 0 : params.codeBlockLanguages) ?? {}),
78
+ [appendCodeBlockEditorDescriptor$]: buildCodeBlockDescriptor(normalized),
42
79
  [codeMirrorAutoLoadLanguageSupport$]: (params == null ? void 0 : params.autoLoadLanguageSupport) ?? true
43
80
  });
44
81
  }
45
82
  });
46
- function buildCodeBlockDescriptor(codeBlockLanguages) {
83
+ function buildCodeBlockDescriptor(normalized) {
47
84
  return {
48
85
  match(language, meta) {
49
- return Object.hasOwn(codeBlockLanguages, language ?? "") && !meta;
86
+ return Object.hasOwn(normalized.keyMap, language ?? "") && !meta;
50
87
  },
51
88
  priority: 1,
52
89
  Editor: CodeMirrorEditor
53
90
  };
54
91
  }
55
92
  export {
93
+ EMPTY_VALUE,
56
94
  codeBlockLanguages$,
57
95
  codeMirrorAutoLoadLanguageSupport$,
58
96
  codeMirrorExtensions$,
59
97
  codeMirrorPlugin,
60
- insertCodeMirror$
98
+ insertCodeMirror$,
99
+ normalizeCodeBlockLanguages
61
100
  };
@@ -2,10 +2,9 @@ import { useCellValues } from "@mdxeditor/gurx";
2
2
  import React__default from "react";
3
3
  import styles from "../../../styles/ui.module.css.js";
4
4
  import { $isCodeBlockNode } from "../../codeblock/CodeBlockNode.js";
5
- import { codeBlockLanguages$ } from "../../codemirror/index.js";
5
+ import { codeBlockLanguages$, EMPTY_VALUE } from "../../codemirror/index.js";
6
6
  import { editorInFocus$, activeEditor$, useTranslation } from "../../core/index.js";
7
7
  import { Select } from "../primitives/select.js";
8
- const EMPTY_VALUE = "__EMPTY_VALUE__";
9
8
  const ChangeCodeMirrorLanguage = () => {
10
9
  const [editorInFocus, theEditor, codeBlockLanguages] = useCellValues(editorInFocus$, activeEditor$, codeBlockLanguages$);
11
10
  const codeBlockNode = $isCodeBlockNode(editorInFocus.rootNode) ? editorInFocus.rootNode : null;
@@ -13,7 +12,8 @@ const ChangeCodeMirrorLanguage = () => {
13
12
  if (!codeBlockNode) {
14
13
  return null;
15
14
  }
16
- let currentLanguage = codeBlockNode.getLanguage();
15
+ const rawLanguage = codeBlockNode.getLanguage();
16
+ let currentLanguage = codeBlockLanguages.keyMap[rawLanguage] ?? rawLanguage;
17
17
  if (currentLanguage === "") {
18
18
  currentLanguage = EMPTY_VALUE;
19
19
  }
@@ -33,7 +33,7 @@ const ChangeCodeMirrorLanguage = () => {
33
33
  },
34
34
  triggerTitle: t("codeBlock.selectLanguage", "Select code block language"),
35
35
  placeholder: t("codeBlock.language", "Code block language"),
36
- items: Object.entries(codeBlockLanguages).map(([value, label]) => ({ value: value ? value : EMPTY_VALUE, label }))
36
+ items: codeBlockLanguages.items
37
37
  }
38
38
  ));
39
39
  };
@@ -38,7 +38,7 @@ const SelectContent = ({
38
38
  },
39
39
  position: "popper"
40
40
  },
41
- /* @__PURE__ */ React__default.createElement(RadixSelect.Viewport, { "data-editor-dropdown": true }, children)
41
+ /* @__PURE__ */ React__default.createElement(RadixSelect.Viewport, { "data-editor-dropdown": true, style: { maxHeight: "var(--radix-select-content-available-height)" } }, children)
42
42
  ));
43
43
  };
44
44
  const SelectButtonTrigger = ({
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "*.css"
12
12
  ],
13
13
  "type": "module",
14
- "version": "3.52.5",
14
+ "version": "3.53.1",
15
15
  "description": "React component for rich text markdown editing",
16
16
  "scripts": {
17
17
  "build": "vite build",