Last active
March 13, 2025 20:19
-
-
Save e111077/7e1c4212bc8b408d8f8d0abacac824a8 to your computer and use it in GitHub Desktop.
Naiive Tagged Template Literal Support in Codemirror 6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { LanguageSupport, LRLanguage } from '@codemirror/language'; | |
| import { LRParser } from '@lezer/lr'; | |
| import { Input, parseMixed, SyntaxNodeRef } from '@lezer/common'; | |
| import { htmlLanguage } from '@codemirror/lang-html'; | |
| import {javascript} from '@codemirror/lang-javascript'; | |
| import {CodeMirrorExtensionElement} from 'codemirror-elements/lib/cm-extension-element.js'; | |
| function mixedTaggedTemplate(node: SyntaxNodeRef, input: Input) { | |
| const isTaggedTemplate = node.type.name === "TaggedTemplateExpression"; | |
| let isHtmlTag = false; | |
| if (isTaggedTemplate) { | |
| const tag = node.node.getChild("VariableName"); | |
| isHtmlTag = !!tag && input.read(tag.from, tag.to) === "html"; | |
| } | |
| // Check if the node is a TaggedTemplate literal and the tag is "html" | |
| if (isHtmlTag) { | |
| const content = node.node.getChild("TemplateString"); | |
| // jump into the html language parser | |
| if (content) { | |
| return { | |
| from: content.from, | |
| to: content.to, | |
| parser: htmlLanguage.parser, | |
| delims: { open: "${", close: "}" } | |
| }; | |
| } | |
| } | |
| return null; | |
| } | |
| // Create our mixed wrapper using parseMixed. | |
| const mixedWrapper = parseMixed(mixedTaggedTemplate); | |
| @customElement('cm-lang-javascript') | |
| export class CodeMirrorLangJavascript extends CodeMirrorExtensionElement { | |
| @property({ type: Boolean }) | |
| jsx = false; | |
| @property({ type: Boolean }) | |
| typescript = false; | |
| override update(changedProperties: PropertyValues<this>) { | |
| if (changedProperties.has('jsx') || changedProperties.has('typescript')) { | |
| // Create the base JavaScript language support extension | |
| const jsSupport = javascript({ | |
| jsx: this.jsx, | |
| typescript: this.typescript | |
| }); | |
| const baseParser = jsSupport.language.parser as LRParser; | |
| // Configure the parser to use our mixed-language wrapper. | |
| const wrappedParser = baseParser.configure({ wrap: mixedWrapper }); | |
| // Create a language from the wrapped parser | |
| const taggedTemplateLanguage = LRLanguage.define({ | |
| parser: wrappedParser, | |
| languageData: jsSupport.language.data.of({}) | |
| }); | |
| // Build a new LanguageSupport extension with the new parser. | |
| const taggedTemplateLiteralLanguageSupport = new LanguageSupport( | |
| taggedTemplateLanguage, | |
| jsSupport.extension | |
| ); | |
| // Set the new extension on the editor. | |
| this.setExtensions([taggedTemplateLiteralLanguageSupport]); | |
| } | |
| super.update(changedProperties); | |
| } | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
forked cm-lang-javascript from https://github.com/justinfagnani/codemirror-elements/blob/main/src/lib/cm-lang-javascript.ts