@@ -11,6 +11,7 @@ import type {LexicalEditor, LexicalNode, NodeKey} from 'lexical';
1111import {
1212 $isCodeHighlightNode ,
1313 $isCodeNode ,
14+ $plainifyCodeContent ,
1415 CodeExtension ,
1516 CodeHighlightNode ,
1617 CodeIndentExtension ,
@@ -50,20 +51,32 @@ export interface Token {
5051}
5152
5253export interface Tokenizer {
53- defaultLanguage : string ;
54+ /**
55+ * Language to fall back to when a {@link CodeNode} doesn't carry one.
56+ * Set to `null` to opt out of the implicit fallback — code blocks
57+ * without a language stay untouched (no `data-language` attribute, no
58+ * syntax highlighting) so a markdown round-trip can preserve ``` with
59+ * no info string.
60+ */
61+ defaultLanguage : string | null ;
5462 tokenize ( code : string , language ?: string ) : ( string | Token ) [ ] ;
5563 $tokenize ( codeNode : CodeNode , language ?: string ) : LexicalNode [ ] ;
5664}
5765
5866export const PrismTokenizer : Tokenizer = {
5967 $tokenize ( codeNode : CodeNode , language ?: string ) : LexicalNode [ ] {
60- return $getHighlightNodes ( codeNode , language || this . defaultLanguage ) ;
68+ const lang = language || this . defaultLanguage ;
69+ return lang === null
70+ ? $plainifyCodeContent ( codeNode . getTextContent ( ) )
71+ : $getHighlightNodes ( codeNode , lang ) ;
6172 } ,
6273 defaultLanguage : DEFAULT_CODE_LANGUAGE ,
6374 tokenize ( code : string , language ?: string ) : ( string | Token ) [ ] {
75+ const fallback = this . defaultLanguage ;
6476 return Prism . tokenize (
6577 code ,
66- Prism . languages [ language || '' ] || Prism . languages [ this . defaultLanguage ] ,
78+ Prism . languages [ language || '' ] ||
79+ ( fallback === null ? undefined : Prism . languages [ fallback ] ) ,
6780 ) ;
6881 } ,
6982} ;
@@ -119,22 +132,29 @@ function $codeNodeTransform(
119132 const { nodesCurrentlyHighlighting} = transformState ;
120133 const nodeKey = node . getKey ( ) ;
121134
122- // When new code block inserted it might not have language selected
123- if ( node . getLanguage ( ) === undefined ) {
135+ // When new code block inserted it might not have language selected.
136+ // Tokenizers configured with `defaultLanguage: null` opt out of the
137+ // implicit fallback — leave the node unset and skip highlighting so
138+ // markdown round-trips ``` (no info string) without injecting one.
139+ if ( node . getLanguage ( ) === undefined && tokenizer . defaultLanguage !== null ) {
124140 node . setLanguage ( tokenizer . defaultLanguage ) ;
125141 }
126142
127143 const language = node . getLanguage ( ) || tokenizer . defaultLanguage ;
128- if ( isCodeLanguageLoaded ( language ) ) {
129- if ( ! node . getIsSyntaxHighlightSupported ( ) ) {
130- node . setIsSyntaxHighlightSupported ( true ) ;
131- }
132- } else {
133- if ( node . getIsSyntaxHighlightSupported ( ) ) {
134- node . setIsSyntaxHighlightSupported ( false ) ;
144+ if ( language ) {
145+ if ( isCodeLanguageLoaded ( language ) ) {
146+ if ( ! node . getIsSyntaxHighlightSupported ( ) ) {
147+ node . setIsSyntaxHighlightSupported ( true ) ;
148+ }
149+ } else {
150+ if ( node . getIsSyntaxHighlightSupported ( ) ) {
151+ node . setIsSyntaxHighlightSupported ( false ) ;
152+ }
153+ loadCodeLanguage ( language , editor , nodeKey ) ;
154+ return ;
135155 }
136- loadCodeLanguage ( language , editor , nodeKey ) ;
137- return ;
156+ } else if ( node . getIsSyntaxHighlightSupported ( ) ) {
157+ node . setIsSyntaxHighlightSupported ( false ) ;
138158 }
139159
140160 if ( nodesCurrentlyHighlighting . has ( nodeKey ) ) {
@@ -161,7 +181,10 @@ function $codeNodeTransform(
161181 currentNode . getLanguage ( ) || tokenizer . defaultLanguage ;
162182 //const diffLanguageMatch = DIFF_LANGUAGE_REGEX.exec(currentLanguage);
163183
164- const highlightNodes = tokenizer . $tokenize ( currentNode , currentLanguage ) ;
184+ const highlightNodes = tokenizer . $tokenize (
185+ currentNode ,
186+ currentLanguage ?? undefined ,
187+ ) ;
165188
166189 const diffRange = getDiffRange ( currentNode . getChildren ( ) , highlightNodes ) ;
167190 const { from, to, nodesForReplacement} = diffRange ;
0 commit comments