模板语言
HTML 代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Monaco Template Editor</title>
<style>
html,
body {
margin: 0;
padding: 0;
height: 100%;
overflow: hidden;
}
#container {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs/loader.min.js"></script>
<script>
require.config({ paths: { 'vs': 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.45.0/min/vs' } });
require(['vs/editor/editor.main'], function () {
const availableVariables = [
{ label: 'userName', detail: '用户姓名', insertText: 'userName' },
{ label: 'company.name', detail: '公司名称', insertText: 'company.name' },
{ label: 'company.address', detail: '公司地址', insertText: 'company.address' },
{ label: 'order.id', detail: '订单ID', insertText: 'order.id' }
];
const LANGUAGE_ID = 'my-template-lang';
monaco.languages.register({ id: LANGUAGE_ID });
monaco.languages.setLanguageConfiguration(LANGUAGE_ID, {
autoClosingPairs: [
{ open: '{{', close: '}}' }, // 输入 {{ 自动补全 }}
{ open: '{', close: '}' }, // 输入 { 自动补全 }
{ open: '"', close: '"' },
{ open: "'", close: "'" }
]
});
monaco.languages.setMonarchTokensProvider(LANGUAGE_ID, {
tokenizer: {
root: [
[/\{\{/, { token: 'delimiter.curly', next: '@expression' }],
[/[^\{]+/, 'string']
],
expression: [
[/[\w\.]+/, 'variable.custom'],
[/\}\}/, { token: 'delimiter.curly', next: '@pop' }],
[/\s+/, '']
]
}
});
monaco.editor.defineTheme('my-template-theme', {
base: 'vs-dark',
inherit: true,
rules: [
{ token: 'variable.custom', foreground: '9CDCFE', fontStyle: 'bold' },
{ token: 'delimiter.curly', foreground: 'C586C0' },
],
colors: {}
});
monaco.languages.registerCompletionItemProvider(LANGUAGE_ID, {
triggerCharacters: ['{', ' ', '.'], // 触发字符包含点号
provideCompletionItems: function (model, position) {
const textUntilPosition = model.getValueInRange({
startLineNumber: position.lineNumber,
startColumn: 1,
endLineNumber: position.lineNumber,
endColumn: position.column
});
// 检测是否在 {{ }} 内
const match = textUntilPosition.match(/\{\{([^}]*)$/);
if (!match) {
return { suggestions: [] };
}
// 核心修复:手动计算当前正在输入的单词范围(包含点号)
// 匹配光标前连续的 字母、数字、下划线、点号
const wordMatch = textUntilPosition.match(/([a-zA-Z0-9_\.]+)$/);
let startColumn = position.column;
if (wordMatch) {
startColumn = position.column - wordMatch[0].length;
}
const range = {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: startColumn,
endColumn: position.column
};
const suggestions = availableVariables.map(vari => ({
label: vari.label,
kind: monaco.languages.CompletionItemKind.Variable,
detail: vari.detail,
insertText: vari.insertText,
range: range // 使用手动计算的范围进行替换
}));
return { suggestions: suggestions };
}
});
monaco.editor.create(document.getElementById('container'), {
value: "输入 {{}}",
language: LANGUAGE_ID,
theme: 'my-template-theme',
fontSize: 14
});
});
</script>
</body>
</html>