✨ Added dockerfile、lua prettier plugin
This commit is contained in:
@@ -1,7 +1,5 @@
|
|||||||
importScripts("guesslang.min.js")
|
importScripts("guesslang.min.js")
|
||||||
|
|
||||||
const LANGUAGES = ["json", "py", "html", "sql", "md", "java", "php", "css", "xml", "cpp", "rs", "cs", "rb", "sh", "yaml", "toml", "go", "clj", "ex", "erl", "js", "ts", "swift", "kt", "groovy", "ps1", "dart", "scala"]
|
|
||||||
|
|
||||||
const guessLang = new self.GuessLang()
|
const guessLang = new self.GuessLang()
|
||||||
|
|
||||||
function sendResult(language, confidence, idx) {
|
function sendResult(language, confidence, idx) {
|
||||||
@@ -27,20 +25,13 @@ onmessage = (event) => {
|
|||||||
|
|
||||||
guessLang.runModel(content).then((result) => {
|
guessLang.runModel(content).then((result) => {
|
||||||
if (result.length > 0) {
|
if (result.length > 0) {
|
||||||
const lang = result[0]
|
// 返回置信度最高的结果
|
||||||
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.15) {
|
const bestResult = result[0]
|
||||||
sendResult(lang.languageId, lang.confidence, idx)
|
if (bestResult.confidence > 0.15) {
|
||||||
|
sendResult(bestResult.languageId, bestResult.confidence, idx)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let lang of result) {
|
|
||||||
if (LANGUAGES.includes(lang.languageId) && lang.confidence > 0.5) {
|
|
||||||
sendResult(lang.languageId, lang.confidence, idx)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendResult("text", 0.0, idx)
|
sendResult("text", 0.0, idx)
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
sendResult("text", 0.0, idx)
|
sendResult("text", 0.0, idx)
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
*.tgz
|
||||||
|
*.unopt.wasm
|
||||||
|
jsr.jsonc
|
||||||
32
frontend/src/common/prettier/plugins/dart/extra/dart_fmt.d.ts
vendored
Normal file
32
frontend/src/common/prettier/plugins/dart/extra/dart_fmt.d.ts
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
export function format(input: string, filename: string, config?: LayoutConfig): string;
|
||||||
|
|
||||||
|
interface LayoutConfig {
|
||||||
|
line_width?: number;
|
||||||
|
line_ending?: "lf" | "crlf";
|
||||||
|
language_version?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
export type InitOutput = unknown;
|
||||||
|
|
||||||
|
// export type SyncInitInput = BufferSource | WebAssembly.Module;
|
||||||
|
// /**
|
||||||
|
// * Instantiates the given `module`, which can either be bytes or
|
||||||
|
// * a precompiled `WebAssembly.Module`.
|
||||||
|
// *
|
||||||
|
// * @param {SyncInitInput} module
|
||||||
|
// *
|
||||||
|
// * @returns {InitOutput}
|
||||||
|
// */
|
||||||
|
// export function initSync(module: SyncInitInput): InitOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||||
|
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||||
|
*
|
||||||
|
* @param {InitInput | Promise<InitInput>} module_or_path
|
||||||
|
*
|
||||||
|
* @returns {Promise<InitOutput>}
|
||||||
|
*/
|
||||||
|
export default function init(module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||||
84
frontend/src/common/prettier/plugins/dart/extra/dart_fmt.js
Normal file
84
frontend/src/common/prettier/plugins/dart/extra/dart_fmt.js
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
import { format as dart_fmt, instantiate, invoke } from "./dart_fmt.mjs";
|
||||||
|
|
||||||
|
let wasm;
|
||||||
|
|
||||||
|
function get_imports() {}
|
||||||
|
function init_memory() {}
|
||||||
|
|
||||||
|
function normalize(module) {
|
||||||
|
if (!(module instanceof WebAssembly.Module)) {
|
||||||
|
return new WebAssembly.Module(module);
|
||||||
|
}
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function (input) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
if (typeof input === "undefined") {
|
||||||
|
input = new URL("dart_fmt.wasm", import.meta.url);
|
||||||
|
}
|
||||||
|
const imports = get_imports();
|
||||||
|
|
||||||
|
if (
|
||||||
|
typeof input === "string" ||
|
||||||
|
(typeof Request === "function" && input instanceof Request) ||
|
||||||
|
(typeof URL === "function" && input instanceof URL)
|
||||||
|
) {
|
||||||
|
input = fetch(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
init_memory(imports);
|
||||||
|
|
||||||
|
wasm = await load(await input)
|
||||||
|
.then(normalize)
|
||||||
|
.then(instantiate);
|
||||||
|
|
||||||
|
invoke(wasm);
|
||||||
|
|
||||||
|
return wasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function load(module) {
|
||||||
|
if (typeof Response === "function" && module instanceof Response) {
|
||||||
|
if ("compileStreaming" in WebAssembly) {
|
||||||
|
try {
|
||||||
|
return await WebAssembly.compileStreaming(module);
|
||||||
|
} catch (e) {
|
||||||
|
if (module.headers.get("Content-Type") != "application/wasm") {
|
||||||
|
console.warn(
|
||||||
|
"`WebAssembly.compileStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",
|
||||||
|
e,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return module.arrayBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function format(source, filename = "stdin.dart", config = {}) {
|
||||||
|
const options = { lineEnding: "\n" };
|
||||||
|
if (config.line_width) {
|
||||||
|
options.pageWidth = config.line_width;
|
||||||
|
}
|
||||||
|
if (options.line_ending === "crlf") {
|
||||||
|
options.lineEnding = "\r\n";
|
||||||
|
}
|
||||||
|
if(options.language_version) {
|
||||||
|
options.languageVersion = options.language_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = dart_fmt(source, filename, JSON.stringify(options));
|
||||||
|
const err = result[0] === "x";
|
||||||
|
const output = result.slice(1);
|
||||||
|
if (err) {
|
||||||
|
throw new Error(output);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./dart_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./dart_fmt.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = fs.readFile(wasm)) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./dart_fmt.js";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./dart_fmt.js";
|
||||||
|
import wasm from "./dart_fmt.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = wasm) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./dart_fmt.js";
|
||||||
31
frontend/src/common/prettier/plugins/dart/lib/binding.dart
Normal file
31
frontend/src/common/prettier/plugins/dart/lib/binding.dart
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:js_interop';
|
||||||
|
import 'package:dart_fmt/dart_fmt.dart';
|
||||||
|
|
||||||
|
class Options {
|
||||||
|
final int? pageWidth;
|
||||||
|
final String? lineEnding;
|
||||||
|
final String? languageVersion;
|
||||||
|
|
||||||
|
Options.fromJson(Map<String, dynamic> json)
|
||||||
|
: pageWidth = json['pageWidth'] as int?,
|
||||||
|
lineEnding = json['lineEnding'] as String?,
|
||||||
|
languageVersion = json['languageVersion'] as String?;
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatWrapper(String source, String filename, String options) {
|
||||||
|
final config = Options.fromJson(jsonDecode(options));
|
||||||
|
|
||||||
|
try {
|
||||||
|
return "o${format(source, filename, pageWidth: config.pageWidth, lineEnding: config.lineEnding, version: config.languageVersion)}";
|
||||||
|
} catch (e) {
|
||||||
|
return "x$e";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@JS('format')
|
||||||
|
external set formatExport(JSFunction handler);
|
||||||
|
|
||||||
|
void main(List<String> arguments) {
|
||||||
|
formatExport = formatWrapper.toJS;
|
||||||
|
}
|
||||||
14
frontend/src/common/prettier/plugins/dart/lib/dart_fmt.dart
Normal file
14
frontend/src/common/prettier/plugins/dart/lib/dart_fmt.dart
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import 'package:dart_style/dart_style.dart';
|
||||||
|
import 'package:pub_semver/pub_semver.dart';
|
||||||
|
|
||||||
|
String format(String source, String filename,
|
||||||
|
{int? pageWidth, String? lineEnding, String? version}) {
|
||||||
|
final languageVersion = version != null
|
||||||
|
? Version.parse(version)
|
||||||
|
: DartFormatter.latestLanguageVersion;
|
||||||
|
final formatter = DartFormatter(
|
||||||
|
pageWidth: pageWidth,
|
||||||
|
lineEnding: lineEnding,
|
||||||
|
languageVersion: languageVersion);
|
||||||
|
return formatter.format(source, uri: filename);
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
cd $(dirname $0)/..
|
||||||
|
|
||||||
|
dart compile wasm ./lib/binding.dart -o ./build/dart_fmt.wasm
|
||||||
|
cp -LR ./extra/. ./build/
|
||||||
|
|
||||||
|
./scripts/patch.mjs ./build/dart_fmt.mjs
|
||||||
|
./scripts/package.mjs ./package.json
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import process from "node:process";
|
||||||
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
const pkg_path = path.resolve(process.cwd(), process.argv[2]);
|
||||||
|
const pkg_text = fs.readFileSync(pkg_path, { encoding: "utf-8" });
|
||||||
|
const pkg_json = JSON.parse(pkg_text);
|
||||||
|
|
||||||
|
// JSR
|
||||||
|
|
||||||
|
const jsr_path = path.resolve(pkg_path, "..", "build", "jsr.jsonc");
|
||||||
|
pkg_json.name = "@fmt/dart-fmt";
|
||||||
|
pkg_json.exports = "./dart_fmt.js";
|
||||||
|
pkg_json.exclude = ["!../build", "*.tgz", ".npmignore"];
|
||||||
|
fs.writeFileSync(jsr_path, JSON.stringify(pkg_json, null, 4));
|
||||||
13
frontend/src/common/prettier/plugins/dart/scripts/patch.mjs
Normal file
13
frontend/src/common/prettier/plugins/dart/scripts/patch.mjs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import process from "node:process";
|
||||||
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
const file_path = path.resolve(process.cwd(), process.argv[2]);
|
||||||
|
let file_text = fs.readFileSync(file_path, { encoding: "utf-8" });
|
||||||
|
|
||||||
|
file_text = file_text.replace(`"length": (s) => s.length`, '"length": (s) => s?.length||0');
|
||||||
|
file_text = file_text.replace('globalThis.format', 'format');
|
||||||
|
file_text += "\nexport let format;";
|
||||||
|
|
||||||
|
fs.writeFileSync(file_path, file_text);
|
||||||
25
frontend/src/common/prettier/plugins/lua/Cargo.toml
Normal file
25
frontend/src/common/prettier/plugins/lua/Cargo.toml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
[package]
|
||||||
|
name = "lua_fmt"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.wasm-pack.profile.release]
|
||||||
|
wasm-opt = ["-Os"]
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
serde-wasm-bindgen = { workspace = true }
|
||||||
|
serde_json = { workspace = true, features = ["preserve_order"] }
|
||||||
|
stylua = { workspace = true, features = ["lua52", "lua53", "lua54"] }
|
||||||
|
wasm-bindgen = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
*.tgz
|
||||||
|
jsr.jsonc
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./lua_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./lua_fmt_bg.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = { module_or_path: fs.readFile(wasm) }) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./lua_fmt.js";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./lua_fmt.js";
|
||||||
|
import wasm from "./lua_fmt_bg.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = { module_or_path: wasm }) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./lua_fmt.js";
|
||||||
178
frontend/src/common/prettier/plugins/lua/index.ts
Normal file
178
frontend/src/common/prettier/plugins/lua/index.ts
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
/**
|
||||||
|
* Prettier Plugin for Lua formatting using StyLua WebAssembly
|
||||||
|
*
|
||||||
|
* This plugin provides support for formatting Lua files using the StyLua WASM implementation.
|
||||||
|
* StyLua is a fast Lua code formatter written in Rust.
|
||||||
|
*/
|
||||||
|
import type { Plugin, Parser, Printer } from 'prettier';
|
||||||
|
|
||||||
|
// Import the StyLua WASM module
|
||||||
|
import luaInit, { format, type Config } from './lua_fmt_vite.js';
|
||||||
|
|
||||||
|
const parserName = 'lua';
|
||||||
|
|
||||||
|
// Language configuration
|
||||||
|
const languages = [
|
||||||
|
{
|
||||||
|
name: 'Lua',
|
||||||
|
aliases: ['lua'],
|
||||||
|
parsers: [parserName],
|
||||||
|
extensions: ['.lua'],
|
||||||
|
aceMode: 'lua',
|
||||||
|
tmScope: 'source.lua',
|
||||||
|
linguistLanguageId: 213,
|
||||||
|
vscodeLanguageIds: ['lua']
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// Parser configuration
|
||||||
|
const luaParser: Parser<string> = {
|
||||||
|
astFormat: parserName,
|
||||||
|
parse: (text: string) => text,
|
||||||
|
locStart: () => 0,
|
||||||
|
locEnd: (node: string) => node.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize StyLua WASM module
|
||||||
|
let initPromise: Promise<void> | null = null;
|
||||||
|
let isInitialized = false;
|
||||||
|
|
||||||
|
function initStyLua(): Promise<void> {
|
||||||
|
if (initPromise) {
|
||||||
|
return initPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
initPromise = (async () => {
|
||||||
|
if (!isInitialized) {
|
||||||
|
await luaInit();
|
||||||
|
isInitialized = true;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return initPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Printer configuration
|
||||||
|
const luaPrinter: Printer<string> = {
|
||||||
|
print: (path, options) => {
|
||||||
|
try {
|
||||||
|
if (!isInitialized) {
|
||||||
|
console.warn('StyLua WASM module not initialized, returning original text');
|
||||||
|
return (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
const text = (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
const config = getStyLuaConfig(options);
|
||||||
|
|
||||||
|
// Format using StyLua (synchronous call)
|
||||||
|
const formatted = format(text, "input.lua", config);
|
||||||
|
|
||||||
|
return formatted.trim();
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('StyLua formatting failed:', error);
|
||||||
|
// Return original text if formatting fails
|
||||||
|
return (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to create StyLua config from Prettier options
|
||||||
|
function getStyLuaConfig(options: any): Config {
|
||||||
|
const config: Config = {};
|
||||||
|
|
||||||
|
// Map Prettier options to StyLua config
|
||||||
|
if (options.useTabs !== undefined) {
|
||||||
|
config.indent_style = options.useTabs ? 'tab' : 'space';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.tabWidth !== undefined) {
|
||||||
|
config.indent_width = options.tabWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.printWidth !== undefined) {
|
||||||
|
config.line_width = options.printWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.endOfLine !== undefined) {
|
||||||
|
config.line_ending = options.endOfLine === 'crlf' ? 'crlf' : 'lf';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.singleQuote !== undefined) {
|
||||||
|
config.quote_style = options.singleQuote ? 'AutoPreferSingle' : 'AutoPreferDouble';
|
||||||
|
}
|
||||||
|
|
||||||
|
// StyLua specific options
|
||||||
|
if (options.luaCallParentheses !== undefined) {
|
||||||
|
config.call_parentheses = options.luaCallParentheses;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.luaCollapseSimpleStatement !== undefined) {
|
||||||
|
config.collapse_simple_statement = options.luaCollapseSimpleStatement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.luaSortRequires !== undefined) {
|
||||||
|
config.sort_requires = options.luaSortRequires;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Plugin options
|
||||||
|
const options = {
|
||||||
|
luaCallParentheses: {
|
||||||
|
since: '0.0.1',
|
||||||
|
category: 'Format' as const,
|
||||||
|
type: 'choice' as const,
|
||||||
|
default: 'Always',
|
||||||
|
description: 'How to handle function call parentheses',
|
||||||
|
choices: [
|
||||||
|
{ value: 'Always', description: 'Always use parentheses' },
|
||||||
|
{ value: 'NoSingleString', description: 'Remove parentheses for single string argument' },
|
||||||
|
{ value: 'NoSingleTable', description: 'Remove parentheses for single table argument' },
|
||||||
|
{ value: 'None', description: 'Remove parentheses when possible' },
|
||||||
|
{ value: 'Input', description: 'Keep input formatting' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
luaCollapseSimpleStatement: {
|
||||||
|
since: '0.0.1',
|
||||||
|
category: 'Format' as const,
|
||||||
|
type: 'choice' as const,
|
||||||
|
default: 'Never',
|
||||||
|
description: 'How to handle simple statement collapsing',
|
||||||
|
choices: [
|
||||||
|
{ value: 'Never', description: 'Never collapse simple statements' },
|
||||||
|
{ value: 'FunctionOnly', description: 'Collapse function statements only' },
|
||||||
|
{ value: 'ConditionalOnly', description: 'Collapse conditional statements only' },
|
||||||
|
{ value: 'Always', description: 'Always collapse simple statements' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
luaSortRequires: {
|
||||||
|
since: '0.0.1',
|
||||||
|
category: 'Format' as const,
|
||||||
|
type: 'boolean' as const,
|
||||||
|
default: false,
|
||||||
|
description: 'Sort require statements alphabetically'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Plugin object
|
||||||
|
const luaPlugin: Plugin = {
|
||||||
|
languages,
|
||||||
|
parsers: {
|
||||||
|
[parserName]: luaParser,
|
||||||
|
},
|
||||||
|
printers: {
|
||||||
|
[parserName]: luaPrinter,
|
||||||
|
},
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize WASM module when plugin loads
|
||||||
|
initStyLua().catch(error => {
|
||||||
|
console.warn('Failed to initialize StyLua WASM module:', error);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default luaPlugin;
|
||||||
|
export { languages };
|
||||||
|
export const parsers = luaPlugin.parsers;
|
||||||
|
export const printers = luaPlugin.printers;
|
||||||
52
frontend/src/common/prettier/plugins/lua/lua_fmt.d.ts
vendored
Normal file
52
frontend/src/common/prettier/plugins/lua/lua_fmt.d.ts
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export function format(input: string, filename: string, config?: Config): string;
|
||||||
|
|
||||||
|
interface LayoutConfig {
|
||||||
|
indent_style?: "tab" | "space";
|
||||||
|
indent_width?: number;
|
||||||
|
line_width?: number;
|
||||||
|
line_ending?: "lf" | "crlf";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface Config extends LayoutConfig {
|
||||||
|
quote_style?: "AutoPreferDouble" | "AutoPreferSingle" | "ForceDouble" | "ForceSingle";
|
||||||
|
call_parentheses?: "Always" | "NoSingleString" | "NoSingleTable" | "None" | "Input";
|
||||||
|
collapse_simple_statement?: | "Never" | "FunctionOnly" | "ConditionalOnly" | "Always";
|
||||||
|
sort_requires?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
export interface InitOutput {
|
||||||
|
readonly memory: WebAssembly.Memory;
|
||||||
|
readonly format: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
readonly __wbindgen_export_0: (a: number, b: number) => number;
|
||||||
|
readonly __wbindgen_export_1: (a: number, b: number, c: number, d: number) => number;
|
||||||
|
readonly __wbindgen_export_2: (a: number) => void;
|
||||||
|
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||||
|
readonly __wbindgen_export_3: (a: number, b: number, c: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
||||||
|
/**
|
||||||
|
* Instantiates the given `module`, which can either be bytes or
|
||||||
|
* a precompiled `WebAssembly.Module`.
|
||||||
|
*
|
||||||
|
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
||||||
|
*
|
||||||
|
* @returns {InitOutput}
|
||||||
|
*/
|
||||||
|
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||||
|
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||||
|
*
|
||||||
|
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
||||||
|
*
|
||||||
|
* @returns {Promise<InitOutput>}
|
||||||
|
*/
|
||||||
|
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||||
524
frontend/src/common/prettier/plugins/lua/lua_fmt.js
Normal file
524
frontend/src/common/prettier/plugins/lua/lua_fmt.js
Normal file
@@ -0,0 +1,524 @@
|
|||||||
|
let wasm;
|
||||||
|
|
||||||
|
const heap = new Array(128).fill(undefined);
|
||||||
|
|
||||||
|
heap.push(undefined, null, true, false);
|
||||||
|
|
||||||
|
function getObject(idx) { return heap[idx]; }
|
||||||
|
|
||||||
|
let WASM_VECTOR_LEN = 0;
|
||||||
|
|
||||||
|
let cachedUint8ArrayMemory0 = null;
|
||||||
|
|
||||||
|
function getUint8ArrayMemory0() {
|
||||||
|
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
||||||
|
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
||||||
|
}
|
||||||
|
return cachedUint8ArrayMemory0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
|
||||||
|
|
||||||
|
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||||
|
? function (arg, view) {
|
||||||
|
return cachedTextEncoder.encodeInto(arg, view);
|
||||||
|
}
|
||||||
|
: function (arg, view) {
|
||||||
|
const buf = cachedTextEncoder.encode(arg);
|
||||||
|
view.set(buf);
|
||||||
|
return {
|
||||||
|
read: arg.length,
|
||||||
|
written: buf.length
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function passStringToWasm0(arg, malloc, realloc) {
|
||||||
|
|
||||||
|
if (realloc === undefined) {
|
||||||
|
const buf = cachedTextEncoder.encode(arg);
|
||||||
|
const ptr = malloc(buf.length, 1) >>> 0;
|
||||||
|
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||||
|
WASM_VECTOR_LEN = buf.length;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = arg.length;
|
||||||
|
let ptr = malloc(len, 1) >>> 0;
|
||||||
|
|
||||||
|
const mem = getUint8ArrayMemory0();
|
||||||
|
|
||||||
|
let offset = 0;
|
||||||
|
|
||||||
|
for (; offset < len; offset++) {
|
||||||
|
const code = arg.charCodeAt(offset);
|
||||||
|
if (code > 0x7F) break;
|
||||||
|
mem[ptr + offset] = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset !== len) {
|
||||||
|
if (offset !== 0) {
|
||||||
|
arg = arg.slice(offset);
|
||||||
|
}
|
||||||
|
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
||||||
|
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
||||||
|
const ret = encodeString(arg, view);
|
||||||
|
|
||||||
|
offset += ret.written;
|
||||||
|
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WASM_VECTOR_LEN = offset;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cachedDataViewMemory0 = null;
|
||||||
|
|
||||||
|
function getDataViewMemory0() {
|
||||||
|
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
||||||
|
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
||||||
|
}
|
||||||
|
return cachedDataViewMemory0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let heap_next = heap.length;
|
||||||
|
|
||||||
|
function addHeapObject(obj) {
|
||||||
|
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||||
|
const idx = heap_next;
|
||||||
|
heap_next = heap[idx];
|
||||||
|
|
||||||
|
heap[idx] = obj;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(f, args) {
|
||||||
|
try {
|
||||||
|
return f.apply(this, args);
|
||||||
|
} catch (e) {
|
||||||
|
wasm.__wbindgen_export_2(addHeapObject(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLikeNone(x) {
|
||||||
|
return x === undefined || x === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function debugString(val) {
|
||||||
|
// primitive types
|
||||||
|
const type = typeof val;
|
||||||
|
if (type == 'number' || type == 'boolean' || val == null) {
|
||||||
|
return `${val}`;
|
||||||
|
}
|
||||||
|
if (type == 'string') {
|
||||||
|
return `"${val}"`;
|
||||||
|
}
|
||||||
|
if (type == 'symbol') {
|
||||||
|
const description = val.description;
|
||||||
|
if (description == null) {
|
||||||
|
return 'Symbol';
|
||||||
|
} else {
|
||||||
|
return `Symbol(${description})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == 'function') {
|
||||||
|
const name = val.name;
|
||||||
|
if (typeof name == 'string' && name.length > 0) {
|
||||||
|
return `Function(${name})`;
|
||||||
|
} else {
|
||||||
|
return 'Function';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// objects
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
const length = val.length;
|
||||||
|
let debug = '[';
|
||||||
|
if (length > 0) {
|
||||||
|
debug += debugString(val[0]);
|
||||||
|
}
|
||||||
|
for(let i = 1; i < length; i++) {
|
||||||
|
debug += ', ' + debugString(val[i]);
|
||||||
|
}
|
||||||
|
debug += ']';
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
// Test for built-in
|
||||||
|
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||||
|
let className;
|
||||||
|
if (builtInMatches && builtInMatches.length > 1) {
|
||||||
|
className = builtInMatches[1];
|
||||||
|
} else {
|
||||||
|
// Failed to match the standard '[object ClassName]'
|
||||||
|
return toString.call(val);
|
||||||
|
}
|
||||||
|
if (className == 'Object') {
|
||||||
|
// we're a user defined class or Object
|
||||||
|
// JSON.stringify avoids problems with cycles, and is generally much
|
||||||
|
// easier than looping through ownProperties of `val`.
|
||||||
|
try {
|
||||||
|
return 'Object(' + JSON.stringify(val) + ')';
|
||||||
|
} catch (_) {
|
||||||
|
return 'Object';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// errors
|
||||||
|
if (val instanceof Error) {
|
||||||
|
return `${val.name}: ${val.message}\n${val.stack}`;
|
||||||
|
}
|
||||||
|
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||||
|
|
||||||
|
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
|
||||||
|
|
||||||
|
function getStringFromWasm0(ptr, len) {
|
||||||
|
ptr = ptr >>> 0;
|
||||||
|
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dropObject(idx) {
|
||||||
|
if (idx < 132) return;
|
||||||
|
heap[idx] = heap_next;
|
||||||
|
heap_next = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function takeObject(idx) {
|
||||||
|
const ret = getObject(idx);
|
||||||
|
dropObject(idx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @param {string} filename
|
||||||
|
* @param {Config | undefined} [config]
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function format(input, filename, config) {
|
||||||
|
let deferred4_0;
|
||||||
|
let deferred4_1;
|
||||||
|
try {
|
||||||
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||||
|
const ptr0 = passStringToWasm0(input, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
const ptr1 = passStringToWasm0(filename, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
wasm.format(retptr, ptr0, len0, ptr1, len1, isLikeNone(config) ? 0 : addHeapObject(config));
|
||||||
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||||
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||||
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||||
|
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
||||||
|
var ptr3 = r0;
|
||||||
|
var len3 = r1;
|
||||||
|
if (r3) {
|
||||||
|
ptr3 = 0; len3 = 0;
|
||||||
|
throw takeObject(r2);
|
||||||
|
}
|
||||||
|
deferred4_0 = ptr3;
|
||||||
|
deferred4_1 = len3;
|
||||||
|
return getStringFromWasm0(ptr3, len3);
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||||
|
wasm.__wbindgen_export_3(deferred4_0, deferred4_1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function __wbg_load(module, imports) {
|
||||||
|
if (typeof Response === 'function' && module instanceof Response) {
|
||||||
|
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||||
|
try {
|
||||||
|
return await WebAssembly.instantiateStreaming(module, imports);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||||
|
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bytes = await module.arrayBuffer();
|
||||||
|
return await WebAssembly.instantiate(bytes, imports);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const instance = await WebAssembly.instantiate(module, imports);
|
||||||
|
|
||||||
|
if (instance instanceof WebAssembly.Instance) {
|
||||||
|
return { instance, module };
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_get_imports() {
|
||||||
|
const imports = {};
|
||||||
|
imports.wbg = {};
|
||||||
|
imports.wbg.__wbg_String_8f0eb39a4a4c2f66 = function(arg0, arg1) {
|
||||||
|
const ret = String(getObject(arg1));
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_buffer_71667b1101df19da = function(arg0) {
|
||||||
|
const ret = getObject(arg0).buffer;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_call_d68488931693e6ee = function() { return handleError(function (arg0, arg1) {
|
||||||
|
const ret = getObject(arg0).call(getObject(arg1));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_done_3ca5b09e8598078d = function(arg0) {
|
||||||
|
const ret = getObject(arg0).done;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_entries_d873dde863e50b8c = function(arg0) {
|
||||||
|
const ret = Object.entries(getObject(arg0));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_get_c122b1d576cf1fdb = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0)[arg1 >>> 0];
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_get_ddd82e34e6366fb9 = function() { return handleError(function (arg0, arg1) {
|
||||||
|
const ret = Reflect.get(getObject(arg0), getObject(arg1));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_instanceof_ArrayBuffer_36214dbc6ea8dd3d = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = getObject(arg0) instanceof ArrayBuffer;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_Map_52afb7722e323e8b = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = getObject(arg0) instanceof Map;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_Uint8Array_0d898f7981fe0a2d = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = getObject(arg0) instanceof Uint8Array;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_isArray_435f9cb9abc7eccc = function(arg0) {
|
||||||
|
const ret = Array.isArray(getObject(arg0));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_isSafeInteger_2817b2c8ebdd29d2 = function(arg0) {
|
||||||
|
const ret = Number.isSafeInteger(getObject(arg0));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_iterator_2a6b115668862130 = function() {
|
||||||
|
const ret = Symbol.iterator;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_length_b52c3d528b88468e = function(arg0) {
|
||||||
|
const ret = getObject(arg0).length;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_length_e9123d1e4db12534 = function(arg0) {
|
||||||
|
const ret = getObject(arg0).length;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_new_9ed4506807911440 = function(arg0) {
|
||||||
|
const ret = new Uint8Array(getObject(arg0));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_next_86c8f7dfb19a94eb = function() { return handleError(function (arg0) {
|
||||||
|
const ret = getObject(arg0).next();
|
||||||
|
return addHeapObject(ret);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_next_b39104aeda52ac60 = function(arg0) {
|
||||||
|
const ret = getObject(arg0).next;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_set_e8d9380e866a1e41 = function(arg0, arg1, arg2) {
|
||||||
|
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_value_f82ca5432417c8ff = function(arg0) {
|
||||||
|
const ret = getObject(arg0).value;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_bigint_from_i64 = function(arg0) {
|
||||||
|
const ret = arg0;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) {
|
||||||
|
const ret = BigInt.asUintN(64, arg0);
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_bigint_get_as_i64 = function(arg0, arg1) {
|
||||||
|
const v = getObject(arg1);
|
||||||
|
const ret = typeof(v) === 'bigint' ? v : undefined;
|
||||||
|
getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_boolean_get = function(arg0) {
|
||||||
|
const v = getObject(arg0);
|
||||||
|
const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||||
|
const ret = debugString(getObject(arg1));
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
|
||||||
|
const ret = new Error(getStringFromWasm0(arg0, arg1));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_in = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0) in getObject(arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_bigint = function(arg0) {
|
||||||
|
const ret = typeof(getObject(arg0)) === 'bigint';
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_function = function(arg0) {
|
||||||
|
const ret = typeof(getObject(arg0)) === 'function';
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_object = function(arg0) {
|
||||||
|
const val = getObject(arg0);
|
||||||
|
const ret = typeof(val) === 'object' && val !== null;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_string = function(arg0) {
|
||||||
|
const ret = typeof(getObject(arg0)) === 'string';
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0) === getObject(arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0) == getObject(arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_memory = function() {
|
||||||
|
const ret = wasm.memory;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_number_get = function(arg0, arg1) {
|
||||||
|
const obj = getObject(arg1);
|
||||||
|
const ret = typeof(obj) === 'number' ? obj : undefined;
|
||||||
|
getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
|
||||||
|
const ret = getObject(arg0);
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||||
|
takeObject(arg0);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
|
||||||
|
const obj = getObject(arg1);
|
||||||
|
const ret = typeof(obj) === 'string' ? obj : undefined;
|
||||||
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
var len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
||||||
|
const ret = getStringFromWasm0(arg0, arg1);
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||||
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||||
|
};
|
||||||
|
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_init_memory(imports, memory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_finalize_init(instance, module) {
|
||||||
|
wasm = instance.exports;
|
||||||
|
__wbg_init.__wbindgen_wasm_module = module;
|
||||||
|
cachedDataViewMemory0 = null;
|
||||||
|
cachedUint8ArrayMemory0 = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return wasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSync(module) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
if (Object.getPrototypeOf(module) === Object.prototype) {
|
||||||
|
({module} = module)
|
||||||
|
} else {
|
||||||
|
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const imports = __wbg_get_imports();
|
||||||
|
|
||||||
|
__wbg_init_memory(imports);
|
||||||
|
|
||||||
|
if (!(module instanceof WebAssembly.Module)) {
|
||||||
|
module = new WebAssembly.Module(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = new WebAssembly.Instance(module, imports);
|
||||||
|
|
||||||
|
return __wbg_finalize_init(instance, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function __wbg_init(module_or_path) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof module_or_path !== 'undefined') {
|
||||||
|
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
||||||
|
({module_or_path} = module_or_path)
|
||||||
|
} else {
|
||||||
|
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof module_or_path === 'undefined') {
|
||||||
|
module_or_path = new URL('lua_fmt_bg.wasm', import.meta.url);
|
||||||
|
}
|
||||||
|
const imports = __wbg_get_imports();
|
||||||
|
|
||||||
|
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
||||||
|
module_or_path = fetch(module_or_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
__wbg_init_memory(imports);
|
||||||
|
|
||||||
|
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
||||||
|
|
||||||
|
return __wbg_finalize_init(instance, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { initSync };
|
||||||
|
export default __wbg_init;
|
||||||
BIN
frontend/src/common/prettier/plugins/lua/lua_fmt_bg.wasm
Normal file
BIN
frontend/src/common/prettier/plugins/lua/lua_fmt_bg.wasm
Normal file
Binary file not shown.
9
frontend/src/common/prettier/plugins/lua/lua_fmt_bg.wasm.d.ts
vendored
Normal file
9
frontend/src/common/prettier/plugins/lua/lua_fmt_bg.wasm.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export const memory: WebAssembly.Memory;
|
||||||
|
export const format: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
export const __wbindgen_export_0: (a: number, b: number) => number;
|
||||||
|
export const __wbindgen_export_1: (a: number, b: number, c: number, d: number) => number;
|
||||||
|
export const __wbindgen_export_2: (a: number) => void;
|
||||||
|
export const __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||||
|
export const __wbindgen_export_3: (a: number, b: number, c: number) => void;
|
||||||
10
frontend/src/common/prettier/plugins/lua/lua_fmt_node.js
Normal file
10
frontend/src/common/prettier/plugins/lua/lua_fmt_node.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./lua_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./lua_fmt_bg.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = { module_or_path: fs.readFile(wasm) }) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./lua_fmt.js";
|
||||||
8
frontend/src/common/prettier/plugins/lua/lua_fmt_vite.js
Normal file
8
frontend/src/common/prettier/plugins/lua/lua_fmt_vite.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./lua_fmt.js";
|
||||||
|
import wasm from "./lua_fmt_bg.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = { module_or_path: wasm }) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./lua_fmt.js";
|
||||||
11
frontend/src/common/prettier/plugins/lua/scripts/build.sh
Normal file
11
frontend/src/common/prettier/plugins/lua/scripts/build.sh
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
cd $(dirname $0)/..
|
||||||
|
crates_dir=$(pwd)
|
||||||
|
|
||||||
|
cd ../..
|
||||||
|
wasm-pack build --target=web --scope=wasm-fmt crates/lua_fmt
|
||||||
|
|
||||||
|
cd $crates_dir
|
||||||
|
|
||||||
|
cp -R ./extra/. ./pkg/
|
||||||
|
|
||||||
|
./scripts/package.mjs ./pkg/package.json
|
||||||
39
frontend/src/common/prettier/plugins/lua/scripts/package.mjs
Normal file
39
frontend/src/common/prettier/plugins/lua/scripts/package.mjs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import process from "node:process";
|
||||||
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
const pkg_path = path.resolve(process.cwd(), process.argv[2]);
|
||||||
|
const pkg_text = fs.readFileSync(pkg_path, { encoding: "utf-8" });
|
||||||
|
const pkg_json = JSON.parse(pkg_text);
|
||||||
|
|
||||||
|
delete pkg_json.files;
|
||||||
|
|
||||||
|
pkg_json.main = pkg_json.module;
|
||||||
|
pkg_json.type = "module";
|
||||||
|
pkg_json.publishConfig = {
|
||||||
|
access: "public",
|
||||||
|
};
|
||||||
|
pkg_json.exports = {
|
||||||
|
".": {
|
||||||
|
types: "./lua_fmt.d.ts",
|
||||||
|
node: "./lua_fmt_node.js",
|
||||||
|
default: "./lua_fmt.js",
|
||||||
|
},
|
||||||
|
"./vite": {
|
||||||
|
types: "./lua_fmt.d.ts",
|
||||||
|
default: "./lua_fmt_vite.js",
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json",
|
||||||
|
"./*": "./*",
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(pkg_path, JSON.stringify(pkg_json, null, 4));
|
||||||
|
|
||||||
|
// JSR
|
||||||
|
|
||||||
|
const jsr_path = path.resolve(pkg_path, "..", "jsr.jsonc");
|
||||||
|
pkg_json.name = "@fmt/lua-fmt";
|
||||||
|
pkg_json.exports = "./lua_fmt.js";
|
||||||
|
pkg_json.exclude = ["!**", "*.tgz"];
|
||||||
|
fs.writeFileSync(jsr_path, JSON.stringify(pkg_json, null, 4));
|
||||||
151
frontend/src/common/prettier/plugins/lua/src/lib.rs
Normal file
151
frontend/src/common/prettier/plugins/lua/src/lib.rs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use stylua_lib::{
|
||||||
|
format_code, CallParenType, CollapseSimpleStatement, Config as StyluaConfig, IndentType,
|
||||||
|
LineEndings, OutputVerification, QuoteStyle, SortRequiresConfig,
|
||||||
|
};
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn format(input: &str, filename: &str, config: Option<Config>) -> Result<String, String> {
|
||||||
|
let _ = filename;
|
||||||
|
|
||||||
|
let config = config
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value::<LuaConfig>(x.clone()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|op| op.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
format_code(input, config.into(), None, OutputVerification::None).map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
interface LayoutConfig {
|
||||||
|
indent_style?: "tab" | "space";
|
||||||
|
indent_width?: number;
|
||||||
|
line_width?: number;
|
||||||
|
line_ending?: "lf" | "crlf";
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
export interface Config extends LayoutConfig {
|
||||||
|
quote_style?: "AutoPreferDouble" | "AutoPreferSingle" | "ForceDouble" | "ForceSingle";
|
||||||
|
call_parentheses?: "Always" | "NoSingleString" | "NoSingleTable" | "None" | "Input";
|
||||||
|
collapse_simple_statement?: | "Never" | "FunctionOnly" | "ConditionalOnly" | "Always";
|
||||||
|
sort_requires?: boolean;
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "Config")]
|
||||||
|
pub type Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Clone, Default)]
|
||||||
|
struct LayoutConfig {
|
||||||
|
#[serde(alias = "indentStyle")]
|
||||||
|
indent_style: Option<IndentStyle>,
|
||||||
|
#[serde(alias = "indentWidth")]
|
||||||
|
indent_width: Option<u8>,
|
||||||
|
#[serde(alias = "lineWidth")]
|
||||||
|
line_width: Option<u16>,
|
||||||
|
#[serde(alias = "lineEnding")]
|
||||||
|
line_ending: Option<LineEnding>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Clone, Default)]
|
||||||
|
struct LuaConfig {
|
||||||
|
#[serde(flatten)]
|
||||||
|
layout: LayoutConfig,
|
||||||
|
|
||||||
|
#[serde(alias = "quoteStyle")]
|
||||||
|
quote_style: Option<QuoteStyle>,
|
||||||
|
|
||||||
|
#[serde(alias = "callParentheses")]
|
||||||
|
call_parentheses: Option<CallParenType>,
|
||||||
|
|
||||||
|
#[serde(alias = "collapseSimpleStatement")]
|
||||||
|
collapse_simple_statement: Option<CollapseSimpleStatement>,
|
||||||
|
|
||||||
|
#[serde(alias = "sortRequires")]
|
||||||
|
sort_requires: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LuaConfig> for StyluaConfig {
|
||||||
|
fn from(val: LuaConfig) -> Self {
|
||||||
|
let mut config = StyluaConfig::default();
|
||||||
|
|
||||||
|
if let Some(indent_style) = val.layout.indent_style {
|
||||||
|
config.indent_type = indent_style.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(indent_width) = val.layout.indent_width {
|
||||||
|
config.indent_width = indent_width as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_width) = val.layout.line_width {
|
||||||
|
config.column_width = line_width as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_ending) = val.layout.line_ending {
|
||||||
|
config.line_endings = line_ending.into();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(quote_style) = val.quote_style {
|
||||||
|
config.quote_style = quote_style;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(call_parentheses) = val.call_parentheses {
|
||||||
|
config.call_parentheses = call_parentheses;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(collapse_simple_statement) = val.collapse_simple_statement {
|
||||||
|
config.collapse_simple_statement = collapse_simple_statement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(enabled) = val.sort_requires {
|
||||||
|
let mut sort_requires = SortRequiresConfig::default();
|
||||||
|
sort_requires.enabled = enabled;
|
||||||
|
config.sort_requires = sort_requires;
|
||||||
|
}
|
||||||
|
|
||||||
|
config
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
enum IndentStyle {
|
||||||
|
Tab,
|
||||||
|
#[default]
|
||||||
|
Space,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IndentStyle> for IndentType {
|
||||||
|
fn from(val: IndentStyle) -> Self {
|
||||||
|
match val {
|
||||||
|
IndentStyle::Tab => Self::Tabs,
|
||||||
|
IndentStyle::Space => Self::Spaces,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
enum LineEnding {
|
||||||
|
#[default]
|
||||||
|
Lf,
|
||||||
|
Crlf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LineEnding> for LineEndings {
|
||||||
|
fn from(val: LineEnding) -> Self {
|
||||||
|
match val {
|
||||||
|
LineEnding::Lf => Self::Unix,
|
||||||
|
LineEnding::Crlf => Self::Windows,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
[package]
|
||||||
|
name = "ruff_fmt"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
description.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[package.metadata.wasm-pack.profile.release]
|
||||||
|
wasm-opt = ["-Os"]
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ruff_fmt_config = { workspace = true }
|
||||||
|
ruff_formatter = { workspace = true }
|
||||||
|
ruff_python_formatter = { workspace = true }
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
serde-wasm-bindgen = { workspace = true }
|
||||||
|
serde_json = { workspace = true, features = ["preserve_order"] }
|
||||||
|
wasm-bindgen = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
testing_macros = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
*.tgz
|
||||||
|
jsr.jsonc
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./ruff_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./ruff_fmt_bg.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = { module_or_path: fs.readFile(wasm) }) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./ruff_fmt.js";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./ruff_fmt.js";
|
||||||
|
import wasm from "./ruff_fmt_bg.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = { module_or_path: wasm }) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./ruff_fmt.js";
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
cd $(dirname $0)/..
|
||||||
|
crates_dir=$(pwd)
|
||||||
|
|
||||||
|
cd ../..
|
||||||
|
wasm-pack build --target=web --scope=wasm-fmt crates/ruff_fmt
|
||||||
|
cp README.md crates/ruff_fmt/pkg/
|
||||||
|
|
||||||
|
cd $crates_dir
|
||||||
|
|
||||||
|
cp -R ./extra/. ./pkg/
|
||||||
|
|
||||||
|
./scripts/package.mjs ./pkg/package.json
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import process from "node:process";
|
||||||
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
const pkg_path = path.resolve(process.cwd(), process.argv[2]);
|
||||||
|
const pkg_text = fs.readFileSync(pkg_path, { encoding: "utf-8" });
|
||||||
|
const pkg_json = JSON.parse(pkg_text);
|
||||||
|
|
||||||
|
delete pkg_json.files;
|
||||||
|
|
||||||
|
pkg_json.main = pkg_json.module;
|
||||||
|
pkg_json.type = "module";
|
||||||
|
pkg_json.publishConfig = {
|
||||||
|
access: "public",
|
||||||
|
};
|
||||||
|
pkg_json.exports = {
|
||||||
|
".": {
|
||||||
|
types: "./ruff_fmt.d.ts",
|
||||||
|
node: "./ruff_fmt_node.js",
|
||||||
|
default: "./ruff_fmt.js",
|
||||||
|
},
|
||||||
|
"./vite": {
|
||||||
|
types: "./ruff_fmt.d.ts",
|
||||||
|
default: "./ruff_fmt_vite.js",
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json",
|
||||||
|
"./*": "./*",
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(pkg_path, JSON.stringify(pkg_json, null, 4));
|
||||||
|
|
||||||
|
// JSR
|
||||||
|
|
||||||
|
const jsr_path = path.resolve(pkg_path, "..", "jsr.jsonc");
|
||||||
|
pkg_json.name = "@fmt/ruff-fmt";
|
||||||
|
pkg_json.exports = "./ruff_fmt.js";
|
||||||
|
pkg_json.exclude = ["!**", "*.tgz"];
|
||||||
|
fs.writeFileSync(jsr_path, JSON.stringify(pkg_json, null, 4));
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod test;
|
||||||
|
|
||||||
|
use ruff_fmt_config::Config as InnerConfig;
|
||||||
|
use ruff_python_formatter::format_module_source;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn format(input: &str, path: Option<String>, config: Option<Config>) -> Result<String, String> {
|
||||||
|
let mut config: InnerConfig = if let Some(config) = config {
|
||||||
|
serde_wasm_bindgen::from_value(config.clone()).map_err(|e| e.to_string())?
|
||||||
|
} else {
|
||||||
|
Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(path) = path {
|
||||||
|
config = config.with_path(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
format_module_source(input, config.into())
|
||||||
|
.map(|result| result.into_code())
|
||||||
|
.map_err(|err| err.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
export interface Config {
|
||||||
|
indent_style?: "tab" | "space";
|
||||||
|
indent_width?: number;
|
||||||
|
line_width?: number;
|
||||||
|
line_ending?: "lf" | "crlf";
|
||||||
|
quote_style?: "single" | "double";
|
||||||
|
magic_trailing_comma?: "respect" | "ignore";
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "Config")]
|
||||||
|
pub type Config;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::{fs::File, io::Read, path::PathBuf, str::FromStr};
|
||||||
|
use testing_macros::fixture;
|
||||||
|
|
||||||
|
use crate::format;
|
||||||
|
|
||||||
|
#[fixture("test_data/**/*.py")]
|
||||||
|
#[fixture("test_data/**/*.pyi")]
|
||||||
|
fn it_works(input: PathBuf) {
|
||||||
|
// calc the expected file path
|
||||||
|
let input = input.clone();
|
||||||
|
let extect_path = input.to_string_lossy() + ".expect";
|
||||||
|
let extect_path = PathBuf::from_str(&extect_path).unwrap();
|
||||||
|
|
||||||
|
let mut actual = String::new();
|
||||||
|
File::open(&input).and_then(|mut file| file.read_to_string(&mut actual)).unwrap();
|
||||||
|
|
||||||
|
let mut expect = String::new();
|
||||||
|
File::open(extect_path).and_then(|mut file| file.read_to_string(&mut expect)).unwrap();
|
||||||
|
|
||||||
|
let actual = format(&actual, Some(input.to_string_lossy().to_string()), None).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(actual, expect);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
authors.workspace = true
|
||||||
|
description = "Config for ruff_fmt"
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
keywords.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
name = "ruff_fmt_config"
|
||||||
|
repository.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ruff_formatter = { workspace = true }
|
||||||
|
ruff_python_formatter = { workspace = true }
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
serde_json = { workspace = true, features = ["preserve_order"] }
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
use std::{
|
||||||
|
num::{NonZeroU16, NonZeroU8},
|
||||||
|
path::Path,
|
||||||
|
str::FromStr,
|
||||||
|
};
|
||||||
|
|
||||||
|
use ruff_formatter::{printer::LineEnding as RuffLineEnding, IndentStyle as RuffIndentStyle};
|
||||||
|
use ruff_python_formatter::{MagicTrailingComma, PyFormatOptions, QuoteStyle};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum IndentStyle {
|
||||||
|
Tab,
|
||||||
|
Space,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for IndentStyle {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"tab" => Ok(Self::Tab),
|
||||||
|
"space" => Ok(Self::Space),
|
||||||
|
_ => Err("Value not supported for IndentStyle"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<RuffIndentStyle> for IndentStyle {
|
||||||
|
fn from(value: RuffIndentStyle) -> Self {
|
||||||
|
match value {
|
||||||
|
RuffIndentStyle::Tab => Self::Tab,
|
||||||
|
RuffIndentStyle::Space => Self::Space,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<IndentStyle> for RuffIndentStyle {
|
||||||
|
fn from(value: IndentStyle) -> Self {
|
||||||
|
match value {
|
||||||
|
IndentStyle::Tab => Self::Tab,
|
||||||
|
IndentStyle::Space => Self::Space,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Deserialize, Serialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
pub enum LineEnding {
|
||||||
|
#[default]
|
||||||
|
Lf,
|
||||||
|
CrLf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LineEnding> for RuffLineEnding {
|
||||||
|
fn from(value: LineEnding) -> Self {
|
||||||
|
match value {
|
||||||
|
LineEnding::Lf => Self::LineFeed,
|
||||||
|
LineEnding::CrLf => Self::CarriageReturnLineFeed,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for LineEnding {
|
||||||
|
type Err = &'static str;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
match s {
|
||||||
|
"lf" => Ok(Self::Lf),
|
||||||
|
"crlf" => Ok(Self::CrLf),
|
||||||
|
_ => Err("Value not supported for LineEnding"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Deserialize, Serialize)]
|
||||||
|
pub struct Config {
|
||||||
|
#[serde(alias = "indentStyle")]
|
||||||
|
pub indent_style: Option<IndentStyle>,
|
||||||
|
#[serde(alias = "indentWidth")]
|
||||||
|
pub indent_width: Option<NonZeroU8>,
|
||||||
|
#[serde(alias = "lineWidth")]
|
||||||
|
pub line_width: Option<NonZeroU16>,
|
||||||
|
#[serde(alias = "lineEnding")]
|
||||||
|
pub line_ending: Option<LineEnding>,
|
||||||
|
|
||||||
|
pub quote_style: Option<QuoteStyle>,
|
||||||
|
pub magic_trailing_comma: Option<MagicTrailingComma>,
|
||||||
|
|
||||||
|
#[serde(skip)]
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn with_indent_style(mut self, indent_style: IndentStyle) -> Self {
|
||||||
|
self.indent_style = Some(indent_style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_indent_width(mut self, indent_width: NonZeroU8) -> Self {
|
||||||
|
self.indent_width = Some(indent_width);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_line_width(mut self, line_width: NonZeroU16) -> Self {
|
||||||
|
self.line_width = Some(line_width);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_line_ending(mut self, line_ending: LineEnding) -> Self {
|
||||||
|
self.line_ending = Some(line_ending);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_quote_style(mut self, quote_style: QuoteStyle) -> Self {
|
||||||
|
self.quote_style = Some(quote_style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_magic_trailing_comma(mut self, magic_trailing_comma: MagicTrailingComma) -> Self {
|
||||||
|
self.magic_trailing_comma = Some(magic_trailing_comma);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_path(mut self, path: String) -> Self {
|
||||||
|
self.path = path;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Config> for PyFormatOptions {
|
||||||
|
fn from(value: Config) -> Self {
|
||||||
|
let mut config = Self::from_extension(Path::new(&value.path));
|
||||||
|
|
||||||
|
if let Some(indent_style) = value.indent_style {
|
||||||
|
config = config.with_indent_style(indent_style.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(indent_width) = value.indent_width {
|
||||||
|
config = config.with_indent_width(indent_width.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_width) = value.line_width {
|
||||||
|
config = config.with_line_width(line_width.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_ending) = value.line_ending {
|
||||||
|
config = config.with_line_ending(line_ending.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(quote_style) = value.quote_style {
|
||||||
|
config = config.with_quote_style(quote_style);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(magic_trailing_comma) = value.magic_trailing_comma {
|
||||||
|
config = config.with_magic_trailing_comma(magic_trailing_comma);
|
||||||
|
}
|
||||||
|
|
||||||
|
config
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "unicode_names2"
|
||||||
|
version = "1.2.2"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
|
||||||
|
[package.metadata.wasm-pack.profile.release]
|
||||||
|
wasm-opt = ["-Os"]
|
||||||
|
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/// This is not correct, but the formatter does not change the output of Unicode.
|
||||||
|
/// Additionally, we do not require users to input the correct name.
|
||||||
|
/// However, this optimization reduces our wasm file size by a substantial 700kb, which is a significant benefit.
|
||||||
|
pub fn character(_name: &str) -> Option<char> {
|
||||||
|
Some('a')
|
||||||
|
}
|
||||||
18
frontend/src/common/prettier/plugins/web/common/Cargo.toml
Normal file
18
frontend/src/common/prettier/plugins/web/common/Cargo.toml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
[package]
|
||||||
|
name = "common"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
biome_formatter = { workspace = true, optional = true }
|
||||||
|
serde = { workspace = true, features = ["derive"], optional = true }
|
||||||
|
wasm-bindgen = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
126
frontend/src/common/prettier/plugins/web/common/src/lib.rs
Normal file
126
frontend/src/common/prettier/plugins/web/common/src/lib.rs
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
interface LayoutConfig {
|
||||||
|
indent_style?: "tab" | "space";
|
||||||
|
indent_width?: number;
|
||||||
|
line_width?: number;
|
||||||
|
line_ending?: "lf" | "crlf";
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serde", derive(Deserialize))]
|
||||||
|
#[derive(Clone, Default)]
|
||||||
|
pub struct LayoutConfig {
|
||||||
|
#[cfg_attr(feature = "serde", serde(alias = "indentStyle"))]
|
||||||
|
indent_style: Option<IndentStyle>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(alias = "indentWidth"))]
|
||||||
|
indent_width: Option<u8>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(alias = "lineWidth"))]
|
||||||
|
line_width: Option<u16>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(alias = "lineEnding"))]
|
||||||
|
line_ending: Option<LineEnding>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LayoutConfig {
|
||||||
|
pub fn fill_empty_with(mut self, other: &Self) -> Self {
|
||||||
|
if self.indent_style.is_none() {
|
||||||
|
self.indent_style = other.indent_style;
|
||||||
|
}
|
||||||
|
if self.indent_width.is_none() {
|
||||||
|
self.indent_width = other.indent_width;
|
||||||
|
}
|
||||||
|
if self.line_width.is_none() {
|
||||||
|
self.line_width = other.line_width;
|
||||||
|
}
|
||||||
|
if self.line_ending.is_none() {
|
||||||
|
self.line_ending = other.line_ending;
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_indent_style(mut self, indent_style: IndentStyle) -> Self {
|
||||||
|
self.indent_style = Some(indent_style);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_indent_width(mut self, indent_width: u8) -> Self {
|
||||||
|
self.indent_width = Some(indent_width);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_line_width(mut self, line_width: u16) -> Self {
|
||||||
|
self.line_width = Some(line_width);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_line_ending(mut self, line_ending: LineEnding) -> Self {
|
||||||
|
self.line_ending = Some(line_ending);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn indent_style(&self) -> Option<IndentStyle> {
|
||||||
|
self.indent_style
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn indent_width(&self) -> Option<u8> {
|
||||||
|
self.indent_width
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn line_width(&self) -> Option<u16> {
|
||||||
|
self.line_width
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn line_ending(&self) -> Option<LineEnding> {
|
||||||
|
self.line_ending
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serde", derive(Deserialize))]
|
||||||
|
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
pub enum IndentStyle {
|
||||||
|
Tab,
|
||||||
|
#[default]
|
||||||
|
Space,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndentStyle {
|
||||||
|
pub fn is_tab(&self) -> bool {
|
||||||
|
matches!(self, Self::Tab)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "biome_formatter")]
|
||||||
|
impl From<IndentStyle> for biome_formatter::IndentStyle {
|
||||||
|
fn from(style: IndentStyle) -> Self {
|
||||||
|
match style {
|
||||||
|
IndentStyle::Tab => biome_formatter::IndentStyle::Tab,
|
||||||
|
IndentStyle::Space => biome_formatter::IndentStyle::Space,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serde", derive(Deserialize))]
|
||||||
|
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
|
||||||
|
#[derive(Clone, Copy, Default)]
|
||||||
|
pub enum LineEnding {
|
||||||
|
#[default]
|
||||||
|
Lf,
|
||||||
|
Crlf,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "biome_formatter")]
|
||||||
|
impl From<LineEnding> for biome_formatter::LineEnding {
|
||||||
|
fn from(ending: LineEnding) -> Self {
|
||||||
|
match ending {
|
||||||
|
LineEnding::Lf => biome_formatter::LineEnding::Lf,
|
||||||
|
LineEnding::Crlf => biome_formatter::LineEnding::Crlf,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
155
frontend/src/common/prettier/plugins/web/index.ts
Normal file
155
frontend/src/common/prettier/plugins/web/index.ts
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/**
|
||||||
|
* Prettier Plugin for Web Languages formatting using web_fmt WebAssembly
|
||||||
|
*
|
||||||
|
* This plugin provides support for formatting multiple web languages using the web_fmt WASM implementation.
|
||||||
|
* web_fmt is a comprehensive formatter for web development supporting HTML, CSS, JavaScript, and JSON.
|
||||||
|
*/
|
||||||
|
import type { Plugin, Parser, Printer, ParserOptions } from 'prettier';
|
||||||
|
|
||||||
|
// Import the web_fmt WASM module
|
||||||
|
import webInit, { format } from './web_fmt_vite.js';
|
||||||
|
import { languages } from './languages';
|
||||||
|
|
||||||
|
const parserName = 'web-fmt';
|
||||||
|
|
||||||
|
// Parser configuration
|
||||||
|
const webParser: Parser<string> = {
|
||||||
|
astFormat: parserName,
|
||||||
|
parse: (text: string) => text,
|
||||||
|
locStart: () => 0,
|
||||||
|
locEnd: (text: string) => text.length,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize web_fmt WASM module
|
||||||
|
let processorInstance: any = null;
|
||||||
|
|
||||||
|
const getProcessorInstance = async () => {
|
||||||
|
if (!processorInstance) {
|
||||||
|
try {
|
||||||
|
await webInit();
|
||||||
|
processorInstance = { initialized: true };
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Failed to initialize web_fmt WASM module:', error);
|
||||||
|
processorInstance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return processorInstance;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper function to convert Prettier options to web_fmt config
|
||||||
|
function buildWebConfig(options: any): any {
|
||||||
|
const config: any = {};
|
||||||
|
|
||||||
|
// Basic layout options
|
||||||
|
if (options.useTabs !== undefined) {
|
||||||
|
config.indent_style = options.useTabs ? 'tab' : 'space';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.tabWidth !== undefined) {
|
||||||
|
config.indent_width = options.tabWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.printWidth !== undefined) {
|
||||||
|
config.line_width = options.printWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.endOfLine !== undefined) {
|
||||||
|
config.line_ending = options.endOfLine === 'crlf' ? 'crlf' : 'lf';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Script-specific options (for JS/TS)
|
||||||
|
if (options.singleQuote !== undefined) {
|
||||||
|
config.script = config.script || {};
|
||||||
|
config.script.quote_style = options.singleQuote ? 'single' : 'double';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.jsxSingleQuote !== undefined) {
|
||||||
|
config.script = config.script || {};
|
||||||
|
config.script.jsx_quote_style = options.jsxSingleQuote ? 'single' : 'double';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.trailingComma !== undefined) {
|
||||||
|
config.script = config.script || {};
|
||||||
|
config.script.trailing_comma = options.trailingComma;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.semi !== undefined) {
|
||||||
|
config.script = config.script || {};
|
||||||
|
config.script.semicolons = options.semi ? 'always' : 'as-needed';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.arrowParens !== undefined) {
|
||||||
|
config.script = config.script || {};
|
||||||
|
config.script.arrow_parentheses = options.arrowParens === 'always' ? 'always' : 'as-needed';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bracketSpacing !== undefined) {
|
||||||
|
config.script = config.script || {};
|
||||||
|
config.script.bracket_spacing = options.bracketSpacing;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bracketSameLine !== undefined) {
|
||||||
|
config.script = config.script || {};
|
||||||
|
config.script.bracket_same_line = options.bracketSameLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Printer configuration
|
||||||
|
const webPrinter: Printer<string> = {
|
||||||
|
// @ts-expect-error -- Support async printer like shell plugin
|
||||||
|
async print(path, options) {
|
||||||
|
const processor = await getProcessorInstance();
|
||||||
|
const text = (path as any).getValue ? (path as any).getValue() : path.node;
|
||||||
|
|
||||||
|
if (!processor) {
|
||||||
|
console.warn('web_fmt WASM not initialized, returning original text');
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const config = buildWebConfig(options);
|
||||||
|
|
||||||
|
// Format using web_fmt
|
||||||
|
const formatted = format(text, options.filename, config);
|
||||||
|
return formatted.trim();
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('web_fmt formatting failed:', error);
|
||||||
|
// Return original text if formatting fails
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Parser and printer exports
|
||||||
|
export const parsers = {
|
||||||
|
[parserName]: webParser,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const printers = {
|
||||||
|
[parserName]: webPrinter,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Configuration options - use standard Prettier options
|
||||||
|
const options: Plugin['options'] = {
|
||||||
|
filename: {
|
||||||
|
// since: '0.1.0',
|
||||||
|
category: 'Config',
|
||||||
|
type: 'string',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Custom filename to use for web_fmt processing (affects language detection)',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Plugin object
|
||||||
|
const webPlugin: Plugin = {
|
||||||
|
languages,
|
||||||
|
parsers,
|
||||||
|
printers,
|
||||||
|
options,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default webPlugin;
|
||||||
|
export { languages };
|
||||||
34
frontend/src/common/prettier/plugins/web/json_fmt/Cargo.toml
Normal file
34
frontend/src/common/prettier/plugins/web/json_fmt/Cargo.toml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[package]
|
||||||
|
description = "JSON formatter powered by WASM ported from Biome"
|
||||||
|
keywords = ["wasm", "formatter", "json", "biome"]
|
||||||
|
name = "json_fmt"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
publish = true
|
||||||
|
repository.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["main"]
|
||||||
|
main = ["wasm-bindgen", "serde-wasm-bindgen", "common/wasm-bindgen"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common = { workspace = true, features = ["biome_formatter", "serde"] }
|
||||||
|
|
||||||
|
biome_formatter = { workspace = true }
|
||||||
|
biome_json_formatter = { workspace = true }
|
||||||
|
biome_json_parser = { workspace = true }
|
||||||
|
biome_json_syntax = { workspace = true }
|
||||||
|
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
serde-wasm-bindgen = { workspace = true, optional = true }
|
||||||
|
serde_json = { workspace = true, features = ["preserve_order"] }
|
||||||
|
wasm-bindgen = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
*.tgz
|
||||||
|
jsr.jsonc
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./json_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./json_fmt_bg.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = { module_or_path: fs.readFile(wasm) }) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./json_fmt.js";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./json_fmt.js";
|
||||||
|
import wasm from "./json_fmt_bg.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = { module_or_path: wasm }) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./json_fmt.js";
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
cd $(dirname $0)/..
|
||||||
|
crates_dir=$(pwd)
|
||||||
|
|
||||||
|
cd ../..
|
||||||
|
wasm-pack build --target=web --scope=wasm-fmt crates/json_fmt
|
||||||
|
|
||||||
|
cd $crates_dir
|
||||||
|
|
||||||
|
cp -R ./extra/. ./pkg/
|
||||||
|
|
||||||
|
./scripts/package.mjs ./pkg/package.json
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import process from "node:process";
|
||||||
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
const pkg_path = path.resolve(process.cwd(), process.argv[2]);
|
||||||
|
const pkg_text = fs.readFileSync(pkg_path, { encoding: "utf-8" });
|
||||||
|
const pkg_json = JSON.parse(pkg_text);
|
||||||
|
|
||||||
|
delete pkg_json.files;
|
||||||
|
|
||||||
|
pkg_json.main = pkg_json.module;
|
||||||
|
pkg_json.type = "module";
|
||||||
|
pkg_json.publishConfig = {
|
||||||
|
access: "public",
|
||||||
|
};
|
||||||
|
pkg_json.exports = {
|
||||||
|
".": {
|
||||||
|
types: "./json_fmt.d.ts",
|
||||||
|
node: "./json_fmt_node.js",
|
||||||
|
default: "./json_fmt.js",
|
||||||
|
},
|
||||||
|
"./vite": {
|
||||||
|
types: "./json_fmt.d.ts",
|
||||||
|
default: "./json_fmt_vite.js",
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json",
|
||||||
|
"./*": "./*",
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(pkg_path, JSON.stringify(pkg_json, null, 4));
|
||||||
|
|
||||||
|
// JSR
|
||||||
|
|
||||||
|
const jsr_path = path.resolve(pkg_path, "..", "jsr.jsonc");
|
||||||
|
pkg_json.name = "@fmt/json-fmt";
|
||||||
|
pkg_json.exports = "./json_fmt.js";
|
||||||
|
pkg_json.exclude = ["!**", "*.tgz"];
|
||||||
|
fs.writeFileSync(jsr_path, JSON.stringify(pkg_json, null, 4));
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
use biome_formatter::LineWidthFromIntError;
|
||||||
|
use biome_json_formatter::context::JsonFormatOptions;
|
||||||
|
use common::LayoutConfig;
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"export type Config = LayoutConfig;"#;
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default, Clone)]
|
||||||
|
#[serde(transparent)]
|
||||||
|
pub struct JsonConfig(LayoutConfig);
|
||||||
|
|
||||||
|
impl From<LayoutConfig> for JsonConfig {
|
||||||
|
fn from(config: LayoutConfig) -> Self {
|
||||||
|
Self(config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JsonConfig {
|
||||||
|
pub fn with_line_width(mut self, line_width: u16) -> Self {
|
||||||
|
self.0 = self.0.with_line_width(line_width);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<JsonConfig> for JsonFormatOptions {
|
||||||
|
type Error = String;
|
||||||
|
|
||||||
|
fn try_from(value: JsonConfig) -> Result<Self, Self::Error> {
|
||||||
|
let mut option = JsonFormatOptions::default();
|
||||||
|
|
||||||
|
if let Some(indent_style) = value.0.indent_style() {
|
||||||
|
option = option.with_indent_style(indent_style.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(indent_width) = value.0.indent_width() {
|
||||||
|
option = option.with_indent_width(indent_width.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_ending) = value.0.line_ending() {
|
||||||
|
option = option.with_line_ending(line_ending.into());
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(line_width) = value.0.line_width() {
|
||||||
|
let line_width =
|
||||||
|
line_width.try_into().map_err(|e: LineWidthFromIntError| e.to_string())?;
|
||||||
|
|
||||||
|
option = option.with_line_width(line_width);
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(option)
|
||||||
|
}
|
||||||
|
}
|
||||||
41
frontend/src/common/prettier/plugins/web/json_fmt/src/lib.rs
Normal file
41
frontend/src/common/prettier/plugins/web/json_fmt/src/lib.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
mod config;
|
||||||
|
|
||||||
|
use biome_formatter::Printed;
|
||||||
|
use biome_json_formatter::format_node;
|
||||||
|
use biome_json_parser::{parse_json, JsonParserOptions};
|
||||||
|
|
||||||
|
use config::JsonConfig;
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "Config")]
|
||||||
|
pub type Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "wasm-bindgen")]
|
||||||
|
#[wasm_bindgen(skip_typescript)]
|
||||||
|
pub fn format(src: &str, config: Option<Config>) -> Result<String, String> {
|
||||||
|
let config = config
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.clone()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|op| op.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
format_json_with_config(src, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format_json_with_config(src: &str, config: JsonConfig) -> Result<String, String> {
|
||||||
|
let options = JsonParserOptions::default().with_allow_comments().with_allow_trailing_commas();
|
||||||
|
let parse = parse_json(src, options);
|
||||||
|
|
||||||
|
let options = config.try_into()?;
|
||||||
|
|
||||||
|
format_node(options, &parse.syntax())
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.print()
|
||||||
|
.map(Printed::into_code)
|
||||||
|
.map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
130
frontend/src/common/prettier/plugins/web/languages.ts
Normal file
130
frontend/src/common/prettier/plugins/web/languages.ts
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
export const languages = [
|
||||||
|
// HTML and template languages
|
||||||
|
{
|
||||||
|
name: "HTML",
|
||||||
|
parsers: ["html"],
|
||||||
|
extensions: [".html", ".htm"],
|
||||||
|
filenames: ["*.html", "*.htm"],
|
||||||
|
tmScope: "text.html.basic",
|
||||||
|
aceMode: "html",
|
||||||
|
codemirrorMode: "htmlmixed",
|
||||||
|
linguistLanguageId: 172,
|
||||||
|
vscodeLanguageIds: ["html"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Vue",
|
||||||
|
parsers: ["vue"],
|
||||||
|
extensions: [".vue"],
|
||||||
|
filenames: ["*.vue"],
|
||||||
|
tmScope: "text.html.vue",
|
||||||
|
aceMode: "html",
|
||||||
|
codemirrorMode: "vue",
|
||||||
|
linguistLanguageId: 391,
|
||||||
|
vscodeLanguageIds: ["vue"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Svelte",
|
||||||
|
parsers: ["svelte"],
|
||||||
|
extensions: [".svelte"],
|
||||||
|
filenames: ["*.svelte"],
|
||||||
|
tmScope: "source.svelte",
|
||||||
|
aceMode: "html",
|
||||||
|
codemirrorMode: "htmlmixed",
|
||||||
|
linguistLanguageId: 377,
|
||||||
|
vscodeLanguageIds: ["svelte"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Astro",
|
||||||
|
parsers: ["astro"],
|
||||||
|
extensions: [".astro"],
|
||||||
|
filenames: ["*.astro"],
|
||||||
|
tmScope: "source.astro",
|
||||||
|
aceMode: "html",
|
||||||
|
codemirrorMode: "htmlmixed",
|
||||||
|
linguistLanguageId: 578,
|
||||||
|
vscodeLanguageIds: ["astro"]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Stylesheet languages
|
||||||
|
{
|
||||||
|
name: "CSS",
|
||||||
|
parsers: ["css"],
|
||||||
|
extensions: [".css"],
|
||||||
|
filenames: ["*.css"],
|
||||||
|
tmScope: "source.css",
|
||||||
|
aceMode: "css",
|
||||||
|
codemirrorMode: "css",
|
||||||
|
linguistLanguageId: 50,
|
||||||
|
vscodeLanguageIds: ["css"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "SCSS",
|
||||||
|
parsers: ["scss"],
|
||||||
|
extensions: [".scss"],
|
||||||
|
filenames: ["*.scss"],
|
||||||
|
tmScope: "source.css.scss",
|
||||||
|
aceMode: "scss",
|
||||||
|
codemirrorMode: "css",
|
||||||
|
linguistLanguageId: 329,
|
||||||
|
vscodeLanguageIds: ["scss"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Sass",
|
||||||
|
parsers: ["sass"],
|
||||||
|
extensions: [".sass"],
|
||||||
|
filenames: ["*.sass"],
|
||||||
|
tmScope: "source.sass",
|
||||||
|
aceMode: "sass",
|
||||||
|
codemirrorMode: "sass",
|
||||||
|
linguistLanguageId: 207,
|
||||||
|
vscodeLanguageIds: ["sass"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Less",
|
||||||
|
parsers: ["less"],
|
||||||
|
extensions: [".less"],
|
||||||
|
filenames: ["*.less"],
|
||||||
|
tmScope: "source.css.less",
|
||||||
|
aceMode: "less",
|
||||||
|
codemirrorMode: "css",
|
||||||
|
linguistLanguageId: 198,
|
||||||
|
vscodeLanguageIds: ["less"]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Script languages
|
||||||
|
{
|
||||||
|
name: "JavaScript",
|
||||||
|
parsers: ["js"],
|
||||||
|
extensions: [".js", ".mjs", ".cjs", ".jsx"],
|
||||||
|
filenames: ["*.js", "*.mjs", "*.cjs", "*.jsx"],
|
||||||
|
tmScope: "source.js",
|
||||||
|
aceMode: "javascript",
|
||||||
|
codemirrorMode: "javascript",
|
||||||
|
linguistLanguageId: 183,
|
||||||
|
vscodeLanguageIds: ["javascript"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "TypeScript",
|
||||||
|
parsers: ["ts"],
|
||||||
|
extensions: [".ts", ".tsx", ".cts", ".mts"],
|
||||||
|
filenames: ["*.ts", "*.tsx", "*.cts", "*.mts"],
|
||||||
|
tmScope: "source.ts",
|
||||||
|
aceMode: "typescript",
|
||||||
|
codemirrorMode: "javascript",
|
||||||
|
linguistLanguageId: 378,
|
||||||
|
vscodeLanguageIds: ["typescript"]
|
||||||
|
},
|
||||||
|
|
||||||
|
// Data languages
|
||||||
|
{
|
||||||
|
name: "JSON",
|
||||||
|
parsers: ["json"],
|
||||||
|
extensions: [".json", ".jsonc"],
|
||||||
|
filenames: ["*.json", "*.jsonc", ".babelrc", ".eslintrc", "tsconfig.json"],
|
||||||
|
tmScope: "source.json",
|
||||||
|
aceMode: "json",
|
||||||
|
codemirrorMode: "javascript",
|
||||||
|
linguistLanguageId: 174,
|
||||||
|
vscodeLanguageIds: ["json", "jsonc"]
|
||||||
|
}
|
||||||
|
];
|
||||||
90
frontend/src/common/prettier/plugins/web/web_fmt.d.ts
vendored
Normal file
90
frontend/src/common/prettier/plugins/web/web_fmt.d.ts
vendored
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export function format_json(src: string, config?: JsonConfig): string;
|
||||||
|
export function format_markup(src: string, filename: string, config?: MarkupConfig): string;
|
||||||
|
export function format_script(src: string, filename: string, config?: ScriptConfig): string;
|
||||||
|
export function format_style(src: string, filename: string, config?: StyleConfig): string;
|
||||||
|
export function format(src: string, filename: string, config?: Config): string;
|
||||||
|
export type JsonConfig = LayoutConfig;
|
||||||
|
|
||||||
|
|
||||||
|
export interface MarkupConfig extends LayoutConfig {
|
||||||
|
/**
|
||||||
|
* See {@link https://github.com/g-plane/markup_fmt/blob/main/docs/config.md}
|
||||||
|
*/
|
||||||
|
[other: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface ScriptConfig extends LayoutConfig {
|
||||||
|
quote_style?: "double" | "single";
|
||||||
|
jsx_quote_style?: "double" | "single";
|
||||||
|
quote_properties?: "preserve" | "as-needed";
|
||||||
|
trailing_comma?: "es5" | "all" | "none";
|
||||||
|
semicolons?: "always" | "as-needed";
|
||||||
|
arrow_parentheses?: "always" | "as-needed";
|
||||||
|
bracket_spacing?: boolean;
|
||||||
|
bracket_same_line?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface StyleConfig extends LayoutConfig {
|
||||||
|
/**
|
||||||
|
* See {@link https://github.com/g-plane/malva/blob/main/docs/config.md}
|
||||||
|
*/
|
||||||
|
[other: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export interface Config extends LayoutConfig {
|
||||||
|
markup?: MarkupConfig;
|
||||||
|
script?: ScriptConfig;
|
||||||
|
style?: StyleConfig;
|
||||||
|
json?: JsonConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
interface LayoutConfig {
|
||||||
|
indent_style?: "tab" | "space";
|
||||||
|
indent_width?: number;
|
||||||
|
line_width?: number;
|
||||||
|
line_ending?: "lf" | "crlf";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
||||||
|
|
||||||
|
export interface InitOutput {
|
||||||
|
readonly memory: WebAssembly.Memory;
|
||||||
|
readonly format_json: (a: number, b: number, c: number, d: number) => void;
|
||||||
|
readonly format_markup: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
readonly format_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
readonly format_style: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
readonly format: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
readonly __wbindgen_export_0: (a: number, b: number) => number;
|
||||||
|
readonly __wbindgen_export_1: (a: number, b: number, c: number, d: number) => number;
|
||||||
|
readonly __wbindgen_export_2: (a: number) => void;
|
||||||
|
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||||
|
readonly __wbindgen_export_3: (a: number, b: number, c: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
||||||
|
/**
|
||||||
|
* Instantiates the given `module`, which can either be bytes or
|
||||||
|
* a precompiled `WebAssembly.Module`.
|
||||||
|
*
|
||||||
|
* @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
|
||||||
|
*
|
||||||
|
* @returns {InitOutput}
|
||||||
|
*/
|
||||||
|
export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
||||||
|
* for everything else, calls `WebAssembly.instantiate` directly.
|
||||||
|
*
|
||||||
|
* @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
|
||||||
|
*
|
||||||
|
* @returns {Promise<InitOutput>}
|
||||||
|
*/
|
||||||
|
export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;
|
||||||
673
frontend/src/common/prettier/plugins/web/web_fmt.js
Normal file
673
frontend/src/common/prettier/plugins/web/web_fmt.js
Normal file
@@ -0,0 +1,673 @@
|
|||||||
|
let wasm;
|
||||||
|
|
||||||
|
const heap = new Array(128).fill(undefined);
|
||||||
|
|
||||||
|
heap.push(undefined, null, true, false);
|
||||||
|
|
||||||
|
function getObject(idx) { return heap[idx]; }
|
||||||
|
|
||||||
|
let WASM_VECTOR_LEN = 0;
|
||||||
|
|
||||||
|
let cachedUint8ArrayMemory0 = null;
|
||||||
|
|
||||||
|
function getUint8ArrayMemory0() {
|
||||||
|
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
||||||
|
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
||||||
|
}
|
||||||
|
return cachedUint8ArrayMemory0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
|
||||||
|
|
||||||
|
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||||
|
? function (arg, view) {
|
||||||
|
return cachedTextEncoder.encodeInto(arg, view);
|
||||||
|
}
|
||||||
|
: function (arg, view) {
|
||||||
|
const buf = cachedTextEncoder.encode(arg);
|
||||||
|
view.set(buf);
|
||||||
|
return {
|
||||||
|
read: arg.length,
|
||||||
|
written: buf.length
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
function passStringToWasm0(arg, malloc, realloc) {
|
||||||
|
|
||||||
|
if (realloc === undefined) {
|
||||||
|
const buf = cachedTextEncoder.encode(arg);
|
||||||
|
const ptr = malloc(buf.length, 1) >>> 0;
|
||||||
|
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||||
|
WASM_VECTOR_LEN = buf.length;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
let len = arg.length;
|
||||||
|
let ptr = malloc(len, 1) >>> 0;
|
||||||
|
|
||||||
|
const mem = getUint8ArrayMemory0();
|
||||||
|
|
||||||
|
let offset = 0;
|
||||||
|
|
||||||
|
for (; offset < len; offset++) {
|
||||||
|
const code = arg.charCodeAt(offset);
|
||||||
|
if (code > 0x7F) break;
|
||||||
|
mem[ptr + offset] = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset !== len) {
|
||||||
|
if (offset !== 0) {
|
||||||
|
arg = arg.slice(offset);
|
||||||
|
}
|
||||||
|
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
||||||
|
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
||||||
|
const ret = encodeString(arg, view);
|
||||||
|
|
||||||
|
offset += ret.written;
|
||||||
|
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
WASM_VECTOR_LEN = offset;
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cachedDataViewMemory0 = null;
|
||||||
|
|
||||||
|
function getDataViewMemory0() {
|
||||||
|
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
||||||
|
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
||||||
|
}
|
||||||
|
return cachedDataViewMemory0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let heap_next = heap.length;
|
||||||
|
|
||||||
|
function addHeapObject(obj) {
|
||||||
|
if (heap_next === heap.length) heap.push(heap.length + 1);
|
||||||
|
const idx = heap_next;
|
||||||
|
heap_next = heap[idx];
|
||||||
|
|
||||||
|
heap[idx] = obj;
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleError(f, args) {
|
||||||
|
try {
|
||||||
|
return f.apply(this, args);
|
||||||
|
} catch (e) {
|
||||||
|
wasm.__wbindgen_export_2(addHeapObject(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isLikeNone(x) {
|
||||||
|
return x === undefined || x === null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function debugString(val) {
|
||||||
|
// primitive types
|
||||||
|
const type = typeof val;
|
||||||
|
if (type == 'number' || type == 'boolean' || val == null) {
|
||||||
|
return `${val}`;
|
||||||
|
}
|
||||||
|
if (type == 'string') {
|
||||||
|
return `"${val}"`;
|
||||||
|
}
|
||||||
|
if (type == 'symbol') {
|
||||||
|
const description = val.description;
|
||||||
|
if (description == null) {
|
||||||
|
return 'Symbol';
|
||||||
|
} else {
|
||||||
|
return `Symbol(${description})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (type == 'function') {
|
||||||
|
const name = val.name;
|
||||||
|
if (typeof name == 'string' && name.length > 0) {
|
||||||
|
return `Function(${name})`;
|
||||||
|
} else {
|
||||||
|
return 'Function';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// objects
|
||||||
|
if (Array.isArray(val)) {
|
||||||
|
const length = val.length;
|
||||||
|
let debug = '[';
|
||||||
|
if (length > 0) {
|
||||||
|
debug += debugString(val[0]);
|
||||||
|
}
|
||||||
|
for(let i = 1; i < length; i++) {
|
||||||
|
debug += ', ' + debugString(val[i]);
|
||||||
|
}
|
||||||
|
debug += ']';
|
||||||
|
return debug;
|
||||||
|
}
|
||||||
|
// Test for built-in
|
||||||
|
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||||
|
let className;
|
||||||
|
if (builtInMatches && builtInMatches.length > 1) {
|
||||||
|
className = builtInMatches[1];
|
||||||
|
} else {
|
||||||
|
// Failed to match the standard '[object ClassName]'
|
||||||
|
return toString.call(val);
|
||||||
|
}
|
||||||
|
if (className == 'Object') {
|
||||||
|
// we're a user defined class or Object
|
||||||
|
// JSON.stringify avoids problems with cycles, and is generally much
|
||||||
|
// easier than looping through ownProperties of `val`.
|
||||||
|
try {
|
||||||
|
return 'Object(' + JSON.stringify(val) + ')';
|
||||||
|
} catch (_) {
|
||||||
|
return 'Object';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// errors
|
||||||
|
if (val instanceof Error) {
|
||||||
|
return `${val.name}: ${val.message}\n${val.stack}`;
|
||||||
|
}
|
||||||
|
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||||
|
return className;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||||
|
|
||||||
|
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
|
||||||
|
|
||||||
|
function getStringFromWasm0(ptr, len) {
|
||||||
|
ptr = ptr >>> 0;
|
||||||
|
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||||
|
}
|
||||||
|
|
||||||
|
function dropObject(idx) {
|
||||||
|
if (idx < 132) return;
|
||||||
|
heap[idx] = heap_next;
|
||||||
|
heap_next = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
function takeObject(idx) {
|
||||||
|
const ret = getObject(idx);
|
||||||
|
dropObject(idx);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param {string} src
|
||||||
|
* @param {JsonConfig | undefined} [config]
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function format_json(src, config) {
|
||||||
|
let deferred3_0;
|
||||||
|
let deferred3_1;
|
||||||
|
try {
|
||||||
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||||
|
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
wasm.format_json(retptr, ptr0, len0, isLikeNone(config) ? 0 : addHeapObject(config));
|
||||||
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||||
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||||
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||||
|
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
||||||
|
var ptr2 = r0;
|
||||||
|
var len2 = r1;
|
||||||
|
if (r3) {
|
||||||
|
ptr2 = 0; len2 = 0;
|
||||||
|
throw takeObject(r2);
|
||||||
|
}
|
||||||
|
deferred3_0 = ptr2;
|
||||||
|
deferred3_1 = len2;
|
||||||
|
return getStringFromWasm0(ptr2, len2);
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||||
|
wasm.__wbindgen_export_3(deferred3_0, deferred3_1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} src
|
||||||
|
* @param {string} filename
|
||||||
|
* @param {MarkupConfig | undefined} [config]
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function format_markup(src, filename, config) {
|
||||||
|
let deferred4_0;
|
||||||
|
let deferred4_1;
|
||||||
|
try {
|
||||||
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||||
|
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
const ptr1 = passStringToWasm0(filename, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
wasm.format_markup(retptr, ptr0, len0, ptr1, len1, isLikeNone(config) ? 0 : addHeapObject(config));
|
||||||
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||||
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||||
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||||
|
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
||||||
|
var ptr3 = r0;
|
||||||
|
var len3 = r1;
|
||||||
|
if (r3) {
|
||||||
|
ptr3 = 0; len3 = 0;
|
||||||
|
throw takeObject(r2);
|
||||||
|
}
|
||||||
|
deferred4_0 = ptr3;
|
||||||
|
deferred4_1 = len3;
|
||||||
|
return getStringFromWasm0(ptr3, len3);
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||||
|
wasm.__wbindgen_export_3(deferred4_0, deferred4_1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} src
|
||||||
|
* @param {string} filename
|
||||||
|
* @param {ScriptConfig | undefined} [config]
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function format_script(src, filename, config) {
|
||||||
|
let deferred4_0;
|
||||||
|
let deferred4_1;
|
||||||
|
try {
|
||||||
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||||
|
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
const ptr1 = passStringToWasm0(filename, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
wasm.format_script(retptr, ptr0, len0, ptr1, len1, isLikeNone(config) ? 0 : addHeapObject(config));
|
||||||
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||||
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||||
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||||
|
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
||||||
|
var ptr3 = r0;
|
||||||
|
var len3 = r1;
|
||||||
|
if (r3) {
|
||||||
|
ptr3 = 0; len3 = 0;
|
||||||
|
throw takeObject(r2);
|
||||||
|
}
|
||||||
|
deferred4_0 = ptr3;
|
||||||
|
deferred4_1 = len3;
|
||||||
|
return getStringFromWasm0(ptr3, len3);
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||||
|
wasm.__wbindgen_export_3(deferred4_0, deferred4_1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} src
|
||||||
|
* @param {string} filename
|
||||||
|
* @param {StyleConfig | undefined} [config]
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function format_style(src, filename, config) {
|
||||||
|
let deferred4_0;
|
||||||
|
let deferred4_1;
|
||||||
|
try {
|
||||||
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||||
|
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
const ptr1 = passStringToWasm0(filename, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
wasm.format_style(retptr, ptr0, len0, ptr1, len1, isLikeNone(config) ? 0 : addHeapObject(config));
|
||||||
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||||
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||||
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||||
|
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
||||||
|
var ptr3 = r0;
|
||||||
|
var len3 = r1;
|
||||||
|
if (r3) {
|
||||||
|
ptr3 = 0; len3 = 0;
|
||||||
|
throw takeObject(r2);
|
||||||
|
}
|
||||||
|
deferred4_0 = ptr3;
|
||||||
|
deferred4_1 = len3;
|
||||||
|
return getStringFromWasm0(ptr3, len3);
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||||
|
wasm.__wbindgen_export_3(deferred4_0, deferred4_1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} src
|
||||||
|
* @param {string} filename
|
||||||
|
* @param {Config | undefined} [config]
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
export function format(src, filename, config) {
|
||||||
|
let deferred4_0;
|
||||||
|
let deferred4_1;
|
||||||
|
try {
|
||||||
|
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
||||||
|
const ptr0 = passStringToWasm0(src, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len0 = WASM_VECTOR_LEN;
|
||||||
|
const ptr1 = passStringToWasm0(filename, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
wasm.format(retptr, ptr0, len0, ptr1, len1, isLikeNone(config) ? 0 : addHeapObject(config));
|
||||||
|
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
||||||
|
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
||||||
|
var r2 = getDataViewMemory0().getInt32(retptr + 4 * 2, true);
|
||||||
|
var r3 = getDataViewMemory0().getInt32(retptr + 4 * 3, true);
|
||||||
|
var ptr3 = r0;
|
||||||
|
var len3 = r1;
|
||||||
|
if (r3) {
|
||||||
|
ptr3 = 0; len3 = 0;
|
||||||
|
throw takeObject(r2);
|
||||||
|
}
|
||||||
|
deferred4_0 = ptr3;
|
||||||
|
deferred4_1 = len3;
|
||||||
|
return getStringFromWasm0(ptr3, len3);
|
||||||
|
} finally {
|
||||||
|
wasm.__wbindgen_add_to_stack_pointer(16);
|
||||||
|
wasm.__wbindgen_export_3(deferred4_0, deferred4_1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function __wbg_load(module, imports) {
|
||||||
|
if (typeof Response === 'function' && module instanceof Response) {
|
||||||
|
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||||
|
try {
|
||||||
|
return await WebAssembly.instantiateStreaming(module, imports);
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||||
|
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bytes = await module.arrayBuffer();
|
||||||
|
return await WebAssembly.instantiate(bytes, imports);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const instance = await WebAssembly.instantiate(module, imports);
|
||||||
|
|
||||||
|
if (instance instanceof WebAssembly.Instance) {
|
||||||
|
return { instance, module };
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_get_imports() {
|
||||||
|
const imports = {};
|
||||||
|
imports.wbg = {};
|
||||||
|
imports.wbg.__wbg_String_8f0eb39a4a4c2f66 = function(arg0, arg1) {
|
||||||
|
const ret = String(getObject(arg1));
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_buffer_61b7ce01341d7f88 = function(arg0) {
|
||||||
|
const ret = getObject(arg0).buffer;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_call_b0d8e36992d9900d = function() { return handleError(function (arg0, arg1) {
|
||||||
|
const ret = getObject(arg0).call(getObject(arg1));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_done_f22c1561fa919baa = function(arg0) {
|
||||||
|
const ret = getObject(arg0).done;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_entries_4f2bb9b0d701c0f6 = function(arg0) {
|
||||||
|
const ret = Object.entries(getObject(arg0));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_get_9aa3dff3f0266054 = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0)[arg1 >>> 0];
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_get_bbccf8970793c087 = function() { return handleError(function (arg0, arg1) {
|
||||||
|
const ret = Reflect.get(getObject(arg0), getObject(arg1));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_getwithrefkey_1dc361bd10053bfe = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0)[getObject(arg1)];
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_ArrayBuffer_670ddde44cdb2602 = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = getObject(arg0) instanceof ArrayBuffer;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_Map_98ecb30afec5acdb = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = getObject(arg0) instanceof Map;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_instanceof_Uint8Array_28af5bc19d6acad8 = function(arg0) {
|
||||||
|
let result;
|
||||||
|
try {
|
||||||
|
result = getObject(arg0) instanceof Uint8Array;
|
||||||
|
} catch (_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
const ret = result;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_isArray_1ba11a930108ec51 = function(arg0) {
|
||||||
|
const ret = Array.isArray(getObject(arg0));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_isSafeInteger_12f5549b2fca23f4 = function(arg0) {
|
||||||
|
const ret = Number.isSafeInteger(getObject(arg0));
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_iterator_23604bb983791576 = function() {
|
||||||
|
const ret = Symbol.iterator;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_length_65d1cd11729ced11 = function(arg0) {
|
||||||
|
const ret = getObject(arg0).length;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_length_d65cf0786bfc5739 = function(arg0) {
|
||||||
|
const ret = getObject(arg0).length;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_new_3ff5b33b1ce712df = function(arg0) {
|
||||||
|
const ret = new Uint8Array(getObject(arg0));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_next_01dd9234a5bf6d05 = function() { return handleError(function (arg0) {
|
||||||
|
const ret = getObject(arg0).next();
|
||||||
|
return addHeapObject(ret);
|
||||||
|
}, arguments) };
|
||||||
|
imports.wbg.__wbg_next_137428deb98342b0 = function(arg0) {
|
||||||
|
const ret = getObject(arg0).next;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_set_23d69db4e5c66a6e = function(arg0, arg1, arg2) {
|
||||||
|
getObject(arg0).set(getObject(arg1), arg2 >>> 0);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbg_value_4c32fd138a88eee2 = function(arg0) {
|
||||||
|
const ret = getObject(arg0).value;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_as_number = function(arg0) {
|
||||||
|
const ret = +getObject(arg0);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_bigint_from_i64 = function(arg0) {
|
||||||
|
const ret = arg0;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) {
|
||||||
|
const ret = BigInt.asUintN(64, arg0);
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_bigint_get_as_i64 = function(arg0, arg1) {
|
||||||
|
const v = getObject(arg1);
|
||||||
|
const ret = typeof(v) === 'bigint' ? v : undefined;
|
||||||
|
getDataViewMemory0().setBigInt64(arg0 + 8 * 1, isLikeNone(ret) ? BigInt(0) : ret, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_boolean_get = function(arg0) {
|
||||||
|
const v = getObject(arg0);
|
||||||
|
const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||||
|
const ret = debugString(getObject(arg1));
|
||||||
|
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
const len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_error_new = function(arg0, arg1) {
|
||||||
|
const ret = new Error(getStringFromWasm0(arg0, arg1));
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_in = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0) in getObject(arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_bigint = function(arg0) {
|
||||||
|
const ret = typeof(getObject(arg0)) === 'bigint';
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_function = function(arg0) {
|
||||||
|
const ret = typeof(getObject(arg0)) === 'function';
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_object = function(arg0) {
|
||||||
|
const val = getObject(arg0);
|
||||||
|
const ret = typeof(val) === 'object' && val !== null;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_string = function(arg0) {
|
||||||
|
const ret = typeof(getObject(arg0)) === 'string';
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_is_undefined = function(arg0) {
|
||||||
|
const ret = getObject(arg0) === undefined;
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0) === getObject(arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) {
|
||||||
|
const ret = getObject(arg0) == getObject(arg1);
|
||||||
|
return ret;
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_memory = function() {
|
||||||
|
const ret = wasm.memory;
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_number_get = function(arg0, arg1) {
|
||||||
|
const obj = getObject(arg1);
|
||||||
|
const ret = typeof(obj) === 'number' ? obj : undefined;
|
||||||
|
getDataViewMemory0().setFloat64(arg0 + 8 * 1, isLikeNone(ret) ? 0 : ret, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, !isLikeNone(ret), true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
|
||||||
|
const ret = getObject(arg0);
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
||||||
|
takeObject(arg0);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
|
||||||
|
const obj = getObject(arg1);
|
||||||
|
const ret = typeof(obj) === 'string' ? obj : undefined;
|
||||||
|
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1);
|
||||||
|
var len1 = WASM_VECTOR_LEN;
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||||
|
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
||||||
|
const ret = getStringFromWasm0(arg0, arg1);
|
||||||
|
return addHeapObject(ret);
|
||||||
|
};
|
||||||
|
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||||
|
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||||
|
};
|
||||||
|
|
||||||
|
return imports;
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_init_memory(imports, memory) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function __wbg_finalize_init(instance, module) {
|
||||||
|
wasm = instance.exports;
|
||||||
|
__wbg_init.__wbindgen_wasm_module = module;
|
||||||
|
cachedDataViewMemory0 = null;
|
||||||
|
cachedUint8ArrayMemory0 = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return wasm;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSync(module) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
if (Object.getPrototypeOf(module) === Object.prototype) {
|
||||||
|
({module} = module)
|
||||||
|
} else {
|
||||||
|
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const imports = __wbg_get_imports();
|
||||||
|
|
||||||
|
__wbg_init_memory(imports);
|
||||||
|
|
||||||
|
if (!(module instanceof WebAssembly.Module)) {
|
||||||
|
module = new WebAssembly.Module(module);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = new WebAssembly.Instance(module, imports);
|
||||||
|
|
||||||
|
return __wbg_finalize_init(instance, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function __wbg_init(module_or_path) {
|
||||||
|
if (wasm !== undefined) return wasm;
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof module_or_path !== 'undefined') {
|
||||||
|
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
||||||
|
({module_or_path} = module_or_path)
|
||||||
|
} else {
|
||||||
|
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof module_or_path === 'undefined') {
|
||||||
|
module_or_path = new URL('web_fmt_bg.wasm', import.meta.url);
|
||||||
|
}
|
||||||
|
const imports = __wbg_get_imports();
|
||||||
|
|
||||||
|
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
||||||
|
module_or_path = fetch(module_or_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
__wbg_init_memory(imports);
|
||||||
|
|
||||||
|
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
||||||
|
|
||||||
|
return __wbg_finalize_init(instance, module);
|
||||||
|
}
|
||||||
|
|
||||||
|
export { initSync };
|
||||||
|
export default __wbg_init;
|
||||||
32
frontend/src/common/prettier/plugins/web/web_fmt/Cargo.toml
Normal file
32
frontend/src/common/prettier/plugins/web/web_fmt/Cargo.toml
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
[package]
|
||||||
|
description = "a formatter for web development powered by WASM"
|
||||||
|
keywords = ["wasm", "formatter", "html", "css", "javascript"]
|
||||||
|
name = "web_fmt"
|
||||||
|
|
||||||
|
authors.workspace = true
|
||||||
|
edition.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
license.workspace = true
|
||||||
|
publish = true
|
||||||
|
repository.workspace = true
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common = { workspace = true, features = [
|
||||||
|
"biome_formatter",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
|
] }
|
||||||
|
|
||||||
|
biome_fmt = { workspace = true, default-features = false }
|
||||||
|
json_fmt = { workspace = true, default-features = false }
|
||||||
|
malva = { workspace = true, features = ["config_serde"] }
|
||||||
|
markup_fmt = { workspace = true, features = ["config_serde"] }
|
||||||
|
|
||||||
|
serde = { workspace = true, features = ["derive"] }
|
||||||
|
serde-wasm-bindgen = { workspace = true }
|
||||||
|
serde_json = { workspace = true, features = ["preserve_order"] }
|
||||||
|
wasm-bindgen = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "rlib"]
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
*.tgz
|
||||||
|
jsr.jsonc
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./web_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./web_fmt_bg.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = { module_or_path: fs.readFile(wasm) }) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./web_fmt.js";
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./web_fmt.js";
|
||||||
|
import wasm from "./web_fmt_bg.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = { module_or_path: wasm }) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./web_fmt.js";
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
cd $(dirname $0)/..
|
||||||
|
crates_dir=$(pwd)
|
||||||
|
|
||||||
|
cd ../..
|
||||||
|
wasm-pack build --target=web --scope=wasm-fmt crates/web_fmt
|
||||||
|
|
||||||
|
cd $crates_dir
|
||||||
|
|
||||||
|
cp -R ./extra/. ./pkg/
|
||||||
|
|
||||||
|
./scripts/package.mjs ./pkg/package.json
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import process from "node:process";
|
||||||
|
import path from "node:path";
|
||||||
|
import fs from "node:fs";
|
||||||
|
|
||||||
|
const pkg_path = path.resolve(process.cwd(), process.argv[2]);
|
||||||
|
const pkg_text = fs.readFileSync(pkg_path, { encoding: "utf-8" });
|
||||||
|
const pkg_json = JSON.parse(pkg_text);
|
||||||
|
|
||||||
|
delete pkg_json.files;
|
||||||
|
|
||||||
|
pkg_json.main = pkg_json.module;
|
||||||
|
pkg_json.type = "module";
|
||||||
|
pkg_json.publishConfig = {
|
||||||
|
access: "public",
|
||||||
|
};
|
||||||
|
pkg_json.exports = {
|
||||||
|
".": {
|
||||||
|
types: "./web_fmt.d.ts",
|
||||||
|
node: "./web_fmt_node.js",
|
||||||
|
default: "./web_fmt.js",
|
||||||
|
},
|
||||||
|
"./vite": {
|
||||||
|
types: "./web_fmt.d.ts",
|
||||||
|
default: "./web_fmt_vite.js",
|
||||||
|
},
|
||||||
|
"./package.json": "./package.json",
|
||||||
|
"./*": "./*",
|
||||||
|
};
|
||||||
|
|
||||||
|
fs.writeFileSync(pkg_path, JSON.stringify(pkg_json, null, 4));
|
||||||
|
|
||||||
|
// JSR
|
||||||
|
|
||||||
|
const jsr_path = path.resolve(pkg_path, "..", "jsr.jsonc");
|
||||||
|
pkg_json.name = "@fmt/web-fmt";
|
||||||
|
pkg_json.exports = "./web_fmt.js";
|
||||||
|
pkg_json.exclude = ["!**", "*.tgz"];
|
||||||
|
fs.writeFileSync(jsr_path, JSON.stringify(pkg_json, null, 4));
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
use common::LayoutConfig;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "JsonConfig")]
|
||||||
|
pub type Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"export type JsonConfig = LayoutConfig;"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn format_json(src: &str, config: Option<Config>) -> Result<String, String> {
|
||||||
|
let config = config
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.clone()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|op| op.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
json_fmt::format_json_with_config(src, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn produce_json_config(
|
||||||
|
config: Option<LayoutConfig>,
|
||||||
|
config_default: &LayoutConfig,
|
||||||
|
global_fallback: &LayoutConfig,
|
||||||
|
) -> LayoutConfig {
|
||||||
|
let default = LayoutConfig::default()
|
||||||
|
.with_indent_style(common::IndentStyle::Space)
|
||||||
|
.with_indent_width(2)
|
||||||
|
.with_line_width(80)
|
||||||
|
.with_line_ending(common::LineEnding::Lf);
|
||||||
|
|
||||||
|
config
|
||||||
|
.unwrap_or_default()
|
||||||
|
.fill_empty_with(config_default)
|
||||||
|
.fill_empty_with(global_fallback)
|
||||||
|
.fill_empty_with(&default)
|
||||||
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use common::LayoutConfig;
|
||||||
|
|
||||||
|
use markup_fmt::Hints;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
use crate::format_style;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "MarkupConfig")]
|
||||||
|
pub type Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
export interface MarkupConfig extends LayoutConfig {
|
||||||
|
/**
|
||||||
|
* See {@link https://github.com/g-plane/markup_fmt/blob/main/docs/config.md}
|
||||||
|
*/
|
||||||
|
[other: string]: any;
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn format_markup(src: &str, filename: &str, config: Option<Config>) -> Result<String, String> {
|
||||||
|
let default_config: LayoutConfig = config
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.into()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let config = config
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.clone()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let markup_config = produce_markup_config(config, &default_config, &default_config);
|
||||||
|
let style_config = format_style::produce_style_config(None, &default_config, &default_config);
|
||||||
|
let script_config = biome_fmt::BiomeConfig::default().fill_empty_layout_with(&default_config);
|
||||||
|
let json_config = LayoutConfig::default().fill_empty_with(&default_config);
|
||||||
|
|
||||||
|
format_markup_with_config(
|
||||||
|
src,
|
||||||
|
filename,
|
||||||
|
markup_config,
|
||||||
|
style_config,
|
||||||
|
script_config,
|
||||||
|
json_config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format_markup_with_config(
|
||||||
|
src: &str,
|
||||||
|
filename: &str,
|
||||||
|
markup_config: markup_fmt::config::FormatOptions,
|
||||||
|
style_config: malva::config::FormatOptions,
|
||||||
|
script_config: biome_fmt::BiomeConfig,
|
||||||
|
json_config: LayoutConfig,
|
||||||
|
) -> Result<String, String> {
|
||||||
|
let language = detect_language(filename).unwrap_or(markup_fmt::Language::Html);
|
||||||
|
|
||||||
|
markup_fmt::format_text(
|
||||||
|
src,
|
||||||
|
language,
|
||||||
|
&markup_config,
|
||||||
|
|src, Hints { print_width, attr, ext, .. }| match ext.as_bytes() {
|
||||||
|
b"js" | b"ts" | b"mjs" | b"cjs" | b"jsx" | b"tsx" | b"mjsx" | b"cjsx" | b"mtsx" => {
|
||||||
|
biome_fmt::format_script_with_config(
|
||||||
|
src,
|
||||||
|
filename,
|
||||||
|
script_config.clone().with_line_width(print_width as u16),
|
||||||
|
)
|
||||||
|
.map(Into::into)
|
||||||
|
}
|
||||||
|
b"css" | b"scss" | b"sass" | b"less" => {
|
||||||
|
let mut style_config = style_config.clone();
|
||||||
|
if attr {
|
||||||
|
if let markup_fmt::config::Quotes::Double = markup_config.language.quotes {
|
||||||
|
style_config.language.quotes = malva::config::Quotes::AlwaysSingle;
|
||||||
|
} else {
|
||||||
|
style_config.language.quotes = malva::config::Quotes::AlwaysDouble;
|
||||||
|
}
|
||||||
|
style_config.language.single_line_top_level_declarations = true;
|
||||||
|
}
|
||||||
|
format_style::format_style_with_config(
|
||||||
|
src,
|
||||||
|
filename,
|
||||||
|
malva::config::FormatOptions {
|
||||||
|
layout: malva::config::LayoutOptions { print_width, ..style_config.layout },
|
||||||
|
language: style_config.language,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.map(Into::into)
|
||||||
|
}
|
||||||
|
b"json" | b"jsonc" => json_fmt::format_json_with_config(
|
||||||
|
src,
|
||||||
|
json_config.clone().with_line_width(print_width as u16).into(),
|
||||||
|
)
|
||||||
|
.map(Into::into),
|
||||||
|
_ => Ok(src.into()),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("{:?}", e))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn detect_language(path: impl AsRef<Path>) -> Option<markup_fmt::Language> {
|
||||||
|
match path.as_ref().extension().map(|x| x.to_ascii_lowercase())?.as_encoded_bytes() {
|
||||||
|
b"html" => Some(markup_fmt::Language::Html),
|
||||||
|
b"vue" => Some(markup_fmt::Language::Vue),
|
||||||
|
b"svelte" => Some(markup_fmt::Language::Svelte),
|
||||||
|
b"astro" => Some(markup_fmt::Language::Astro),
|
||||||
|
b"jinja" | b"jinja2" | b"twig" => Some(markup_fmt::Language::Jinja),
|
||||||
|
_ => Some(markup_fmt::Language::Html),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn produce_markup_config(
|
||||||
|
base_config: Option<markup_fmt::config::FormatOptions>,
|
||||||
|
config_default: &LayoutConfig,
|
||||||
|
global_fallback: &LayoutConfig,
|
||||||
|
) -> markup_fmt::config::FormatOptions {
|
||||||
|
let mut config = base_config.unwrap_or_default();
|
||||||
|
|
||||||
|
if let Some(indent_style) = config_default.indent_style().or(global_fallback.indent_style()) {
|
||||||
|
config.layout.use_tabs = indent_style.is_tab();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(indent_width) = config_default.indent_width().or(global_fallback.indent_width()) {
|
||||||
|
config.layout.indent_width = indent_width as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_width) = config_default.line_width().or(global_fallback.line_width()) {
|
||||||
|
config.layout.print_width = line_width as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_endings) = config_default.line_ending().or(global_fallback.line_ending()) {
|
||||||
|
config.layout.line_break = match line_endings {
|
||||||
|
common::LineEnding::Lf => markup_fmt::config::LineBreak::Lf,
|
||||||
|
common::LineEnding::Crlf => markup_fmt::config::LineBreak::Crlf,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
config
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
use common::LayoutConfig;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "ScriptConfig")]
|
||||||
|
pub type Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
export interface ScriptConfig extends LayoutConfig {
|
||||||
|
quote_style?: "double" | "single";
|
||||||
|
jsx_quote_style?: "double" | "single";
|
||||||
|
quote_properties?: "preserve" | "as-needed";
|
||||||
|
trailing_comma?: "es5" | "all" | "none";
|
||||||
|
semicolons?: "always" | "as-needed";
|
||||||
|
arrow_parentheses?: "always" | "as-needed";
|
||||||
|
bracket_spacing?: boolean;
|
||||||
|
bracket_same_line?: boolean;
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn format_script(src: &str, filename: &str, config: Option<Config>) -> Result<String, String> {
|
||||||
|
let config = config
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.clone()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|op| op.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
biome_fmt::format_script_with_config(src, filename, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn produce_script_config(
|
||||||
|
config: Option<biome_fmt::BiomeConfig>,
|
||||||
|
config_default: &LayoutConfig,
|
||||||
|
global_fallback: &LayoutConfig,
|
||||||
|
) -> biome_fmt::BiomeConfig {
|
||||||
|
let default = LayoutConfig::default()
|
||||||
|
.with_indent_style(common::IndentStyle::Space)
|
||||||
|
.with_indent_width(2)
|
||||||
|
.with_line_width(80)
|
||||||
|
.with_line_ending(common::LineEnding::Lf);
|
||||||
|
|
||||||
|
config
|
||||||
|
.unwrap_or_default()
|
||||||
|
.fill_empty_layout_with(config_default)
|
||||||
|
.fill_empty_layout_with(global_fallback)
|
||||||
|
.fill_empty_layout_with(&default)
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
use common::LayoutConfig;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "StyleConfig")]
|
||||||
|
pub type Config;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
export interface StyleConfig extends LayoutConfig {
|
||||||
|
/**
|
||||||
|
* See {@link https://github.com/g-plane/malva/blob/main/docs/config.md}
|
||||||
|
*/
|
||||||
|
[other: string]: any;
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn format_style(src: &str, filename: &str, config: Option<Config>) -> Result<String, String> {
|
||||||
|
let default_config: LayoutConfig = config
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.into()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let config = config
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.clone()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| e.to_string())?;
|
||||||
|
|
||||||
|
let config = produce_style_config(config, &default_config, &default_config);
|
||||||
|
|
||||||
|
format_style_with_config(src, filename, config)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format_style_with_config(
|
||||||
|
src: &str,
|
||||||
|
filename: &str,
|
||||||
|
config: malva::config::FormatOptions,
|
||||||
|
) -> Result<String, String> {
|
||||||
|
let syntax = syntax_from_filename(filename).unwrap_or_default();
|
||||||
|
|
||||||
|
malva::format_text(src, syntax, &config).map_err(|e| e.to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn syntax_from_filename(filename: &str) -> Option<malva::Syntax> {
|
||||||
|
let filename = filename.strip_suffix(['s', 'S'])?;
|
||||||
|
let filename = filename.strip_suffix(['s', 'S'])?;
|
||||||
|
|
||||||
|
let result = 'result: {
|
||||||
|
if let Some(filename) = filename.strip_suffix(['a', 'A']) {
|
||||||
|
filename.strip_suffix(['s', 'S'])?;
|
||||||
|
break 'result malva::Syntax::Sass;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(filename) = filename.strip_suffix(['e', 'E']) {
|
||||||
|
filename.strip_suffix(['l', 'L'])?;
|
||||||
|
break 'result malva::Syntax::Less;
|
||||||
|
}
|
||||||
|
|
||||||
|
if filename.strip_suffix(['c', 'C'])?.strip_suffix(['s', 'S']).is_some() {
|
||||||
|
break 'result malva::Syntax::Scss;
|
||||||
|
}
|
||||||
|
|
||||||
|
malva::Syntax::Css
|
||||||
|
};
|
||||||
|
|
||||||
|
filename.strip_suffix('.')?;
|
||||||
|
|
||||||
|
Some(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn produce_style_config(
|
||||||
|
base_config: Option<malva::config::FormatOptions>,
|
||||||
|
config_default: &LayoutConfig,
|
||||||
|
global_fallback: &LayoutConfig,
|
||||||
|
) -> malva::config::FormatOptions {
|
||||||
|
let mut config: malva::config::FormatOptions = base_config.unwrap_or_default();
|
||||||
|
|
||||||
|
if let Some(indent_style) = config_default.indent_style().or(global_fallback.indent_style()) {
|
||||||
|
config.layout.use_tabs = indent_style.is_tab();
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(indent_width) = config_default.indent_width().or(global_fallback.indent_width()) {
|
||||||
|
config.layout.indent_width = indent_width as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_width) = config_default.line_width().or(global_fallback.line_width()) {
|
||||||
|
config.layout.print_width = line_width as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(line_endings) = config_default.line_ending().or(global_fallback.line_ending()) {
|
||||||
|
config.layout.line_break = match line_endings {
|
||||||
|
common::LineEnding::Lf => malva::config::LineBreak::Lf,
|
||||||
|
common::LineEnding::Crlf => malva::config::LineBreak::Crlf,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
config
|
||||||
|
}
|
||||||
109
frontend/src/common/prettier/plugins/web/web_fmt/src/lib.rs
Normal file
109
frontend/src/common/prettier/plugins/web/web_fmt/src/lib.rs
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
mod format_json;
|
||||||
|
mod format_markup;
|
||||||
|
mod format_script;
|
||||||
|
mod format_style;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use common::LayoutConfig;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(typescript_type = "Config")]
|
||||||
|
pub type JSConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
struct Config {
|
||||||
|
markup: Option<markup_fmt::config::FormatOptions>,
|
||||||
|
script: Option<biome_fmt::BiomeConfig>,
|
||||||
|
style: Option<malva::config::FormatOptions>,
|
||||||
|
json: Option<LayoutConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[wasm_bindgen(typescript_custom_section)]
|
||||||
|
const TS_Config: &'static str = r#"
|
||||||
|
export interface Config extends LayoutConfig {
|
||||||
|
markup?: MarkupConfig;
|
||||||
|
script?: ScriptConfig;
|
||||||
|
style?: StyleConfig;
|
||||||
|
json?: JsonConfig;
|
||||||
|
}"#;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
pub fn format(src: &str, filename: &str, config: Option<JSConfig>) -> Result<String, String> {
|
||||||
|
let default_config: ConfigDefault = config
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.into()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let config: Config = config
|
||||||
|
.as_ref()
|
||||||
|
.map(|x| serde_wasm_bindgen::from_value(x.into()))
|
||||||
|
.transpose()
|
||||||
|
.map_err(|e| e.to_string())?
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let extension = Path::new(&filename).extension().ok_or("expected extension")?;
|
||||||
|
|
||||||
|
let script_config = format_script::produce_script_config(
|
||||||
|
config.script,
|
||||||
|
&default_config.script,
|
||||||
|
&default_config.default,
|
||||||
|
);
|
||||||
|
let style_config = format_style::produce_style_config(
|
||||||
|
config.style,
|
||||||
|
&default_config.style,
|
||||||
|
&default_config.default,
|
||||||
|
);
|
||||||
|
let markup_config = format_markup::produce_markup_config(
|
||||||
|
config.markup,
|
||||||
|
&default_config.markup,
|
||||||
|
&default_config.default,
|
||||||
|
);
|
||||||
|
let json_config = format_json::produce_json_config(
|
||||||
|
config.json,
|
||||||
|
&default_config.json,
|
||||||
|
&default_config.default,
|
||||||
|
);
|
||||||
|
|
||||||
|
match extension.as_encoded_bytes() {
|
||||||
|
b"js" | b"ts" | b"mjs" | b"cjs" | b"jsx" | b"tsx" | b"mjsx" | b"cjsx" | b"mtsx"
|
||||||
|
| b"ctsx" => biome_fmt::format_script_with_config(src, filename, script_config),
|
||||||
|
b"css" | b"scss" | b"sass" | b"less" => {
|
||||||
|
format_style::format_style_with_config(src, filename, style_config)
|
||||||
|
}
|
||||||
|
b"html" | b"vue" | b"svelte" | b"astro" | b"jinja" | b"jinja2" | b"twig" => {
|
||||||
|
format_markup::format_markup_with_config(
|
||||||
|
src,
|
||||||
|
filename,
|
||||||
|
markup_config,
|
||||||
|
style_config,
|
||||||
|
script_config,
|
||||||
|
json_config,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
b"json" | b"jsonc" => json_fmt::format_json_with_config(src, json_config.into()),
|
||||||
|
_ => Err(format!("unsupported file extension: {}", filename)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
|
struct ConfigDefault {
|
||||||
|
#[serde(flatten, default)]
|
||||||
|
default: LayoutConfig,
|
||||||
|
#[serde(default)]
|
||||||
|
markup: LayoutConfig,
|
||||||
|
#[serde(default)]
|
||||||
|
script: LayoutConfig,
|
||||||
|
#[serde(default)]
|
||||||
|
style: LayoutConfig,
|
||||||
|
#[serde(default)]
|
||||||
|
json: LayoutConfig,
|
||||||
|
}
|
||||||
BIN
frontend/src/common/prettier/plugins/web/web_fmt_bg.wasm
Normal file
BIN
frontend/src/common/prettier/plugins/web/web_fmt_bg.wasm
Normal file
Binary file not shown.
13
frontend/src/common/prettier/plugins/web/web_fmt_bg.wasm.d.ts
vendored
Normal file
13
frontend/src/common/prettier/plugins/web/web_fmt_bg.wasm.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
export const memory: WebAssembly.Memory;
|
||||||
|
export const format_json: (a: number, b: number, c: number, d: number) => void;
|
||||||
|
export const format_markup: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
export const format_script: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
export const format_style: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
export const format: (a: number, b: number, c: number, d: number, e: number, f: number) => void;
|
||||||
|
export const __wbindgen_export_0: (a: number, b: number) => number;
|
||||||
|
export const __wbindgen_export_1: (a: number, b: number, c: number, d: number) => number;
|
||||||
|
export const __wbindgen_export_2: (a: number) => void;
|
||||||
|
export const __wbindgen_add_to_stack_pointer: (a: number) => number;
|
||||||
|
export const __wbindgen_export_3: (a: number, b: number, c: number) => void;
|
||||||
10
frontend/src/common/prettier/plugins/web/web_fmt_node.js
Normal file
10
frontend/src/common/prettier/plugins/web/web_fmt_node.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import fs from "node:fs/promises";
|
||||||
|
import initAsync from "./web_fmt.js";
|
||||||
|
|
||||||
|
const wasm = new URL("./web_fmt_bg.wasm", import.meta.url);
|
||||||
|
|
||||||
|
export default function __wbg_init(init = { module_or_path: fs.readFile(wasm) }) {
|
||||||
|
return initAsync(init);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./web_fmt.js";
|
||||||
8
frontend/src/common/prettier/plugins/web/web_fmt_vite.js
Normal file
8
frontend/src/common/prettier/plugins/web/web_fmt_vite.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import initAsync from "./web_fmt.js";
|
||||||
|
import wasm from "./web_fmt_bg.wasm?url";
|
||||||
|
|
||||||
|
export default function __wbg_init(input = { module_or_path: wasm }) {
|
||||||
|
return initAsync(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
export * from "./web_fmt.js";
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
import { ref, computed, onMounted, onUnmounted, watch, nextTick } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useEditorStore } from '@/stores/editorStore';
|
import { useEditorStore } from '@/stores/editorStore';
|
||||||
import { SUPPORTED_LANGUAGES, type SupportedLanguage } from '@/views/editor/extensions/codeblock/types';
|
import { type SupportedLanguage } from '@/views/editor/extensions/codeblock/types';
|
||||||
|
import { LANGUAGES, getAllSupportedLanguages } from '@/views/editor/extensions/codeblock/lang-parser/languages';
|
||||||
import { getActiveNoteBlock } from '@/views/editor/extensions/codeblock/state';
|
import { getActiveNoteBlock } from '@/views/editor/extensions/codeblock/state';
|
||||||
import { changeCurrentBlockLanguage } from '@/views/editor/extensions/codeblock/commands';
|
import { changeCurrentBlockLanguage } from '@/views/editor/extensions/codeblock/commands';
|
||||||
|
|
||||||
@@ -14,73 +15,37 @@ const showLanguageMenu = ref(false);
|
|||||||
const searchQuery = ref('');
|
const searchQuery = ref('');
|
||||||
const searchInputRef = ref<HTMLInputElement>();
|
const searchInputRef = ref<HTMLInputElement>();
|
||||||
|
|
||||||
// 语言别名映射
|
// 支持的语言列表
|
||||||
const LANGUAGE_ALIASES: Record<SupportedLanguage, string> = {
|
const supportedLanguages = getAllSupportedLanguages();
|
||||||
auto: 'auto',
|
|
||||||
text: 'txt',
|
|
||||||
json: 'JSON',
|
|
||||||
py: 'python',
|
|
||||||
html: 'HTML',
|
|
||||||
sql: 'SQL',
|
|
||||||
md: 'markdown',
|
|
||||||
java: 'Java',
|
|
||||||
php: 'PHP',
|
|
||||||
css: 'CSS',
|
|
||||||
xml: 'XML',
|
|
||||||
cpp: 'c++',
|
|
||||||
rs: 'rust',
|
|
||||||
cs: 'c#',
|
|
||||||
rb: 'ruby',
|
|
||||||
sh: 'shell',
|
|
||||||
yaml: 'yml',
|
|
||||||
toml: 'TOML',
|
|
||||||
go: 'Go',
|
|
||||||
clj: 'clojure',
|
|
||||||
ex: 'elixir',
|
|
||||||
erl: 'erlang',
|
|
||||||
js: 'javascript',
|
|
||||||
ts: 'typescript',
|
|
||||||
swift: 'Swift',
|
|
||||||
kt: 'kotlin',
|
|
||||||
groovy: 'Groovy',
|
|
||||||
ps1: 'powershell',
|
|
||||||
dart: 'Dart',
|
|
||||||
scala: 'Scala'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 语言显示名称映射
|
// 动态生成语言显示名称映射
|
||||||
const LANGUAGE_NAMES: Record<SupportedLanguage, string> = {
|
const languageNames = computed(() => {
|
||||||
auto: 'Auto',
|
const names: Record<string, string> = {
|
||||||
text: 'Plain Text',
|
auto: 'Auto',
|
||||||
json: 'JSON',
|
text: 'Plain Text'
|
||||||
py: 'Python',
|
};
|
||||||
html: 'HTML',
|
|
||||||
sql: 'SQL',
|
LANGUAGES.forEach(lang => {
|
||||||
md: 'Markdown',
|
names[lang.token] = lang.name;
|
||||||
java: 'Java',
|
});
|
||||||
php: 'PHP',
|
|
||||||
css: 'CSS',
|
return names;
|
||||||
xml: 'XML',
|
});
|
||||||
cpp: 'C++',
|
|
||||||
rs: 'Rust',
|
// 动态生成语言别名映射
|
||||||
cs: 'C#',
|
const languageAliases = computed(() => {
|
||||||
rb: 'Ruby',
|
const aliases: Record<string, string> = {
|
||||||
sh: 'Shell',
|
auto: 'auto',
|
||||||
yaml: 'YAML',
|
text: 'txt'
|
||||||
toml: 'TOML',
|
};
|
||||||
go: 'Go',
|
|
||||||
clj: 'Clojure',
|
LANGUAGES.forEach(lang => {
|
||||||
ex: 'Elixir',
|
// 使用语言名称的小写作为别名
|
||||||
erl: 'Erlang',
|
aliases[lang.token] = lang.name.toLowerCase();
|
||||||
js: 'JavaScript',
|
});
|
||||||
ts: 'TypeScript',
|
|
||||||
swift: 'Swift',
|
return aliases;
|
||||||
kt: 'Kotlin',
|
});
|
||||||
groovy: 'Groovy',
|
|
||||||
ps1: 'PowerShell',
|
|
||||||
dart: 'Dart',
|
|
||||||
scala: 'Scala'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 当前活动块的语言信息
|
// 当前活动块的语言信息
|
||||||
const currentBlockLanguage = ref<{ name: SupportedLanguage; auto: boolean }>({
|
const currentBlockLanguage = ref<{ name: SupportedLanguage; auto: boolean }>({
|
||||||
@@ -197,13 +162,13 @@ watch(
|
|||||||
// 过滤后的语言列表
|
// 过滤后的语言列表
|
||||||
const filteredLanguages = computed(() => {
|
const filteredLanguages = computed(() => {
|
||||||
if (!searchQuery.value) {
|
if (!searchQuery.value) {
|
||||||
return SUPPORTED_LANGUAGES;
|
return supportedLanguages;
|
||||||
}
|
}
|
||||||
|
|
||||||
const query = searchQuery.value.toLowerCase();
|
const query = searchQuery.value.toLowerCase();
|
||||||
return SUPPORTED_LANGUAGES.filter(langId => {
|
return supportedLanguages.filter(langId => {
|
||||||
const name = LANGUAGE_NAMES[langId];
|
const name = languageNames.value[langId];
|
||||||
const alias = LANGUAGE_ALIASES[langId];
|
const alias = languageAliases.value[langId];
|
||||||
return langId.toLowerCase().includes(query) ||
|
return langId.toLowerCase().includes(query) ||
|
||||||
(name && name.toLowerCase().includes(query)) ||
|
(name && name.toLowerCase().includes(query)) ||
|
||||||
(alias && alias.toLowerCase().includes(query));
|
(alias && alias.toLowerCase().includes(query));
|
||||||
@@ -380,7 +345,7 @@ const scrollToCurrentLanguage = () => {
|
|||||||
:data-language="language"
|
:data-language="language"
|
||||||
@click="selectLanguage(language)"
|
@click="selectLanguage(language)"
|
||||||
>
|
>
|
||||||
<span class="language-name">{{ LANGUAGE_NAMES[language] || language }}</span>
|
<span class="language-name">{{ languageNames[language] || language }}</span>
|
||||||
<span class="language-alias">{{ language }}</span>
|
<span class="language-alias">{{ language }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -6,36 +6,14 @@
|
|||||||
import { EditorState, EditorSelection } from "@codemirror/state";
|
import { EditorState, EditorSelection } from "@codemirror/state";
|
||||||
import { EditorView } from "@codemirror/view";
|
import { EditorView } from "@codemirror/view";
|
||||||
import { Command } from "@codemirror/view";
|
import { Command } from "@codemirror/view";
|
||||||
import { SUPPORTED_LANGUAGES } from "./types";
|
import { LANGUAGES } from "./lang-parser/languages";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构建块分隔符正则表达式
|
* 构建块分隔符正则表达式
|
||||||
*/
|
*/
|
||||||
const languageTokensMatcher = SUPPORTED_LANGUAGES.join("|");
|
const languageTokensMatcher = LANGUAGES.map(lang => lang.token).join("|");
|
||||||
const blockSeparatorRegex = new RegExp(`\\n∞∞∞(${languageTokensMatcher})(-a)?\\n`, "g");
|
const blockSeparatorRegex = new RegExp(`\\n∞∞∞(${languageTokensMatcher})(-a)?\\n`, "g");
|
||||||
|
|
||||||
/**
|
|
||||||
* 降级复制方法 - 使用传统的 document.execCommand
|
|
||||||
*/
|
|
||||||
function fallbackCopyToClipboard(text: string): boolean {
|
|
||||||
try {
|
|
||||||
const textArea = document.createElement('textarea');
|
|
||||||
textArea.value = text;
|
|
||||||
textArea.style.position = 'fixed';
|
|
||||||
textArea.style.left = '-999999px';
|
|
||||||
textArea.style.top = '-999999px';
|
|
||||||
document.body.appendChild(textArea);
|
|
||||||
textArea.focus();
|
|
||||||
textArea.select();
|
|
||||||
const result = document.execCommand('copy');
|
|
||||||
document.body.removeChild(textArea);
|
|
||||||
return result;
|
|
||||||
} catch (err) {
|
|
||||||
console.error('The downgrade replication method also failed:', err);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取被复制的范围和内容
|
* 获取被复制的范围和内容
|
||||||
*/
|
*/
|
||||||
@@ -118,15 +96,9 @@ const copyCut = (view: EditorView, cut: boolean): boolean => {
|
|||||||
let { text, ranges } = copiedRange(view.state);
|
let { text, ranges } = copiedRange(view.state);
|
||||||
// 将块分隔符替换为双换行符
|
// 将块分隔符替换为双换行符
|
||||||
text = text.replaceAll(blockSeparatorRegex, "\n\n");
|
text = text.replaceAll(blockSeparatorRegex, "\n\n");
|
||||||
|
|
||||||
// 使用现代剪贴板 API
|
|
||||||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||||||
navigator.clipboard.writeText(text).catch(err => {
|
navigator.clipboard.writeText(text);
|
||||||
fallbackCopyToClipboard(text);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 降级到传统方法
|
|
||||||
fallbackCopyToClipboard(text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cut && !view.state.readOnly) {
|
if (cut && !view.state.readOnly) {
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ const blockLayer = layer({
|
|||||||
markers.push(new RectangleMarker(
|
markers.push(new RectangleMarker(
|
||||||
idx++ % 2 == 0 ? "block-even" : "block-odd",
|
idx++ % 2 == 0 ? "block-even" : "block-odd",
|
||||||
0,
|
0,
|
||||||
// 参考 Heynote 的精确计算方式
|
|
||||||
fromCoordsTop - (view.documentTop - view.documentPadding.top) - 1 - 6,
|
fromCoordsTop - (view.documentTop - view.documentPadding.top) - 1 - 6,
|
||||||
null, // 宽度在 CSS 中设置为 100%
|
null, // 宽度在 CSS 中设置为 100%
|
||||||
(toCoordsBottom - fromCoordsTop) + 15,
|
(toCoordsBottom - fromCoordsTop) + 15,
|
||||||
|
|||||||
@@ -38,12 +38,16 @@ export const formatBlockContent = (view) => {
|
|||||||
const performFormat = async () => {
|
const performFormat = async () => {
|
||||||
let formattedContent
|
let formattedContent
|
||||||
try {
|
try {
|
||||||
// 格式化代码
|
// 构建格式化配置
|
||||||
const formatted = await prettier.format(content, {
|
const formatOptions = {
|
||||||
parser: language.prettier!.parser,
|
parser: language.prettier!.parser,
|
||||||
plugins: language.prettier!.plugins,
|
plugins: language.prettier!.plugins,
|
||||||
tabWidth: tabSize,
|
tabWidth: tabSize,
|
||||||
})
|
...language.prettier!.options,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化代码
|
||||||
|
const formatted = await prettier.format(content, formatOptions)
|
||||||
|
|
||||||
// 计算新光标位置
|
// 计算新光标位置
|
||||||
const cursorOffset = cursorAtEdge
|
const cursorOffset = cursorAtEdge
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import {getBlockSelectExtensions} from './selectAll';
|
|||||||
import {getCopyPasteExtensions} from './copyPaste';
|
import {getCopyPasteExtensions} from './copyPaste';
|
||||||
import {moveLineDown, moveLineUp} from './moveLines';
|
import {moveLineDown, moveLineUp} from './moveLines';
|
||||||
import {getCodeBlockLanguageExtension} from './lang-parser';
|
import {getCodeBlockLanguageExtension} from './lang-parser';
|
||||||
import {createLanguageDetection} from './language-detection';
|
import {createLanguageDetection} from './lang-detect';
|
||||||
import {EditorOptions, SupportedLanguage} from './types';
|
import {SupportedLanguage} from './types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代码块扩展配置选项
|
* 代码块扩展配置选项
|
||||||
@@ -127,7 +127,6 @@ export {
|
|||||||
type Block,
|
type Block,
|
||||||
type SupportedLanguage,
|
type SupportedLanguage,
|
||||||
type CreateBlockOptions,
|
type CreateBlockOptions,
|
||||||
SUPPORTED_LANGUAGES
|
|
||||||
} from './types';
|
} from './types';
|
||||||
|
|
||||||
// 状态管理
|
// 状态管理
|
||||||
@@ -187,10 +186,8 @@ export {
|
|||||||
export {
|
export {
|
||||||
getCodeBlockLanguageExtension,
|
getCodeBlockLanguageExtension,
|
||||||
getLanguage,
|
getLanguage,
|
||||||
getLanguageTokens,
|
|
||||||
languageMapping,
|
languageMapping,
|
||||||
LanguageInfo,
|
LanguageInfo,
|
||||||
LANGUAGES as PARSER_LANGUAGES
|
|
||||||
} from './lang-parser';
|
} from './lang-parser';
|
||||||
|
|
||||||
// 语言检测
|
// 语言检测
|
||||||
@@ -200,7 +197,7 @@ export {
|
|||||||
detectLanguages,
|
detectLanguages,
|
||||||
levenshteinDistance,
|
levenshteinDistance,
|
||||||
type LanguageDetectionResult
|
type LanguageDetectionResult
|
||||||
} from './language-detection';
|
} from './lang-detect';
|
||||||
|
|
||||||
// 行号相关
|
// 行号相关
|
||||||
export {getBlockLineFromPos, blockLineNumbers};
|
export {getBlockLineFromPos, blockLineNumbers};
|
||||||
|
|||||||
@@ -61,18 +61,24 @@ const DEFAULT_CONFIG = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持的语言列表
|
* 创建检测ID到语言token的映射
|
||||||
*/
|
*/
|
||||||
const SUPPORTED_LANGUAGES = new Set([
|
function createDetectionMap(): Map<string, SupportedLanguage> {
|
||||||
"json", "py", "html", "sql", "md", "java", "php", "css", "xml",
|
const map = new Map<string, SupportedLanguage>();
|
||||||
"cpp", "rs", "cs", "rb", "sh", "yaml", "toml", "go", "clj",
|
LANGUAGES.forEach(lang => {
|
||||||
"ex", "erl", "js", "ts", "swift", "kt", "groovy", "ps1", "dart", "scala"
|
if (lang.detectIds) {
|
||||||
]);
|
lang.detectIds.forEach(detectId => {
|
||||||
|
map.set(detectId, lang.token);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 语言标记映射表
|
* 检测ID到语言token的映射表
|
||||||
*/
|
*/
|
||||||
const LANGUAGE_MAP = new Map(LANGUAGES.map(lang => [lang.token, lang.token]));
|
const DETECTION_MAP = createDetectionMap();
|
||||||
|
|
||||||
// ===== 工具函数 =====
|
// ===== 工具函数 =====
|
||||||
|
|
||||||
@@ -253,14 +259,16 @@ export function createLanguageDetection(config: LanguageDetectionConfig = {}): V
|
|||||||
try {
|
try {
|
||||||
const result = await worker.detectLanguage(content);
|
const result = await worker.detectLanguage(content);
|
||||||
|
|
||||||
if (result.confidence >= finalConfig.confidenceThreshold &&
|
// 使用检测映射表将检测结果转换为我们支持的语言
|
||||||
result.language !== block.language.name &&
|
const mappedLanguage = DETECTION_MAP.get(result.language);
|
||||||
SUPPORTED_LANGUAGES.has(result.language) &&
|
|
||||||
LANGUAGE_MAP.has(result.language)) {
|
if (mappedLanguage &&
|
||||||
|
result.confidence >= finalConfig.confidenceThreshold &&
|
||||||
|
mappedLanguage !== block.language.name) {
|
||||||
|
|
||||||
// 只有在用户没有撤销操作时才更改语言
|
// 只有在用户没有撤销操作时才更改语言
|
||||||
if (redoDepth(state) === 0) {
|
if (redoDepth(state) === 0) {
|
||||||
changeLanguageTo(state, this.view.dispatch, block, result.language, true);
|
changeLanguageTo(state, this.view.dispatch, block, mappedLanguage, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,6 @@ export {
|
|||||||
LANGUAGES,
|
LANGUAGES,
|
||||||
languageMapping,
|
languageMapping,
|
||||||
getLanguage,
|
getLanguage,
|
||||||
getLanguageTokens
|
|
||||||
} from './languages';
|
} from './languages';
|
||||||
|
|
||||||
// 嵌套解析器
|
// 嵌套解析器
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ import {groovy} from "@codemirror/legacy-modes/mode/groovy";
|
|||||||
import {powerShell} from "@codemirror/legacy-modes/mode/powershell";
|
import {powerShell} from "@codemirror/legacy-modes/mode/powershell";
|
||||||
import {toml} from "@codemirror/legacy-modes/mode/toml";
|
import {toml} from "@codemirror/legacy-modes/mode/toml";
|
||||||
import {elixir} from "codemirror-lang-elixir";
|
import {elixir} from "codemirror-lang-elixir";
|
||||||
|
import {dockerFile} from "@codemirror/legacy-modes/mode/dockerfile";
|
||||||
|
import {lua} from "@codemirror/legacy-modes/mode/lua";
|
||||||
import {SupportedLanguage} from '../types';
|
import {SupportedLanguage} from '../types';
|
||||||
|
|
||||||
import typescriptPlugin from "prettier/plugins/typescript"
|
import typescriptPlugin from "prettier/plugins/typescript"
|
||||||
@@ -43,6 +45,7 @@ import javaPrettierPlugin from "@/common/prettier/plugins/java"
|
|||||||
import xmlPrettierPlugin from "@prettier/plugin-xml"
|
import xmlPrettierPlugin from "@prettier/plugin-xml"
|
||||||
import * as rustPrettierPlugin from "@/common/prettier/plugins/rust";
|
import * as rustPrettierPlugin from "@/common/prettier/plugins/rust";
|
||||||
import * as shellPrettierPlugin from "@/common/prettier/plugins/shell";
|
import * as shellPrettierPlugin from "@/common/prettier/plugins/shell";
|
||||||
|
import * as dockerfilePrettierPlugin from "@/common/prettier/plugins/shell";
|
||||||
import tomlPrettierPlugin from "@/common/prettier/plugins/toml";
|
import tomlPrettierPlugin from "@/common/prettier/plugins/toml";
|
||||||
import clojurePrettierPlugin from "@cospaia/prettier-plugin-clojure";
|
import clojurePrettierPlugin from "@cospaia/prettier-plugin-clojure";
|
||||||
import groovyPrettierPlugin from "@/common/prettier/plugins/groovy";
|
import groovyPrettierPlugin from "@/common/prettier/plugins/groovy";
|
||||||
@@ -50,6 +53,7 @@ import scalaPrettierPlugin from "@/common/prettier/plugins/scala";
|
|||||||
import clangPrettierPlugin from "@/common/prettier/plugins/clang";
|
import clangPrettierPlugin from "@/common/prettier/plugins/clang";
|
||||||
import pythonPrettierPlugin from "@/common/prettier/plugins/python";
|
import pythonPrettierPlugin from "@/common/prettier/plugins/python";
|
||||||
import dartPrettierPlugin from "@/common/prettier/plugins/dart";
|
import dartPrettierPlugin from "@/common/prettier/plugins/dart";
|
||||||
|
import luaPrettierPlugin from "@/common/prettier/plugins/lua";
|
||||||
import * as prettierPluginEstree from "prettier/plugins/estree";
|
import * as prettierPluginEstree from "prettier/plugins/estree";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,9 +64,11 @@ export class LanguageInfo {
|
|||||||
public token: SupportedLanguage,
|
public token: SupportedLanguage,
|
||||||
public name: string,
|
public name: string,
|
||||||
public parser: any,
|
public parser: any,
|
||||||
|
public detectIds?: string[],
|
||||||
public prettier?: {
|
public prettier?: {
|
||||||
parser: string;
|
parser: string;
|
||||||
plugins: any[];
|
plugins: any[];
|
||||||
|
options?: Record<string, any>; // 添加自定义配置选项
|
||||||
}) {
|
}) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -72,97 +78,105 @@ export class LanguageInfo {
|
|||||||
*/
|
*/
|
||||||
export const LANGUAGES: LanguageInfo[] = [
|
export const LANGUAGES: LanguageInfo[] = [
|
||||||
new LanguageInfo("text", "Plain Text", null),
|
new LanguageInfo("text", "Plain Text", null),
|
||||||
new LanguageInfo("json", "JSON", jsonLanguage.parser, {
|
new LanguageInfo("json", "JSON", jsonLanguage.parser, ["json"], {
|
||||||
parser: "json",
|
parser: "json",
|
||||||
plugins: [babelPrettierPlugin, prettierPluginEstree]
|
plugins: [babelPrettierPlugin, prettierPluginEstree]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("py", "Python", pythonLanguage.parser,{
|
new LanguageInfo("py", "Python", pythonLanguage.parser, ["py"], {
|
||||||
parser: "python",
|
parser: "python",
|
||||||
plugins: [pythonPrettierPlugin]
|
plugins: [pythonPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("html", "HTML", htmlLanguage.parser, {
|
new LanguageInfo("html", "HTML", htmlLanguage.parser, ["html"], {
|
||||||
parser: "html",
|
parser: "html",
|
||||||
plugins: [htmlPrettierPlugin]
|
plugins: [htmlPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("sql", "SQL", StandardSQL.language.parser, {
|
new LanguageInfo("sql", "SQL", StandardSQL.language.parser, ["sql"], {
|
||||||
parser: "sql",
|
parser: "sql",
|
||||||
plugins: [sqlPrettierPlugin]
|
plugins: [sqlPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("md", "Markdown", markdownLanguage.parser, {
|
new LanguageInfo("md", "Markdown", markdownLanguage.parser, ["md"], {
|
||||||
parser: "markdown",
|
parser: "markdown",
|
||||||
plugins: [markdownPrettierPlugin]
|
plugins: [markdownPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("java", "Java", javaLanguage.parser,{
|
new LanguageInfo("java", "Java", javaLanguage.parser, ["java"], {
|
||||||
parser: "java",
|
parser: "java",
|
||||||
plugins: [javaPrettierPlugin]
|
plugins: [javaPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("php", "PHP", phpLanguage.configure({top: "Program"}).parser, {
|
new LanguageInfo("php", "PHP", phpLanguage.configure({top: "Program"}).parser, ["php"], {
|
||||||
parser: "php",
|
parser: "php",
|
||||||
plugins: [phpPrettierPlugin]
|
plugins: [phpPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("css", "CSS", cssLanguage.parser, {
|
new LanguageInfo("css", "CSS", cssLanguage.parser, ["css"], {
|
||||||
parser: "css",
|
parser: "css",
|
||||||
plugins: [cssPrettierPlugin]
|
plugins: [cssPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("xml", "XML", xmlLanguage.parser,{
|
new LanguageInfo("xml", "XML", xmlLanguage.parser, ["xml"], {
|
||||||
parser: "xml",
|
parser: "xml",
|
||||||
plugins: [xmlPrettierPlugin]
|
plugins: [xmlPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("cpp", "C++", cppLanguage.parser,{
|
new LanguageInfo("cpp", "C++", cppLanguage.parser, ["cpp", "c"], {
|
||||||
parser: "clang",
|
parser: "clang",
|
||||||
plugins: [clangPrettierPlugin]
|
plugins: [clangPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("rs", "Rust", rustLanguage.parser,{
|
new LanguageInfo("rs", "Rust", rustLanguage.parser, ["rs"], {
|
||||||
parser: "jinx-rust",
|
parser: "jinx-rust",
|
||||||
plugins: [rustPrettierPlugin]
|
plugins: [rustPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("cs", "C#", StreamLanguage.define(csharp).parser),
|
new LanguageInfo("cs", "C#", StreamLanguage.define(csharp).parser, ["cs"]),
|
||||||
new LanguageInfo("rb", "Ruby", StreamLanguage.define(ruby).parser),
|
new LanguageInfo("rb", "Ruby", StreamLanguage.define(ruby).parser, ["rb"]),
|
||||||
new LanguageInfo("sh", "Shell", StreamLanguage.define(shell).parser,{
|
new LanguageInfo("sh", "Shell", StreamLanguage.define(shell).parser, ["sh", "bat"], {
|
||||||
parser: "sh",
|
parser: "sh",
|
||||||
plugins: [shellPrettierPlugin]
|
plugins: [shellPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("yaml", "YAML", yamlLanguage.parser, {
|
new LanguageInfo("yaml", "YAML", yamlLanguage.parser, ["yaml"], {
|
||||||
parser: "yaml",
|
parser: "yaml",
|
||||||
plugins: [yamlPrettierPlugin]
|
plugins: [yamlPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("toml", "TOML", StreamLanguage.define(toml).parser,{
|
new LanguageInfo("toml", "TOML", StreamLanguage.define(toml).parser, ["toml"], {
|
||||||
parser: "toml",
|
parser: "toml",
|
||||||
plugins: [tomlPrettierPlugin]
|
plugins: [tomlPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("go", "Go", StreamLanguage.define(go).parser, {
|
new LanguageInfo("go", "Go", StreamLanguage.define(go).parser, ["go"], {
|
||||||
parser: "go-format",
|
parser: "go-format",
|
||||||
plugins: [goPrettierPlugin]
|
plugins: [goPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("clj", "Clojure", StreamLanguage.define(clojure).parser,{
|
new LanguageInfo("clj", "Clojure", StreamLanguage.define(clojure).parser, ["clj"], {
|
||||||
parser: "clojure",
|
parser: "clojure",
|
||||||
plugins: [clojurePrettierPlugin]
|
plugins: [clojurePrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("ex", "Elixir", elixir().language.parser),
|
new LanguageInfo("ex", "Elixir", elixir().language.parser, ["ex"]),
|
||||||
new LanguageInfo("erl", "Erlang", StreamLanguage.define(erlang).parser),
|
new LanguageInfo("erl", "Erlang", StreamLanguage.define(erlang).parser, ["erl"]),
|
||||||
new LanguageInfo("js", "JavaScript", javascriptLanguage.parser, {
|
new LanguageInfo("js", "JavaScript", javascriptLanguage.parser, ["js"], {
|
||||||
parser: "babel",
|
parser: "babel",
|
||||||
plugins: [babelPrettierPlugin, prettierPluginEstree]
|
plugins: [babelPrettierPlugin, prettierPluginEstree]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("ts", "TypeScript", typescriptLanguage.parser, {
|
new LanguageInfo("ts", "TypeScript", typescriptLanguage.parser, ["ts", "js"], {
|
||||||
parser: "typescript",
|
parser: "typescript",
|
||||||
plugins: [typescriptPlugin, prettierPluginEstree]
|
plugins: [typescriptPlugin, prettierPluginEstree]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("swift", "Swift", StreamLanguage.define(swift).parser),
|
new LanguageInfo("swift", "Swift", StreamLanguage.define(swift).parser, ["swift"]),
|
||||||
new LanguageInfo("kt", "Kotlin", StreamLanguage.define(kotlin).parser),
|
new LanguageInfo("kt", "Kotlin", StreamLanguage.define(kotlin).parser, ["kt"]),
|
||||||
new LanguageInfo("groovy", "Groovy", StreamLanguage.define(groovy).parser,{
|
new LanguageInfo("groovy", "Groovy", StreamLanguage.define(groovy).parser, ["groovy"], {
|
||||||
parser: "groovy",
|
parser: "groovy",
|
||||||
plugins: [groovyPrettierPlugin]
|
plugins: [groovyPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("ps1", "PowerShell", StreamLanguage.define(powerShell).parser),
|
new LanguageInfo("ps1", "PowerShell", StreamLanguage.define(powerShell).parser, ["ps1"]),
|
||||||
new LanguageInfo("dart", "Dart", null,{
|
new LanguageInfo("dart", "Dart", null, ["dart"], {
|
||||||
parser: "dart",
|
parser: "dart",
|
||||||
plugins: [dartPrettierPlugin]
|
plugins: [dartPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
new LanguageInfo("scala", "Scala", StreamLanguage.define(scala).parser,{
|
new LanguageInfo("scala", "Scala", StreamLanguage.define(scala).parser, ["scala"], {
|
||||||
parser: "scala",
|
parser: "scala",
|
||||||
plugins: [scalaPrettierPlugin]
|
plugins: [scalaPrettierPlugin]
|
||||||
}),
|
}),
|
||||||
|
new LanguageInfo("dockerfile", "Dockerfile", StreamLanguage.define(dockerFile).parser, ["dockerfile"], {
|
||||||
|
parser: "dockerfile",
|
||||||
|
plugins: [dockerfilePrettierPlugin]
|
||||||
|
}),
|
||||||
|
new LanguageInfo("lua", "Lua", StreamLanguage.define(lua).parser, ["lua"], {
|
||||||
|
parser: "lua",
|
||||||
|
plugins: [luaPrettierPlugin]
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -180,8 +194,8 @@ export function getLanguage(token: SupportedLanguage): LanguageInfo | undefined
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有语言的 token 列表
|
* 获取完整的支持语言列表(包括 'auto')
|
||||||
*/
|
*/
|
||||||
export function getLanguageTokens(): SupportedLanguage[] {
|
export function getAllSupportedLanguages(): SupportedLanguage[] {
|
||||||
return LANGUAGES.map(lang => lang.token);
|
return ['auto', ...LANGUAGES.map(lang => lang.token)];
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
import { EditorSelection, SelectionRange } from "@codemirror/state";
|
import { EditorSelection, SelectionRange } from "@codemirror/state";
|
||||||
import { blockState } from "./state";
|
import { blockState } from "./state";
|
||||||
import { SUPPORTED_LANGUAGES } from "./types";
|
import { LANGUAGES } from "./lang-parser/languages";
|
||||||
|
|
||||||
interface LineBlock {
|
interface LineBlock {
|
||||||
from: number;
|
from: number;
|
||||||
@@ -14,7 +14,7 @@ interface LineBlock {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建语言标记的正则表达式
|
// 创建语言标记的正则表达式
|
||||||
const languageTokensMatcher = SUPPORTED_LANGUAGES.join("|");
|
const languageTokensMatcher = LANGUAGES.map(lang => lang.token).join("|");
|
||||||
const tokenRegEx = new RegExp(`^∞∞∞(${languageTokensMatcher})(-a)?$`, "g");
|
const tokenRegEx = new RegExp(`^∞∞∞(${languageTokensMatcher})(-a)?$`, "g");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -6,17 +6,14 @@ import { EditorState } from '@codemirror/state';
|
|||||||
import { syntaxTree, syntaxTreeAvailable } from '@codemirror/language';
|
import { syntaxTree, syntaxTreeAvailable } from '@codemirror/language';
|
||||||
import { Block as BlockNode, BlockDelimiter, BlockContent, BlockLanguage, Document } from './lang-parser/parser.terms.js';
|
import { Block as BlockNode, BlockDelimiter, BlockContent, BlockLanguage, Document } from './lang-parser/parser.terms.js';
|
||||||
import {
|
import {
|
||||||
CodeBlock,
|
|
||||||
SupportedLanguage,
|
SupportedLanguage,
|
||||||
SUPPORTED_LANGUAGES,
|
|
||||||
DELIMITER_REGEX,
|
DELIMITER_REGEX,
|
||||||
DELIMITER_PREFIX,
|
DELIMITER_PREFIX,
|
||||||
DELIMITER_SUFFIX,
|
DELIMITER_SUFFIX,
|
||||||
AUTO_DETECT_SUFFIX,
|
AUTO_DETECT_SUFFIX,
|
||||||
ParseOptions,
|
|
||||||
LanguageDetectionResult,
|
|
||||||
Block
|
Block
|
||||||
} from './types';
|
} from './types';
|
||||||
|
import { LANGUAGES } from './lang-parser/languages';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从语法树解析代码块
|
* 从语法树解析代码块
|
||||||
@@ -397,7 +394,7 @@ export function parseDelimiter(delimiterText: string): { language: SupportedLang
|
|||||||
const languageName = match[1];
|
const languageName = match[1];
|
||||||
const isAuto = match[2] === AUTO_DETECT_SUFFIX;
|
const isAuto = match[2] === AUTO_DETECT_SUFFIX;
|
||||||
|
|
||||||
const validLanguage = SUPPORTED_LANGUAGES.includes(languageName as SupportedLanguage)
|
const validLanguage = LANGUAGES.some(lang => lang.token === languageName)
|
||||||
? languageName as SupportedLanguage
|
? languageName as SupportedLanguage
|
||||||
: 'text';
|
: 'text';
|
||||||
|
|
||||||
|
|||||||
@@ -2,136 +2,102 @@
|
|||||||
* Block 结构
|
* Block 结构
|
||||||
*/
|
*/
|
||||||
export interface Block {
|
export interface Block {
|
||||||
language: {
|
language: {
|
||||||
name: string;
|
name: string;
|
||||||
auto: boolean;
|
auto: boolean;
|
||||||
};
|
};
|
||||||
content: {
|
content: {
|
||||||
from: number;
|
from: number;
|
||||||
to: number;
|
to: number;
|
||||||
};
|
};
|
||||||
delimiter: {
|
delimiter: {
|
||||||
from: number;
|
from: number;
|
||||||
to: number;
|
to: number;
|
||||||
};
|
};
|
||||||
range: {
|
range: {
|
||||||
from: number;
|
from: number;
|
||||||
to: number;
|
to: number;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支持的语言类型
|
* 支持的语言类型
|
||||||
*/
|
*/
|
||||||
export type SupportedLanguage =
|
export type SupportedLanguage =
|
||||||
| 'auto' // 自动检测
|
| 'auto' // 自动检测
|
||||||
| 'text'
|
| 'text'
|
||||||
| 'json'
|
| 'json'
|
||||||
| 'py' // Python
|
| 'py' // Python
|
||||||
| 'html'
|
| 'html'
|
||||||
| 'sql'
|
| 'sql'
|
||||||
| 'md' // Markdown
|
| 'md' // Markdown
|
||||||
| 'java'
|
| 'java'
|
||||||
| 'php'
|
| 'php'
|
||||||
| 'css'
|
| 'css'
|
||||||
| 'xml'
|
| 'xml'
|
||||||
| 'cpp' // C++
|
| 'cpp' // C++
|
||||||
| 'rs' // Rust
|
| 'rs' // Rust
|
||||||
| 'cs' // C#
|
| 'cs' // C#
|
||||||
| 'rb' // Ruby
|
| 'rb' // Ruby
|
||||||
| 'sh' // Shell
|
| 'sh' // Shell
|
||||||
| 'yaml'
|
| 'yaml'
|
||||||
| 'toml'
|
| 'toml'
|
||||||
| 'go'
|
| 'go'
|
||||||
| 'clj' // Clojure
|
| 'clj' // Clojure
|
||||||
| 'ex' // Elixir
|
| 'ex' // Elixir
|
||||||
| 'erl' // Erlang
|
| 'erl' // Erlang
|
||||||
| 'js' // JavaScript
|
| 'js' // JavaScript
|
||||||
| 'ts' // TypeScript
|
| 'ts' // TypeScript
|
||||||
| 'swift'
|
| 'swift'
|
||||||
| 'kt' // Kotlin
|
| 'kt' // Kotlin
|
||||||
| 'groovy'
|
| 'groovy'
|
||||||
| 'ps1' // PowerShell
|
| 'ps1' // PowerShell
|
||||||
| 'dart'
|
| 'dart'
|
||||||
| 'scala';
|
| 'scala'
|
||||||
|
| 'dockerfile'
|
||||||
/**
|
| 'lua'
|
||||||
* 支持的语言列表
|
|
||||||
*/
|
|
||||||
export const SUPPORTED_LANGUAGES: SupportedLanguage[] = [
|
|
||||||
'auto',
|
|
||||||
'text',
|
|
||||||
'json',
|
|
||||||
'py',
|
|
||||||
'html',
|
|
||||||
'sql',
|
|
||||||
'md',
|
|
||||||
'java',
|
|
||||||
'php',
|
|
||||||
'css',
|
|
||||||
'xml',
|
|
||||||
'cpp',
|
|
||||||
'rs',
|
|
||||||
'cs',
|
|
||||||
'rb',
|
|
||||||
'sh',
|
|
||||||
'yaml',
|
|
||||||
'toml',
|
|
||||||
'go',
|
|
||||||
'clj',
|
|
||||||
'ex',
|
|
||||||
'erl',
|
|
||||||
'js',
|
|
||||||
'ts',
|
|
||||||
'swift',
|
|
||||||
'kt',
|
|
||||||
'groovy',
|
|
||||||
'ps1',
|
|
||||||
'dart',
|
|
||||||
'scala'
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建块的选项
|
* 创建块的选项
|
||||||
*/
|
*/
|
||||||
export interface CreateBlockOptions {
|
export interface CreateBlockOptions {
|
||||||
language?: SupportedLanguage;
|
language?: SupportedLanguage;
|
||||||
auto?: boolean;
|
auto?: boolean;
|
||||||
content?: string;
|
content?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 编辑器配置选项
|
* 编辑器配置选项
|
||||||
*/
|
*/
|
||||||
export interface EditorOptions {
|
export interface EditorOptions {
|
||||||
defaultBlockToken: string;
|
defaultBlockToken: string;
|
||||||
defaultBlockAutoDetect: boolean;
|
defaultBlockAutoDetect: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 语言信息接口
|
// 语言信息接口
|
||||||
export interface LanguageInfo {
|
export interface LanguageInfo {
|
||||||
name: SupportedLanguage;
|
name: SupportedLanguage;
|
||||||
auto: boolean; // 是否自动检测语言
|
auto: boolean; // 是否自动检测语言
|
||||||
}
|
}
|
||||||
|
|
||||||
// 位置范围接口
|
// 位置范围接口
|
||||||
export interface Range {
|
export interface Range {
|
||||||
from: number;
|
from: number;
|
||||||
to: number;
|
to: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 代码块核心接口
|
// 代码块核心接口
|
||||||
export interface CodeBlock {
|
export interface CodeBlock {
|
||||||
language: LanguageInfo;
|
language: LanguageInfo;
|
||||||
content: Range; // 内容区域
|
content: Range; // 内容区域
|
||||||
delimiter: Range; // 分隔符区域
|
delimiter: Range; // 分隔符区域
|
||||||
range: Range; // 整个块区域(包括分隔符和内容)
|
range: Range; // 整个块区域(包括分隔符和内容)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 代码块解析选项
|
// 代码块解析选项
|
||||||
export interface ParseOptions {
|
export interface ParseOptions {
|
||||||
fallbackLanguage?: SupportedLanguage;
|
fallbackLanguage?: SupportedLanguage;
|
||||||
enableAutoDetection?: boolean;
|
enableAutoDetection?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 分隔符格式常量
|
// 分隔符格式常量
|
||||||
@@ -141,23 +107,23 @@ export const DELIMITER_SUFFIX = '\n';
|
|||||||
export const AUTO_DETECT_SUFFIX = '-a';
|
export const AUTO_DETECT_SUFFIX = '-a';
|
||||||
|
|
||||||
// 代码块操作类型
|
// 代码块操作类型
|
||||||
export type BlockOperation =
|
export type BlockOperation =
|
||||||
| 'insert-after'
|
| 'insert-after'
|
||||||
| 'insert-before'
|
| 'insert-before'
|
||||||
| 'delete'
|
| 'delete'
|
||||||
| 'move-up'
|
| 'move-up'
|
||||||
| 'move-down'
|
| 'move-down'
|
||||||
| 'change-language';
|
| 'change-language';
|
||||||
|
|
||||||
// 代码块状态更新事件
|
// 代码块状态更新事件
|
||||||
export interface BlockStateUpdate {
|
export interface BlockStateUpdate {
|
||||||
blocks: CodeBlock[];
|
blocks: CodeBlock[];
|
||||||
activeBlockIndex: number;
|
activeBlockIndex: number;
|
||||||
operation?: BlockOperation;
|
operation?: BlockOperation;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 语言检测结果
|
// 语言检测结果
|
||||||
export interface LanguageDetectionResult {
|
export interface LanguageDetectionResult {
|
||||||
language: SupportedLanguage;
|
language: SupportedLanguage;
|
||||||
confidence: number;
|
confidence: number;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user