跳至主要內容

在插件内使用代码编辑器

muzzik大约 2 分钟文章CocosCocosCreator 插件

# 效果

# 前言

由于使用坑比较多,所以开贴记录

# 选择

市面上流行的编辑器有 Ace,Monaco,还有比较小众的 CodeMirror

这里有比较帖,可以看看,跳转链接open in new window

这里说说自己的使用感受

  • Ace
    • 好处: 轻量级,有官方文档,使用简单
    • 坏处: Typescript 没有类型提示,没有报错提示,全部需要自己接
  • Monaco
    • 好处:vscode 核心,使用体验堪比 vscode,还可以接入部分插件
    • 坏处:没有官方文档,入门困难
      经过体验后最终选择了 monaco 编辑器,只怪语法提示太香

# 接入

1. 安装 npm 包

npm i monaco-editor

2. 添加 css

    将下面的 link 标签放在 Editor.Panel.define 导出的 template 中

<link
	rel="stylesheet"
	href="替换为插件目录/node_modules/monaco-editor/min/vs/editor/editor.main.css"
></link>

3. 使用加载器
ps: 由于 monaco 编辑器只有 esm 模块和 amd 模块,我们的插件不能直接使用,除了 webpack 等打包工具,还可以直接用 min 版本提供的 loader 加载器加载

/** monaco 加载器 */
const monaco_loader = require(path.join(
	替换为插件目录,
	"node_modules/monaco-editor/min/vs/loader"
));

// monaco 加载器配置
monaco_loader.require.config({
	paths: {
		vs: path.join(替换为插件目录, "node_modules/monaco-editor/min/vs"),
	},
	// 本地化
	"vs/nls": {
		availableLanguages: { "*": "zh-cn" },
	},
});

4. 加载编辑器并初始化

这里注意我们查找的标签类名为 editor,也就是<div class="editor"></div>才是编辑器的标签,当然也可以自行修改

  • ts:typescript 模块,自行 npm i typescriptimport ts from "typescript";
// 加载编辑器并初始化
monaco_loader.require(
	["vs/editor/editor.main"],
	(monaco: typeof import("monaco-editor")) => {
		/** 编辑器元素 */
		let editor_element_as = (this.$el as HTMLElement).getElementsByClassName(
			"editor"
		);
		if (!editor_element_as.length) {
			return;
		}

    	// 引用 cc.d.ts
    	{
    		let file_s = fs.readFileSync(
    			path.join(Editor.Project.path, "temp/declarations/cc.d.ts"),
    			"utf-8"
    		);
    		let reg_as = file_s.match(/(?<=<reference path=")([^"]*)(?=")/g);
    		if (reg_as?.length) {
    			monaco.languages.typescript.typescriptDefaults.addExtraLib(
    				fs.readFileSync(reg_as[0], "utf-8").replace('"cc"', "cc"),
    				"cc.d.ts"
    			);
    		}
    	}

    	/** 当前编辑器 model */
    	let curr_model = monaco.editor.createModel(
    		``,
    		"typescript",
    		monaco.Uri.parse(`main.ts`)
    	);

    	/** 项目 tsconfig 解析 */
    	let tsconfig_parse: ts.ParsedCommandLine;
    	{
    		/** 配置路径 */
    		let tsconfig_path_s = path.join(Editor.Project.path, "tsconfig.json");
    		let tsconfig = ts.readConfigFile(
    			path.join(Editor.Project.path, "tsconfig.json"),
    			ts.sys.readFile
    		);
    		if (!tsconfig.error) {
    			 tsconfig_parse = ts.parseJsonConfigFileContent(
    				tsconfig.config,
    				ts.sys,
    				path.dirname(tsconfig_path_s)
    			);
    		}
    	}

    	for (let k_n = 0, length_n = editor_element_as.length; k_n < length_n; k_n++) {
    		let element = editor_element_as.item(k_n) as HTMLElement;

    		// 初始化编辑器
    		let editor = monaco.editor.create(element, {
    			value: [""].join("\n"),
    			language: "typescript",
    			theme: "vs-dark",
    			model: curr_model,
    		});

    		// 设置编译配置
    		if (tsconfig_parse) {
    			monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
    				tsconfig_parse.options as any
    			);
    		}

    		// 防止编辑器初始化时元素未展示导致展示错误
    		new ResizeObserver(() => {
    			editor.layout();
    		}).observe(element);
    	}
    }

);

# 使用

1. 如何将文件夹设为工作区?

    这里大家记住,monaco 编辑器没有工作区的概念,而是将每个文件都视为一个 Model,我们只需要使用 monaco.editor.createModel

// 示例
monaco.editor.createModel(
	// 文件内容字符串
	`export class Test {}`,
	// 语言类型
	"typescript",
	// 文件路径,xxx/xxx.ts
	monaco.Uri.parse(`Test.ts`)
);

结语

📣 觉得很赞?分享给你的朋友吧!