增加文件管理器,增加文件编辑
This commit is contained in:
219
src/lib/eslint-integration.ts
Normal file
219
src/lib/eslint-integration.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import * as monaco from 'monaco-editor';
|
||||
import type { Linter } from 'eslint';
|
||||
|
||||
// 将 ESLint 诊断转换为 Monaco 标记
|
||||
export function convertESLintToMonacoMarkers(
|
||||
eslintMessages: Linter.LintMessage[],
|
||||
_model: monaco.editor.ITextModel
|
||||
): monaco.editor.IMarkerData[] {
|
||||
return eslintMessages.map(message => {
|
||||
return {
|
||||
severity: message.severity === 2
|
||||
? monaco.MarkerSeverity.Error
|
||||
: monaco.MarkerSeverity.Warning,
|
||||
startLineNumber: message.line || 1,
|
||||
startColumn: message.column || 1,
|
||||
endLineNumber: message.endLine || message.line || 1,
|
||||
endColumn: message.endColumn || (message.column ? message.column + 1 : 1),
|
||||
message: message.message,
|
||||
source: message.ruleId || 'eslint',
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// 实时语法检查配置
|
||||
export interface RealtimeLintOptions {
|
||||
enabled: boolean;
|
||||
delay: number; // 延迟时间(毫秒)
|
||||
showInlineErrors: boolean;
|
||||
showErrorsInScrollbar: boolean;
|
||||
showErrorsInMinimap: boolean;
|
||||
}
|
||||
|
||||
export const defaultLintOptions: RealtimeLintOptions = {
|
||||
enabled: true,
|
||||
delay: 500,
|
||||
showInlineErrors: true,
|
||||
showErrorsInScrollbar: true,
|
||||
showErrorsInMinimap: true,
|
||||
};
|
||||
|
||||
// 配置实时语法检查
|
||||
export function setupRealtimeLinting(
|
||||
editor: monaco.editor.IStandaloneCodeEditor,
|
||||
options: RealtimeLintOptions = defaultLintOptions
|
||||
) {
|
||||
if (!options.enabled) return;
|
||||
|
||||
let lintTimer: NodeJS.Timeout | null = null;
|
||||
|
||||
const performLinting = () => {
|
||||
const model = editor.getModel();
|
||||
if (!model) return;
|
||||
|
||||
const language = model.getLanguageId();
|
||||
if (language !== 'typescript' && language !== 'javascript' &&
|
||||
language !== 'typescriptreact' && language !== 'javascriptreact') {
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据选项配置显示
|
||||
if (options.showErrorsInScrollbar) {
|
||||
editor.updateOptions({
|
||||
overviewRulerLanes: 3,
|
||||
});
|
||||
}
|
||||
|
||||
if (options.showErrorsInMinimap) {
|
||||
editor.updateOptions({
|
||||
minimap: {
|
||||
showSlider: 'always',
|
||||
renderCharacters: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 监听内容变化
|
||||
editor.onDidChangeModelContent(() => {
|
||||
if (lintTimer) {
|
||||
clearTimeout(lintTimer);
|
||||
}
|
||||
|
||||
lintTimer = setTimeout(() => {
|
||||
performLinting();
|
||||
}, options.delay);
|
||||
});
|
||||
|
||||
// 初始检查
|
||||
performLinting();
|
||||
}
|
||||
|
||||
// 代码快速修复建议
|
||||
export interface QuickFix {
|
||||
title: string;
|
||||
kind: string;
|
||||
edit: monaco.languages.WorkspaceEdit;
|
||||
}
|
||||
|
||||
// 注册代码操作提供器(快速修复)
|
||||
export function registerCodeActionProvider() {
|
||||
monaco.languages.registerCodeActionProvider(['typescript', 'javascript', 'typescriptreact', 'javascriptreact'], {
|
||||
provideCodeActions: (model, _range, context, _token) => {
|
||||
const actions: monaco.languages.CodeAction[] = [];
|
||||
|
||||
// 检查是否有错误标记
|
||||
const markers = context.markers.filter(marker => marker.severity === monaco.MarkerSeverity.Error);
|
||||
|
||||
for (const marker of markers) {
|
||||
// 未使用变量的快速修复
|
||||
if (marker.code === '6133' || marker.message.includes('is declared but')) {
|
||||
actions.push({
|
||||
title: `Remove unused declaration`,
|
||||
kind: 'quickfix',
|
||||
diagnostics: [marker],
|
||||
edit: {
|
||||
edits: [{
|
||||
resource: model.uri,
|
||||
textEdit: {
|
||||
range: {
|
||||
startLineNumber: marker.startLineNumber,
|
||||
startColumn: 1,
|
||||
endLineNumber: marker.endLineNumber,
|
||||
endColumn: model.getLineLength(marker.endLineNumber) + 1,
|
||||
},
|
||||
text: '',
|
||||
},
|
||||
versionId: undefined,
|
||||
}],
|
||||
},
|
||||
isPreferred: true,
|
||||
});
|
||||
}
|
||||
|
||||
// 缺少导入的快速修复
|
||||
if (marker.message.includes('Cannot find name')) {
|
||||
const variableName = marker.message.match(/Cannot find name '([^']+)'/)?.[1];
|
||||
if (variableName) {
|
||||
actions.push({
|
||||
title: `Import '${variableName}'`,
|
||||
kind: 'quickfix',
|
||||
diagnostics: [marker],
|
||||
edit: {
|
||||
edits: [{
|
||||
resource: model.uri,
|
||||
textEdit: {
|
||||
range: {
|
||||
startLineNumber: 1,
|
||||
startColumn: 1,
|
||||
endLineNumber: 1,
|
||||
endColumn: 1,
|
||||
},
|
||||
text: `import { ${variableName} } from './${variableName.toLowerCase()}';\n`,
|
||||
},
|
||||
versionId: undefined,
|
||||
}],
|
||||
},
|
||||
isPreferred: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 类型错误的快速修复
|
||||
if (marker.message.includes('Type') && marker.message.includes('is not assignable')) {
|
||||
actions.push({
|
||||
title: 'Add type assertion',
|
||||
kind: 'quickfix',
|
||||
diagnostics: [marker],
|
||||
edit: {
|
||||
edits: [{
|
||||
resource: model.uri,
|
||||
textEdit: {
|
||||
range: {
|
||||
startLineNumber: marker.startLineNumber,
|
||||
startColumn: marker.startColumn,
|
||||
endLineNumber: marker.endLineNumber,
|
||||
endColumn: marker.endColumn,
|
||||
},
|
||||
text: `(${model.getValueInRange({
|
||||
startLineNumber: marker.startLineNumber,
|
||||
startColumn: marker.startColumn,
|
||||
endLineNumber: marker.endLineNumber,
|
||||
endColumn: marker.endColumn,
|
||||
})} as any)`,
|
||||
},
|
||||
versionId: undefined,
|
||||
}],
|
||||
},
|
||||
isPreferred: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 添加格式化操作
|
||||
actions.push({
|
||||
title: 'Format Document',
|
||||
kind: 'source.formatAll',
|
||||
command: {
|
||||
id: 'editor.action.formatDocument',
|
||||
title: 'Format Document',
|
||||
},
|
||||
});
|
||||
|
||||
// 添加组织导入操作
|
||||
actions.push({
|
||||
title: 'Organize Imports',
|
||||
kind: 'source.organizeImports',
|
||||
command: {
|
||||
id: 'editor.action.organizeImports',
|
||||
title: 'Organize Imports',
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
actions,
|
||||
dispose: () => {},
|
||||
};
|
||||
},
|
||||
});
|
||||
}
|
412
src/lib/monaco-config.ts
Normal file
412
src/lib/monaco-config.ts
Normal file
@@ -0,0 +1,412 @@
|
||||
import * as monaco from 'monaco-editor';
|
||||
import { registerCodeActionProvider } from './eslint-integration';
|
||||
|
||||
// TypeScript 默认编译选项
|
||||
export const defaultCompilerOptions: monaco.languages.typescript.CompilerOptions = {
|
||||
target: monaco.languages.typescript.ScriptTarget.Latest,
|
||||
allowNonTsExtensions: true,
|
||||
moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
|
||||
module: monaco.languages.typescript.ModuleKind.ESNext,
|
||||
noEmit: true,
|
||||
esModuleInterop: true,
|
||||
jsx: monaco.languages.typescript.JsxEmit.React,
|
||||
reactNamespace: 'React',
|
||||
allowJs: true,
|
||||
typeRoots: ['node_modules/@types'],
|
||||
lib: ['es2020', 'dom', 'dom.iterable', 'esnext'],
|
||||
strict: true,
|
||||
skipLibCheck: true,
|
||||
forceConsistentCasingInFileNames: true,
|
||||
resolveJsonModule: true,
|
||||
isolatedModules: true,
|
||||
noUnusedLocals: true,
|
||||
noUnusedParameters: true,
|
||||
noImplicitReturns: true,
|
||||
noFallthroughCasesInSwitch: true,
|
||||
};
|
||||
|
||||
// JavaScript 默认编译选项
|
||||
export const jsCompilerOptions: monaco.languages.typescript.CompilerOptions = {
|
||||
...defaultCompilerOptions,
|
||||
strict: false,
|
||||
noUnusedLocals: false,
|
||||
noUnusedParameters: false,
|
||||
checkJs: true,
|
||||
allowJs: true,
|
||||
};
|
||||
|
||||
// 配置 TypeScript 语言服务
|
||||
export function configureMonacoTypescript() {
|
||||
// 配置 TypeScript 默认选项
|
||||
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(defaultCompilerOptions);
|
||||
|
||||
// 配置 JavaScript 默认选项
|
||||
monaco.languages.typescript.javascriptDefaults.setCompilerOptions(jsCompilerOptions);
|
||||
|
||||
// 设置诊断选项
|
||||
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
|
||||
noSemanticValidation: false,
|
||||
noSyntaxValidation: false,
|
||||
noSuggestionDiagnostics: false,
|
||||
});
|
||||
|
||||
monaco.languages.typescript.javascriptDefaults.setDiagnosticsOptions({
|
||||
noSemanticValidation: false,
|
||||
noSyntaxValidation: false,
|
||||
noSuggestionDiagnostics: false,
|
||||
});
|
||||
|
||||
// 启用格式化选项
|
||||
monaco.languages.typescript.typescriptDefaults.setEagerModelSync(true);
|
||||
monaco.languages.typescript.javascriptDefaults.setEagerModelSync(true);
|
||||
}
|
||||
|
||||
// 添加常用类型定义
|
||||
export async function addTypeDefinitions() {
|
||||
const typeDefs = [
|
||||
{
|
||||
name: '@types/react',
|
||||
content: `
|
||||
declare module "react" {
|
||||
export interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
|
||||
type: T;
|
||||
props: P;
|
||||
key: Key | null;
|
||||
}
|
||||
export type FC<P = {}> = FunctionComponent<P>;
|
||||
export interface FunctionComponent<P = {}> {
|
||||
(props: P, context?: any): ReactElement<any, any> | null;
|
||||
}
|
||||
export function useState<S>(initialState: S | (() => S)): [S, Dispatch<SetStateAction<S>>];
|
||||
export function useEffect(effect: EffectCallback, deps?: DependencyList): void;
|
||||
export function useCallback<T extends Function>(callback: T, deps: DependencyList): T;
|
||||
export function useMemo<T>(factory: () => T, deps: DependencyList): T;
|
||||
export function useRef<T>(initialValue: T): MutableRefObject<T>;
|
||||
}
|
||||
`
|
||||
},
|
||||
{
|
||||
name: '@types/node',
|
||||
content: `
|
||||
declare module "fs" {
|
||||
export function readFileSync(path: string, encoding?: string): string | Buffer;
|
||||
export function writeFileSync(path: string, data: string | Buffer): void;
|
||||
}
|
||||
declare module "path" {
|
||||
export function join(...paths: string[]): string;
|
||||
export function resolve(...paths: string[]): string;
|
||||
}
|
||||
`
|
||||
}
|
||||
];
|
||||
|
||||
for (const typeDef of typeDefs) {
|
||||
monaco.languages.typescript.typescriptDefaults.addExtraLib(
|
||||
typeDef.content,
|
||||
`file:///node_modules/${typeDef.name}/index.d.ts`
|
||||
);
|
||||
monaco.languages.typescript.javascriptDefaults.addExtraLib(
|
||||
typeDef.content,
|
||||
`file:///node_modules/${typeDef.name}/index.d.ts`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 注册自定义主题
|
||||
export function registerCustomThemes() {
|
||||
// VS Code Dark+ 主题
|
||||
monaco.editor.defineTheme('vs-dark-plus', {
|
||||
base: 'vs-dark',
|
||||
inherit: true,
|
||||
rules: [
|
||||
{ token: 'comment', foreground: '6A9955' },
|
||||
{ token: 'keyword', foreground: '569CD6' },
|
||||
{ token: 'string', foreground: 'CE9178' },
|
||||
{ token: 'number', foreground: 'B5CEA8' },
|
||||
{ token: 'type', foreground: '4EC9B0' },
|
||||
{ token: 'class', foreground: '4EC9B0' },
|
||||
{ token: 'function', foreground: 'DCDCAA' },
|
||||
{ token: 'variable', foreground: '9CDCFE' },
|
||||
{ token: 'constant', foreground: '4FC1FF' },
|
||||
{ token: 'parameter', foreground: '9CDCFE' },
|
||||
{ token: 'property', foreground: '9CDCFE' },
|
||||
{ token: 'regexp', foreground: 'D16969' },
|
||||
{ token: 'operator', foreground: 'D4D4D4' },
|
||||
{ token: 'namespace', foreground: '4EC9B0' },
|
||||
{ token: 'type.identifier', foreground: '4EC9B0' },
|
||||
{ token: 'tag', foreground: '569CD6' },
|
||||
{ token: 'attribute.name', foreground: '9CDCFE' },
|
||||
{ token: 'attribute.value', foreground: 'CE9178' },
|
||||
],
|
||||
colors: {
|
||||
'editor.background': '#1E1E1E',
|
||||
'editor.foreground': '#D4D4D4',
|
||||
'editorLineNumber.foreground': '#858585',
|
||||
'editorCursor.foreground': '#AEAFAD',
|
||||
'editor.selectionBackground': '#264F78',
|
||||
'editor.inactiveSelectionBackground': '#3A3D41',
|
||||
'editorIndentGuide.background': '#404040',
|
||||
'editorIndentGuide.activeBackground': '#707070',
|
||||
'editor.wordHighlightBackground': '#515C6A',
|
||||
'editor.wordHighlightStrongBackground': '#515C6A',
|
||||
'editorError.foreground': '#F48771',
|
||||
'editorWarning.foreground': '#CCA700',
|
||||
'editorInfo.foreground': '#75BEFF',
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 配置 JSON 语言
|
||||
export function configureJsonLanguage() {
|
||||
monaco.languages.json.jsonDefaults.setDiagnosticsOptions({
|
||||
validate: true,
|
||||
schemas: [
|
||||
{
|
||||
uri: 'http://json-schema.org/draft-07/schema#',
|
||||
fileMatch: ['*.json'],
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
additionalProperties: true
|
||||
}
|
||||
},
|
||||
{
|
||||
uri: 'http://json.schemastore.org/package',
|
||||
fileMatch: ['package.json'],
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
version: { type: 'string' },
|
||||
dependencies: { type: 'object' },
|
||||
devDependencies: { type: 'object' },
|
||||
scripts: { type: 'object' }
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
uri: 'http://json.schemastore.org/tsconfig',
|
||||
fileMatch: ['tsconfig.json', 'tsconfig.*.json'],
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
compilerOptions: { type: 'object' },
|
||||
include: { type: 'array' },
|
||||
exclude: { type: 'array' }
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
allowComments: true,
|
||||
trailingCommas: 'warning'
|
||||
});
|
||||
}
|
||||
|
||||
// 添加代码片段
|
||||
export function registerSnippets() {
|
||||
// TypeScript/JavaScript 代码片段
|
||||
monaco.languages.registerCompletionItemProvider(['typescript', 'javascript', 'typescriptreact', 'javascriptreact'], {
|
||||
provideCompletionItems: (model, position) => {
|
||||
const word = model.getWordUntilPosition(position);
|
||||
const range = {
|
||||
startLineNumber: position.lineNumber,
|
||||
endLineNumber: position.lineNumber,
|
||||
startColumn: word.startColumn,
|
||||
endColumn: word.endColumn
|
||||
};
|
||||
|
||||
const suggestions = [
|
||||
{
|
||||
label: 'log',
|
||||
kind: monaco.languages.CompletionItemKind.Snippet,
|
||||
insertText: 'console.log(${1:message});',
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
documentation: 'Console log statement',
|
||||
range
|
||||
},
|
||||
{
|
||||
label: 'useState',
|
||||
kind: monaco.languages.CompletionItemKind.Snippet,
|
||||
insertText: 'const [${1:state}, set${1/(.*)/${1:/capitalize}/}] = useState(${2:initialValue});',
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
documentation: 'React useState hook',
|
||||
range
|
||||
},
|
||||
{
|
||||
label: 'useEffect',
|
||||
kind: monaco.languages.CompletionItemKind.Snippet,
|
||||
insertText: [
|
||||
'useEffect(() => {',
|
||||
'\t${1:// Effect logic}',
|
||||
'\treturn () => {',
|
||||
'\t\t${2:// Cleanup}',
|
||||
'\t};',
|
||||
'}, [${3:dependencies}]);'
|
||||
].join('\n'),
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
documentation: 'React useEffect hook',
|
||||
range
|
||||
},
|
||||
{
|
||||
label: 'component',
|
||||
kind: monaco.languages.CompletionItemKind.Snippet,
|
||||
insertText: [
|
||||
'const ${1:ComponentName}: React.FC = () => {',
|
||||
'\treturn (',
|
||||
'\t\t<div>',
|
||||
'\t\t\t${2:content}',
|
||||
'\t\t</div>',
|
||||
'\t);',
|
||||
'};',
|
||||
'',
|
||||
'export default ${1:ComponentName};'
|
||||
].join('\n'),
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
documentation: 'React functional component',
|
||||
range
|
||||
},
|
||||
{
|
||||
label: 'async',
|
||||
kind: monaco.languages.CompletionItemKind.Snippet,
|
||||
insertText: [
|
||||
'async function ${1:functionName}() {',
|
||||
'\ttry {',
|
||||
'\t\tconst result = await ${2:promise};',
|
||||
'\t\t${3:// Handle result}',
|
||||
'\t} catch (error) {',
|
||||
'\t\tconsole.error(error);',
|
||||
'\t}',
|
||||
'}'
|
||||
].join('\n'),
|
||||
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
||||
documentation: 'Async function with try-catch',
|
||||
range
|
||||
}
|
||||
];
|
||||
|
||||
return { suggestions };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 配置语言特性
|
||||
export function configureLanguageFeatures() {
|
||||
// 配置 HTML 标签自动闭合
|
||||
monaco.languages.registerOnTypeFormattingEditProvider(['html', 'xml', 'javascriptreact', 'typescriptreact'], {
|
||||
autoFormatTriggerCharacters: ['>'],
|
||||
provideOnTypeFormattingEdits: (model, position, ch) => {
|
||||
if (ch === '>') {
|
||||
const lineContent = model.getLineContent(position.lineNumber);
|
||||
const beforeCursor = lineContent.substring(0, position.column - 1);
|
||||
|
||||
// 检查是否是开始标签
|
||||
const tagMatch = beforeCursor.match(/<(\w+)(?:\s+[^>]*)?>/);
|
||||
if (tagMatch) {
|
||||
const tagName = tagMatch[1];
|
||||
// 自闭合标签列表
|
||||
const selfClosingTags = ['img', 'br', 'hr', 'input', 'meta', 'link'];
|
||||
if (!selfClosingTags.includes(tagName.toLowerCase())) {
|
||||
return [{
|
||||
range: {
|
||||
startLineNumber: position.lineNumber,
|
||||
startColumn: position.column,
|
||||
endLineNumber: position.lineNumber,
|
||||
endColumn: position.column
|
||||
},
|
||||
text: `</${tagName}>`
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
});
|
||||
|
||||
// 配置括号自动配对
|
||||
monaco.languages.setLanguageConfiguration('typescript', {
|
||||
autoClosingPairs: [
|
||||
{ open: '{', close: '}' },
|
||||
{ open: '[', close: ']' },
|
||||
{ open: '(', close: ')' },
|
||||
{ open: '"', close: '"' },
|
||||
{ open: "'", close: "'" },
|
||||
{ open: '`', close: '`' },
|
||||
{ open: '<', close: '>' },
|
||||
],
|
||||
surroundingPairs: [
|
||||
{ open: '{', close: '}' },
|
||||
{ open: '[', close: ']' },
|
||||
{ open: '(', close: ')' },
|
||||
{ open: '"', close: '"' },
|
||||
{ open: "'", close: "'" },
|
||||
{ open: '`', close: '`' },
|
||||
{ open: '<', close: '>' },
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
// 初始化 Monaco Editor 配置
|
||||
export async function initializeMonaco() {
|
||||
// 配置 TypeScript/JavaScript
|
||||
configureMonacoTypescript();
|
||||
|
||||
// 添加类型定义
|
||||
await addTypeDefinitions();
|
||||
|
||||
// 注册自定义主题
|
||||
registerCustomThemes();
|
||||
|
||||
// 配置 JSON
|
||||
configureJsonLanguage();
|
||||
|
||||
// 注册代码片段
|
||||
registerSnippets();
|
||||
|
||||
// 配置语言特性
|
||||
configureLanguageFeatures();
|
||||
|
||||
// 注册代码操作提供器(快速修复)
|
||||
registerCodeActionProvider();
|
||||
}
|
||||
|
||||
// 格式化文档
|
||||
export function formatDocument(editor: monaco.editor.IStandaloneCodeEditor) {
|
||||
editor.getAction('editor.action.formatDocument')?.run();
|
||||
}
|
||||
|
||||
// 添加错误标记
|
||||
export function addErrorMarkers(
|
||||
editor: monaco.editor.IStandaloneCodeEditor,
|
||||
errors: Array<{
|
||||
line: number;
|
||||
column: number;
|
||||
message: string;
|
||||
severity: 'error' | 'warning' | 'info';
|
||||
}>
|
||||
) {
|
||||
const model = editor.getModel();
|
||||
if (!model) return;
|
||||
|
||||
const markers = errors.map(error => ({
|
||||
severity: error.severity === 'error'
|
||||
? monaco.MarkerSeverity.Error
|
||||
: error.severity === 'warning'
|
||||
? monaco.MarkerSeverity.Warning
|
||||
: monaco.MarkerSeverity.Info,
|
||||
startLineNumber: error.line,
|
||||
startColumn: error.column,
|
||||
endLineNumber: error.line,
|
||||
endColumn: error.column + 1,
|
||||
message: error.message,
|
||||
}));
|
||||
|
||||
monaco.editor.setModelMarkers(model, 'owner', markers);
|
||||
}
|
||||
|
||||
// 清除错误标记
|
||||
export function clearErrorMarkers(editor: monaco.editor.IStandaloneCodeEditor) {
|
||||
const model = editor.getModel();
|
||||
if (model) {
|
||||
monaco.editor.setModelMarkers(model, 'owner', []);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user