🚨 Format code
This commit is contained in:
@@ -193,8 +193,8 @@ function setSel(state: any, selection: EditorSelection) {
|
||||
}
|
||||
|
||||
function extendSel(state: any, dispatch: any, how: (range: any) => any) {
|
||||
let selection = updateSel(state.selection, range => {
|
||||
let head = how(range);
|
||||
const selection = updateSel(state.selection, range => {
|
||||
const head = how(range);
|
||||
return EditorSelection.range(range.anchor, head.head, head.goalColumn, head.bidiLevel || undefined);
|
||||
});
|
||||
if (selection.eq(state.selection)) return false;
|
||||
@@ -203,7 +203,7 @@ function extendSel(state: any, dispatch: any, how: (range: any) => any) {
|
||||
}
|
||||
|
||||
function moveSel(state: any, dispatch: any, how: (range: any) => any) {
|
||||
let selection = updateSel(state.selection, how);
|
||||
const selection = updateSel(state.selection, how);
|
||||
if (selection.eq(state.selection)) return false;
|
||||
dispatch(setSel(state, selection));
|
||||
return true;
|
||||
@@ -268,7 +268,7 @@ export function selectPreviousBlock({ state, dispatch }: any) {
|
||||
/**
|
||||
* 删除块
|
||||
*/
|
||||
export const deleteBlock = (options: EditorOptions): Command => ({ state, dispatch }) => {
|
||||
export const deleteBlock = (_options: EditorOptions): Command => ({ state, dispatch }) => {
|
||||
if (state.readOnly) return false;
|
||||
|
||||
const block = getActiveNoteBlock(state);
|
||||
@@ -380,4 +380,4 @@ function moveCurrentBlock(state: any, dispatch: any, up: boolean) {
|
||||
*/
|
||||
export const formatCurrentBlock: Command = (view) => {
|
||||
return formatBlockContent(view);
|
||||
}
|
||||
};
|
||||
@@ -18,10 +18,10 @@ const blockSeparatorRegex = new RegExp(`\\n∞∞∞(${languageTokensMatcher})(-
|
||||
* 获取被复制的范围和内容
|
||||
*/
|
||||
function copiedRange(state: EditorState) {
|
||||
let content: string[] = [];
|
||||
let ranges: any[] = [];
|
||||
const content: string[] = [];
|
||||
const ranges: any[] = [];
|
||||
|
||||
for (let range of state.selection.ranges) {
|
||||
for (const range of state.selection.ranges) {
|
||||
if (!range.empty) {
|
||||
content.push(state.sliceDoc(range.from, range.to));
|
||||
ranges.push(range);
|
||||
@@ -31,7 +31,7 @@ function copiedRange(state: EditorState) {
|
||||
if (ranges.length === 0) {
|
||||
// 如果所有范围都是空的,我们想要复制每个选择的整行(唯一的)
|
||||
const copiedLines: number[] = [];
|
||||
for (let range of state.selection.ranges) {
|
||||
for (const range of state.selection.ranges) {
|
||||
if (range.empty) {
|
||||
const line = state.doc.lineAt(range.head);
|
||||
const lineContent = state.sliceDoc(line.from, line.to);
|
||||
@@ -55,7 +55,7 @@ function copiedRange(state: EditorState) {
|
||||
*/
|
||||
export const codeBlockCopyCut = EditorView.domEventHandlers({
|
||||
copy(event, view) {
|
||||
let { text, ranges } = copiedRange(view.state);
|
||||
let { text } = copiedRange(view.state);
|
||||
// 将块分隔符替换为双换行符
|
||||
text = text.replaceAll(blockSeparatorRegex, "\n\n");
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ class NoteBlockStart extends WidgetType {
|
||||
}
|
||||
|
||||
toDOM() {
|
||||
let wrap = document.createElement("div");
|
||||
const wrap = document.createElement("div");
|
||||
wrap.className = "code-block-start" + (this.isFirst ? " first" : "");
|
||||
return wrap;
|
||||
}
|
||||
@@ -37,8 +37,8 @@ const noteBlockWidget = () => {
|
||||
const builder = new RangeSetBuilder<Decoration>();
|
||||
|
||||
state.field(blockState).forEach((block: any) => {
|
||||
let delimiter = block.delimiter;
|
||||
let deco = Decoration.replace({
|
||||
const delimiter = block.delimiter;
|
||||
const deco = Decoration.replace({
|
||||
widget: new NoteBlockStart(delimiter.from === 0),
|
||||
inclusive: true,
|
||||
block: true,
|
||||
@@ -80,7 +80,7 @@ const noteBlockWidget = () => {
|
||||
* 原子范围,防止在分隔符内编辑
|
||||
*/
|
||||
function atomicRanges(view: EditorView) {
|
||||
let builder = new RangeSetBuilder();
|
||||
const builder = new RangeSetBuilder();
|
||||
view.state.field(blockState).forEach((block: any) => {
|
||||
builder.add(
|
||||
block.delimiter.from,
|
||||
@@ -167,7 +167,7 @@ const blockLayer = layer({
|
||||
return markers;
|
||||
},
|
||||
|
||||
update(update: any, dom: any) {
|
||||
update(update: any, _dom: any) {
|
||||
return update.docChanged || update.viewportChanged;
|
||||
},
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@ function updateSel(sel: EditorSelection, by: (range: SelectionRange) => Selectio
|
||||
* 获取选中的行块
|
||||
*/
|
||||
function selectedLineBlocks(state: any): LineBlock[] {
|
||||
let blocks: LineBlock[] = [];
|
||||
const blocks: LineBlock[] = [];
|
||||
let upto = -1;
|
||||
|
||||
for (let range of state.selection.ranges) {
|
||||
let startLine = state.doc.lineAt(range.from);
|
||||
for (const range of state.selection.ranges) {
|
||||
const startLine = state.doc.lineAt(range.from);
|
||||
let endLine = state.doc.lineAt(range.to);
|
||||
|
||||
if (!range.empty && range.to == endLine.from) {
|
||||
@@ -36,7 +36,7 @@ function selectedLineBlocks(state: any): LineBlock[] {
|
||||
}
|
||||
|
||||
if (upto >= startLine.number) {
|
||||
let prev = blocks[blocks.length - 1];
|
||||
const prev = blocks[blocks.length - 1];
|
||||
prev.to = endLine.to;
|
||||
prev.ranges.push(range);
|
||||
} else {
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
import { EditorSelection } from "@codemirror/state"
|
||||
import { EditorSelection } from "@codemirror/state";
|
||||
|
||||
import * as prettier from "prettier/standalone"
|
||||
import { getActiveNoteBlock } from "./state"
|
||||
import { getLanguage } from "./lang-parser/languages"
|
||||
import { SupportedLanguage } from "./types"
|
||||
import * as prettier from "prettier/standalone";
|
||||
import { getActiveNoteBlock } from "./state";
|
||||
import { getLanguage } from "./lang-parser/languages";
|
||||
import { SupportedLanguage } from "./types";
|
||||
|
||||
export const formatBlockContent = (view) => {
|
||||
if (!view || view.state.readOnly)
|
||||
return false
|
||||
return false;
|
||||
|
||||
// 获取初始信息,但不缓存state对象
|
||||
const initialState = view.state
|
||||
const block = getActiveNoteBlock(initialState)
|
||||
const initialState = view.state;
|
||||
const block = getActiveNoteBlock(initialState);
|
||||
|
||||
if (!block) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
const blockFrom = block.content.from
|
||||
const blockTo = block.content.to
|
||||
const blockLanguageName = block.language.name as SupportedLanguage
|
||||
const blockFrom = block.content.from;
|
||||
const blockTo = block.content.to;
|
||||
const blockLanguageName = block.language.name as SupportedLanguage;
|
||||
|
||||
const language = getLanguage(blockLanguageName)
|
||||
const language = getLanguage(blockLanguageName);
|
||||
if (!language || !language.prettier) {
|
||||
return false
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取初始需要的信息
|
||||
const cursorPos = initialState.selection.asSingle().ranges[0].head
|
||||
const content = initialState.sliceDoc(blockFrom, blockTo)
|
||||
const tabSize = initialState.tabSize
|
||||
const cursorPos = initialState.selection.asSingle().ranges[0].head;
|
||||
const content = initialState.sliceDoc(blockFrom, blockTo);
|
||||
const tabSize = initialState.tabSize;
|
||||
|
||||
// 检查光标是否在块的开始或结束
|
||||
const cursorAtEdge = cursorPos == blockFrom || cursorPos == blockTo
|
||||
const cursorAtEdge = cursorPos == blockFrom || cursorPos == blockTo;
|
||||
|
||||
// 执行异步格式化
|
||||
const performFormat = async () => {
|
||||
let formattedContent
|
||||
let formattedContent;
|
||||
try {
|
||||
// 构建格式化配置
|
||||
const formatOptions = {
|
||||
@@ -44,39 +44,39 @@ export const formatBlockContent = (view) => {
|
||||
plugins: language.prettier!.plugins,
|
||||
tabWidth: tabSize,
|
||||
...language.prettier!.options,
|
||||
}
|
||||
};
|
||||
|
||||
// 格式化代码
|
||||
const formatted = await prettier.format(content, formatOptions)
|
||||
const formatted = await prettier.format(content, formatOptions);
|
||||
|
||||
// 计算新光标位置
|
||||
const cursorOffset = cursorAtEdge
|
||||
? (cursorPos == blockFrom ? 0 : formatted.length)
|
||||
: Math.min(cursorPos - blockFrom, formatted.length)
|
||||
: Math.min(cursorPos - blockFrom, formatted.length);
|
||||
|
||||
formattedContent = {
|
||||
formatted,
|
||||
cursorOffset
|
||||
}
|
||||
} catch (e) {
|
||||
return false
|
||||
};
|
||||
} catch (_e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
// 格式化完成后再次获取最新状态
|
||||
const currentState = view.state
|
||||
const currentState = view.state;
|
||||
|
||||
// 重新获取当前块的位置
|
||||
const currentBlock = getActiveNoteBlock(currentState)
|
||||
const currentBlock = getActiveNoteBlock(currentState);
|
||||
|
||||
if (!currentBlock) {
|
||||
console.warn('Block not found after formatting')
|
||||
return false
|
||||
console.warn('Block not found after formatting');
|
||||
return false;
|
||||
}
|
||||
|
||||
// 使用当前块的实际位置
|
||||
const currentBlockFrom = currentBlock.content.from
|
||||
const currentBlockTo = currentBlock.content.to
|
||||
const currentBlockFrom = currentBlock.content.from;
|
||||
const currentBlockTo = currentBlock.content.to;
|
||||
|
||||
// 基于最新状态创建更新
|
||||
view.dispatch({
|
||||
@@ -88,16 +88,16 @@ export const formatBlockContent = (view) => {
|
||||
selection: EditorSelection.cursor(currentBlockFrom + Math.min(formattedContent.cursorOffset, formattedContent.formatted.length)),
|
||||
scrollIntoView: true,
|
||||
userEvent: "input"
|
||||
})
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('Failed to apply formatting changes:', error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 执行异步格式化
|
||||
performFormat()
|
||||
return true // 立即返回 true,表示命令已开始执行
|
||||
}
|
||||
performFormat();
|
||||
return true; // 立即返回 true,表示命令已开始执行
|
||||
};
|
||||
@@ -49,8 +49,8 @@ export const CodeBlockLanguage = LRLanguage.define({
|
||||
* 创建代码块语言支持
|
||||
*/
|
||||
export function codeBlockLang() {
|
||||
let wrap = configureNesting();
|
||||
let lang = CodeBlockLanguage.configure({ dialect: "", wrap: wrap });
|
||||
const wrap = configureNesting();
|
||||
const lang = CodeBlockLanguage.configure({ dialect: "", wrap: wrap });
|
||||
|
||||
return [
|
||||
new LanguageSupport(lang, [json().support]),
|
||||
|
||||
@@ -32,17 +32,17 @@ import {dockerFile} from "@codemirror/legacy-modes/mode/dockerfile";
|
||||
import {lua} from "@codemirror/legacy-modes/mode/lua";
|
||||
import {SupportedLanguage} from '../types';
|
||||
|
||||
import typescriptPlugin from "prettier/plugins/typescript"
|
||||
import babelPrettierPlugin from "prettier/plugins/babel"
|
||||
import htmlPrettierPlugin from "prettier/plugins/html"
|
||||
import cssPrettierPlugin from "prettier/plugins/postcss"
|
||||
import markdownPrettierPlugin from "prettier/plugins/markdown"
|
||||
import yamlPrettierPlugin from "prettier/plugins/yaml"
|
||||
import goPrettierPlugin from "@/common/prettier/plugins/go"
|
||||
import sqlPrettierPlugin from "@/common/prettier/plugins/sql"
|
||||
import phpPrettierPlugin from "@/common/prettier/plugins/php"
|
||||
import javaPrettierPlugin from "@/common/prettier/plugins/java"
|
||||
import xmlPrettierPlugin from "@prettier/plugin-xml"
|
||||
import typescriptPlugin from "prettier/plugins/typescript";
|
||||
import babelPrettierPlugin from "prettier/plugins/babel";
|
||||
import htmlPrettierPlugin from "prettier/plugins/html";
|
||||
import cssPrettierPlugin from "prettier/plugins/postcss";
|
||||
import markdownPrettierPlugin from "prettier/plugins/markdown";
|
||||
import yamlPrettierPlugin from "prettier/plugins/yaml";
|
||||
import goPrettierPlugin from "@/common/prettier/plugins/go";
|
||||
import sqlPrettierPlugin from "@/common/prettier/plugins/sql";
|
||||
import phpPrettierPlugin from "@/common/prettier/plugins/php";
|
||||
import javaPrettierPlugin from "@/common/prettier/plugins/java";
|
||||
import xmlPrettierPlugin from "@prettier/plugin-xml";
|
||||
import shellPrettierPlugin from "@/common/prettier/plugins/shell";
|
||||
import dockerfilePrettierPlugin from "@/common/prettier/plugins/docker";
|
||||
import rustPrettierPlugin from "@/common/prettier/plugins/rust";
|
||||
|
||||
@@ -13,11 +13,11 @@ import { languageMapping } from "./languages";
|
||||
*/
|
||||
export function configureNesting() {
|
||||
return parseMixed((node, input) => {
|
||||
let id = node.type.id;
|
||||
const id = node.type.id;
|
||||
|
||||
if (id === BlockContent) {
|
||||
// 获取父节点中的语言标记
|
||||
let blockLang = node.node.parent?.firstChild?.getChildren(BlockLanguage)[0];
|
||||
const blockLang = node.node.parent?.firstChild?.getChildren(BlockLanguage)[0];
|
||||
let langName = blockLang ? input.read(blockLang.from, blockLang.to) : null;
|
||||
|
||||
// 如果 BlockContent 为空,不返回解析器
|
||||
|
||||
@@ -63,13 +63,13 @@ class MathResult extends WidgetType {
|
||||
* 数学装饰函数
|
||||
*/
|
||||
function mathDeco(view: any): any {
|
||||
let mathParsers = new WeakMap();
|
||||
let builder = new RangeSetBuilder();
|
||||
const mathParsers = new WeakMap();
|
||||
const builder = new RangeSetBuilder();
|
||||
|
||||
for (let { from, to } of view.visibleRanges) {
|
||||
for (const { from, to } of view.visibleRanges) {
|
||||
for (let pos = from; pos <= to;) {
|
||||
let line = view.state.doc.lineAt(pos);
|
||||
var block = getNoteBlockFromPos(view.state, pos);
|
||||
const line = view.state.doc.lineAt(pos);
|
||||
const block = getNoteBlockFromPos(view.state, pos);
|
||||
|
||||
if (block && block.language.name === "math") {
|
||||
// get math.js parser and cache it for this block
|
||||
@@ -97,7 +97,7 @@ function mathDeco(view: any): any {
|
||||
|
||||
// if we got a result from math.js, add the result decoration
|
||||
if (result !== undefined) {
|
||||
let format = parser?.get("format");
|
||||
const format = parser?.get("format");
|
||||
|
||||
let resultWidget: MathResult | undefined;
|
||||
if (typeof(result) === "string") {
|
||||
|
||||
@@ -21,11 +21,11 @@ const tokenRegEx = new RegExp(`^∞∞∞(${languageTokensMatcher})(-a)?$`, "g")
|
||||
* 获取选中的行块
|
||||
*/
|
||||
function selectedLineBlocks(state: any): LineBlock[] {
|
||||
let blocks: LineBlock[] = [];
|
||||
const blocks: LineBlock[] = [];
|
||||
let upto = -1;
|
||||
|
||||
for (let range of state.selection.ranges) {
|
||||
let startLine = state.doc.lineAt(range.from);
|
||||
for (const range of state.selection.ranges) {
|
||||
const startLine = state.doc.lineAt(range.from);
|
||||
let endLine = state.doc.lineAt(range.to);
|
||||
|
||||
if (!range.empty && range.to == endLine.from) {
|
||||
@@ -33,7 +33,7 @@ function selectedLineBlocks(state: any): LineBlock[] {
|
||||
}
|
||||
|
||||
if (upto >= startLine.number) {
|
||||
let prev = blocks[blocks.length - 1];
|
||||
const prev = blocks[blocks.length - 1];
|
||||
prev.to = endLine.to;
|
||||
prev.ranges.push(range);
|
||||
} else {
|
||||
@@ -57,15 +57,15 @@ function moveLine(state: any, dispatch: any, forward: boolean): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
let changes: any[] = [];
|
||||
let ranges: SelectionRange[] = [];
|
||||
const changes: any[] = [];
|
||||
const ranges: SelectionRange[] = [];
|
||||
|
||||
for (let block of selectedLineBlocks(state)) {
|
||||
for (const block of selectedLineBlocks(state)) {
|
||||
if (forward ? block.to == state.doc.length : block.from == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let nextLine = state.doc.lineAt(forward ? block.to + 1 : block.from - 1);
|
||||
const nextLine = state.doc.lineAt(forward ? block.to + 1 : block.from - 1);
|
||||
let previousLine;
|
||||
|
||||
if (!forward ? block.to == state.doc.length : block.from == 0) {
|
||||
@@ -76,8 +76,8 @@ function moveLine(state: any, dispatch: any, forward: boolean): boolean {
|
||||
|
||||
// 如果整个选择是一个被分隔符包围的块,我们需要在分隔符之间添加额外的换行符
|
||||
// 以避免创建两个只有单个换行符的分隔符,这会导致语法解析器无法解析
|
||||
let nextLineIsSeparator = nextLine.text.match(tokenRegEx);
|
||||
let blockSurroundedBySeparators = previousLine !== null &&
|
||||
const nextLineIsSeparator = nextLine.text.match(tokenRegEx);
|
||||
const blockSurroundedBySeparators = previousLine !== null &&
|
||||
previousLine.text.match(tokenRegEx) && nextLineIsSeparator;
|
||||
|
||||
let size = nextLine.length + 1;
|
||||
@@ -96,7 +96,7 @@ function moveLine(state: any, dispatch: any, forward: boolean): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
for (let r of block.ranges) {
|
||||
for (const r of block.ranges) {
|
||||
ranges.push(EditorSelection.range(
|
||||
Math.min(state.doc.length, r.anchor + size),
|
||||
Math.min(state.doc.length, r.head + size)
|
||||
@@ -108,7 +108,7 @@ function moveLine(state: any, dispatch: any, forward: boolean): boolean {
|
||||
{ from: nextLine.from, to: block.from },
|
||||
{ from: block.to, insert: state.lineBreak + nextLine.text + state.lineBreak }
|
||||
);
|
||||
for (let r of block.ranges) {
|
||||
for (const r of block.ranges) {
|
||||
ranges.push(EditorSelection.range(r.anchor - size, r.head - size));
|
||||
}
|
||||
} else {
|
||||
@@ -116,7 +116,7 @@ function moveLine(state: any, dispatch: any, forward: boolean): boolean {
|
||||
{ from: nextLine.from, to: block.from },
|
||||
{ from: block.to, insert: state.lineBreak + nextLine.text }
|
||||
);
|
||||
for (let r of block.ranges) {
|
||||
for (const r of block.ranges) {
|
||||
ranges.push(EditorSelection.range(r.anchor - size, r.head - size));
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@ function moveLine(state: any, dispatch: any, forward: boolean): boolean {
|
||||
export const moveLineUp = ({ state, dispatch }: { state: any; dispatch: any }): boolean => {
|
||||
// 防止移动行到第一个块分隔符之前
|
||||
if (state.selection.ranges.some((range: SelectionRange) => {
|
||||
let startLine = state.doc.lineAt(range.from);
|
||||
const startLine = state.doc.lineAt(range.from);
|
||||
return startLine.from <= state.field(blockState)[0].content.from;
|
||||
})) {
|
||||
return true;
|
||||
|
||||
@@ -27,7 +27,7 @@ export const emptyBlockSelected = StateField.define<number | null>({
|
||||
// 如果选择改变,重置状态
|
||||
return null;
|
||||
} else {
|
||||
for (let e of tr.effects) {
|
||||
for (const e of tr.effects) {
|
||||
if (e.is(setEmptyBlockSelected)) {
|
||||
// 切换状态为 true
|
||||
return e.value;
|
||||
@@ -164,8 +164,8 @@ export const blockAwareSelection = EditorState.transactionFilter.of((tr: any) =>
|
||||
|
||||
// 如果选择在一个块内,确保不超出块边界
|
||||
if (fromBlock) {
|
||||
let newFrom = Math.max(range.from, fromBlock.content.from);
|
||||
let newTo = Math.min(range.to, fromBlock.content.to);
|
||||
const newFrom = Math.max(range.from, fromBlock.content.from);
|
||||
const newTo = Math.min(range.to, fromBlock.content.to);
|
||||
|
||||
if (newFrom !== range.from || newTo !== range.to) {
|
||||
needsCorrection = true;
|
||||
|
||||
@@ -14,7 +14,7 @@ export const transposeChars = ({ state, dispatch }: { state: any; dispatch: any
|
||||
return false;
|
||||
}
|
||||
|
||||
let changes = state.changeByRange((range: any) => {
|
||||
const changes = state.changeByRange((range: any) => {
|
||||
// 防止在代码块的开始或结束位置进行字符转置,因为这会破坏块语法
|
||||
const block = getNoteBlockFromPos(state, range.from);
|
||||
if (block && (range.from === block.content.from || range.from === block.content.to)) {
|
||||
@@ -25,10 +25,10 @@ export const transposeChars = ({ state, dispatch }: { state: any; dispatch: any
|
||||
return { range };
|
||||
}
|
||||
|
||||
let pos = range.from;
|
||||
let line = state.doc.lineAt(pos);
|
||||
let from = pos == line.from ? pos - 1 : findClusterBreak(line.text, pos - line.from, false) + line.from;
|
||||
let to = pos == line.to ? pos + 1 : findClusterBreak(line.text, pos - line.from, true) + line.from;
|
||||
const pos = range.from;
|
||||
const line = state.doc.lineAt(pos);
|
||||
const from = pos == line.from ? pos - 1 : findClusterBreak(line.text, pos - line.from, false) + line.from;
|
||||
const to = pos == line.to ? pos + 1 : findClusterBreak(line.text, pos - line.from, true) + line.from;
|
||||
|
||||
return {
|
||||
changes: {
|
||||
|
||||
Reference in New Issue
Block a user