diff --git a/src/editor/block/format-code.js b/src/editor/block/format-code.js index 6cd19d6..f4742dd 100644 --- a/src/editor/block/format-code.js +++ b/src/editor/block/format-code.js @@ -1,22 +1,8 @@ import { EditorSelection } from "@codemirror/state" import * as prettier from "prettier/standalone" -import babelParser from "prettier/plugins/babel.mjs" -import htmlParser from "prettier/esm/parser-html.mjs" -import cssParser from "prettier/esm/parser-postcss.mjs" -import markdownParser from "prettier/esm/parser-markdown.mjs" -import * as prettierPluginEstree from "prettier/plugins/estree.mjs"; - import { getActiveNoteBlock } from "./block.js" - - -const PARSER_MAP = { - "json": {parser:"json-stringify", plugins: [babelParser, prettierPluginEstree]}, - "javascript": {parser:"babel", plugins: [babelParser, prettierPluginEstree]}, - "html": {parser:"html", plugins: [htmlParser]}, - "css": {parser:"css", plugins: [cssParser]}, - "markdown": {parser:"markdown", plugins: [markdownParser]}, -} +import { getLanguage } from "../languages.js" export const formatBlockContent = async ({ state, dispatch }) => { @@ -24,9 +10,10 @@ export const formatBlockContent = async ({ state, dispatch }) => { return false const block = getActiveNoteBlock(state) - const langName = block.language.name - if (!(langName in PARSER_MAP)) + const language = getLanguage(block.language.name) + if (!language.prettier) { return false + } // get current cursor position const cursorPos = state.selection.asSingle().ranges[0].head @@ -49,8 +36,8 @@ export const formatBlockContent = async ({ state, dispatch }) => { if (useFormat) { formattedContent = { formatted: await prettier.format(content, { - parser: PARSER_MAP[langName].parser, - plugins: PARSER_MAP[langName].plugins, + parser: language.prettier.parser, + plugins: language.prettier.plugins, tabWidth: state.tabSize, }), cursorOffset: cursorPos == block.content.from ? 0 : content.length, @@ -58,8 +45,8 @@ export const formatBlockContent = async ({ state, dispatch }) => { } else { formattedContent = await prettier.formatWithCursor(content, { cursorOffset: cursorPos - block.content.from, - parser: PARSER_MAP[langName].parser, - plugins: PARSER_MAP[langName].plugins, + parser: language.prettier.parser, + plugins: language.prettier.plugins, tabWidth: state.tabSize, }) } diff --git a/src/editor/languages.js b/src/editor/languages.js index 4753783..b0f392e 100644 --- a/src/editor/languages.js +++ b/src/editor/languages.js @@ -21,38 +21,182 @@ import { go } from "@codemirror/legacy-modes/mode/go" import { clojure } from "@codemirror/legacy-modes/mode/clojure" import { erlang } from "@codemirror/legacy-modes/mode/erlang" +import babelPrettierPlugin from "prettier/plugins/babel.mjs" +import htmlPrettierPlugin from "prettier/esm/parser-html.mjs" +import cssPrettierPlugin from "prettier/esm/parser-postcss.mjs" +import markdownPrettierPlugin from "prettier/esm/parser-markdown.mjs" +import yamlPrettierPlugin from "prettier/plugins/yaml.mjs" +import rustPrettierPlugin from "prettier-plugin-rust" +import * as prettierPluginEstree from "prettier/plugins/estree.mjs"; + class Language { - constructor(token, name, parser, guesslang, supportsFormat = false) { + /** + * @param token: The token used to identify the language in the buffer content + * @param name: The name of the language + * @param parser: The Lezer parser used to parse the language + * @param guesslang: The name of the language as used by the guesslang library + * @param prettier: The prettier configuration for the language (if any) + */ + constructor({ token, name, parser, guesslang, prettier }) { this.token = token this.name = name this.parser = parser this.guesslang = guesslang - this.supportsFormat = supportsFormat + this.prettier = prettier + } + + get supportsFormat() { + return !!this.prettier } } export const LANGUAGES = [ - new Language("text", "Plain Text", null, null), - new Language("math", "Math", null, null), - new Language("javascript", "JavaScript", javascriptLanguage.parser, "js", true), - new Language("json", "JSON", jsonLanguage.parser, "json", true), - new Language("python", "Python", pythonLanguage.parser, "py"), - new Language("html", "HTML", htmlLanguage.parser, "html", true), - new Language("sql", "SQL", StandardSQL.language.parser, "sql"), - new Language("markdown", "Markdown", markdownLanguage.parser, "md", true), - new Language("java", "Java", javaLanguage.parser, "java"), - new Language("lezer", "Lezer", lezerLanguage.parser, null), - new Language("php", "PHP", phpLanguage.parser, "php"), - new Language("css", "CSS", cssLanguage.parser, "css", true), - new Language("xml", "XML", xmlLanguage.parser, "xml"), - new Language("cpp", "C++", cppLanguage.parser, "cpp"), - new Language("rust", "Rust", rustLanguage.parser, "rust"), - new Language("csharp", "C#", csharpLanguage.parser, "cs"), - new Language("ruby", "Ruby", StreamLanguage.define(ruby).parser, "rb"), - new Language("shell", "Shell", StreamLanguage.define(shell).parser, "sh"), - new Language("yaml", "YAML", StreamLanguage.define(yaml).parser, "yaml"), - new Language("golang", "Go", StreamLanguage.define(go).parser, "go"), - new Language("clojure", "Clojure", StreamLanguage.define(clojure).parser, "clj"), - new Language("erlang", "Erlang", StreamLanguage.define(erlang).parser, "erl"), + new Language({ + token: "text", + name: "Plain Text", + parser: null, + guesslang: null, + }), + new Language({ + token: "math", + name: "Math", + parser: null, + guesslang: null, + }), + new Language({ + token: "json", + name: "JSON", + parser: jsonLanguage.parser, + guesslang: "json", + prettier: {parser:"json-stringify", plugins: [babelPrettierPlugin, prettierPluginEstree]}, + }), + new Language({ + token: "python", + name: "Python", + parser: pythonLanguage.parser, + guesslang: "py", + }), + new Language({ + token: "html", + name: "HTML", + parser: htmlLanguage.parser, + guesslang: "html", + prettier: {parser:"html", plugins: [htmlPrettierPlugin]}, + }), + new Language({ + token: "sql", + name: "SQL", + parser: StandardSQL.language.parser, + guesslang: "sql", + }), + new Language({ + token: "markdown", + name: "Markdown", + parser: markdownLanguage.parser, + guesslang: "md", + prettier: {parser:"markdown", plugins: [markdownPrettierPlugin]}, + }), + new Language({ + token: "java", + name: "Java", + parser: javaLanguage.parser, + guesslang: "java", + }), + new Language({ + token: "lezer", + name: "Lezer", + parser: lezerLanguage.parser, + guesslang: null, + }), + new Language({ + token: "php", + name: "PHP", + parser: phpLanguage.parser, + guesslang: "php", + }), + new Language({ + token: "css", + name: "CSS", + parser: cssLanguage.parser, + guesslang: "css", + prettier: {parser:"css", plugins: [cssPrettierPlugin]}, + }), + new Language({ + token: "xml", + name: "XML", + parser: xmlLanguage.parser, + guesslang: "xml", + }), + new Language({ + token: "cpp", + name: "C++", + parser: cppLanguage.parser, + guesslang: "cpp", + }), + new Language({ + token: "rust", + name: "Rust", + parser: rustLanguage.parser, + guesslang: "rs", + }), + new Language({ + token: "csharp", + name: "C#", + parser: csharpLanguage.parser, + guesslang: "cs", + }), + new Language({ + token: "ruby", + name: "Ruby", + parser: StreamLanguage.define(ruby).parser, + guesslang: "rb", + }), + new Language({ + token: "shell", + name: "Shell", + parser: StreamLanguage.define(shell).parser, + guesslang: "sh", + }), + new Language({ + token: "yaml", + name: "YAML", + parser: StreamLanguage.define(yaml).parser, + guesslang: "yaml", + prettier: {parser:"yaml", plugins: [yamlPrettierPlugin]}, + }), + new Language({ + token: "golang", + name: "Go", + parser: StreamLanguage.define(go).parser, + guesslang: "go", + }), + new Language({ + token: "clojure", + name: "Clojure", + parser: StreamLanguage.define(clojure).parser, + guesslang: "clj", + }), + new Language({ + token: "erlang", + name: "Erlang", + parser: StreamLanguage.define(erlang).parser, + guesslang: "erl", + }), + new Language({ + token: "javascript", + name: "JavaScript", + parser: javascriptLanguage.parser, + guesslang: "js", + prettier: {parser:"babel", plugins: [babelPrettierPlugin, prettierPluginEstree]}, + }), ] + + +const languageMapping = Object.fromEntries(LANGUAGES.map(l => [l.token, l])) + +export function getLanguage(token) { + return languageMapping[token] +} + +