Ace(Ajax.org Cloud9 Editor)嵌入、运行与构建完全指南
【免费下载链接】aceAce (Ajax.org Cloud9 Editor)项目地址: https://gitcode.com/gh_mirrors/ac/ace
Ace 是一款用 JavaScript 编写的独立浏览器代码编辑器,目标是在浏览器中复现并超越 TextMate、Vim、Eclipse 等原生编辑器的功能、易用性与性能。本篇指南以 Ace 官方 README(仓库根目录 Readme.md)为主线,结合本仓库源码(src/ace.js、src/config.js、static.js、Makefile.dryice.js、package.json)逐层讲解:如何把 Ace 嵌入任意网页、如何本地运行与调试、如何按需构建打包、如何运行单元测试,以及配置项与构建参数的底层实现原理。
一、Ace 是什么:项目定位与核心特性
Ace(全称 Ajax.org Cloud9 Editor)是 Cloud9 IDE 的主编辑器,也是 Mozilla Skywriter(Bespin)项目的后继者。它不依赖任何后端服务,可以轻松嵌入任意网页或 JavaScript 应用中,其主入口文件为 src/ace.js,当前仓库版本为1.44.0(见 package.json)。
根据官方 README,Ace 的核心特性包括:
- 超过 120 种语言的语法高亮,且可直接导入 TextMate / Sublime 的
tmlanguage语法文件; - 超过 20 套主题,可直接导入 TextMate / Sublime 的
tmtheme主题文件; - 自动缩进与反缩进(indent / outdent);
- 可选命令行(Command Line);
- 支持超大文档(官方记录的上限为 4,000,000 行);
- 完全可自定义的键位绑定,内置 Vim 与 Emacs 模式(对应 src/keyboard/vim.js、src/keyboard/emacs.js);
- 支持正则表达式的查找与替换(src/search.js);
- 匹配括号高亮;
- 软 Tab 与真实 Tab 切换;
- 显示隐藏字符;
- 鼠标拖放文本;
- 自动换行(Line wrapping);
- 代码折叠(Code Folding);
- 多光标与多选区(src/multi_select.js);
- 实时语法检查(目前支持 JavaScript / CoffeeScript / CSS / XQuery,通过 Web Worker 实现);
- 通过 ace-linters 为众多语言提供完整的 Language Server 客户端支持;
- 完整的剪切、复制、粘贴功能。
从仓库结构看,这些能力被组织为高度模块化的 AMD 模块:mode/目录存放语言模式与高亮规则(如 src/mode/javascript.js、src/mode/javascript_highlight_rules.js),theme/目录存放主题(如 src/theme/twilight.js),ext/目录存放扩展(如 src/ext/statusbar.js、src/ext/settings_menu.js),这为按需加载与自定义扩展提供了清晰的边界。
二、快速体验:先跑起来再说
在动手嵌入之前,最快的体验方式是官方在线 demo(kitchen-sink,厨房水槽式全功能演示页)。本仓库中对应的源码位于 demo/kitchen-sink/demo.js,演示页入口为根目录的 kitchen-sink.html。此外,也可以注册 Cloud9 IDE 账号,在编辑自己 GitHub 项目的同时体验 Ace 的完整能力。
如果只想把 Ace 当作 textarea 的替代品,还可以使用 Ace Bookmarklet:将书签指向 Bookmarklet 版本后,在任意页面点击书签,页面上的 textarea 就会被替换为 Ace 编辑器实例。仓库中 Bookmarklet 的构建逻辑由 Makefile.dryice.js 的-bm选项负责。
三、嵌入 Ace:五步上手
官方 README 强调,Ace 可以轻易嵌入任何现有网页。有两种方式引入代码:
- 使用预先打包好的 ace-builds 发行包(将其中某个
src*子目录复制进项目); - 使用 requireJS 将本仓库 lib/ace 的内容以模块名
ace加载。
下面是最简嵌入版本,直接使用单文件版本:
<div id="editor">some text</div> <script src="src/ace.js" type="text/javascript" charset="utf-8"></script> <script> var editor = ace.edit("editor"); </script>其中"editor"是会被转换为编辑器的 DOM 元素的 id。注意:该元素必须被显式设定尺寸,且定位方式必须为absolute或relative,否则 Ace 无法正常工作。例如:
#editor { position: absolute; width: 500px; height: 400px; }从源码层面看,ace.edit(src/ace.js#L35-L71)的实际执行流程是:
- 如果传入的是字符串,则通过
document.getElementById查找元素,找不到会抛出ace.edit can't find div #<id>错误; - 如果元素是
input/textarea,会读取其value作为初始内容,并将其替换为一个pre元素(实现 textarea 无损升级); - 否则读取元素的
textContent作为初始内容并清空innerHTML; - 调用
createEditSession创建编辑会话(见 src/ace.js#L79-L83,内部会附加 UndoManager 撤销管理器); - 用
new Editor(new VirtualRenderer(el), doc, options)组合渲染器与编辑会话,并挂载env环境对象与resize回调。
3.1 切换主题
默认情况下编辑器使用textmate主题。要更换主题,先引入主题的 JavaScript 文件:
<script src="src/theme-twilight.js" type="text/javascript" charset="utf-8"></script>再配置编辑器使用该主题:
editor.setTheme("ace/theme/twilight");本仓库中对应的主题实现位于 src/theme/twilight.js,theme/目录下共包含 90+ 套主题,均以ace/theme/<name>作为模块标识。从 src/config.js 的moduleUrl实现可以看到,ace/theme/twilight会被解析为themePath + "theme-twilight" + suffix,即文件名中的目录分隔符被转换为连字符,因此主题文件统一命名为theme-<name>.js。
3.2 设置语言模式
默认情况下编辑器只支持纯文本模式,其他语言以独立模块形式提供。引入语言的模式文件:
<script src="src/mode-javascript.js" type="text/javascript" charset="utf-8"></script>随后通过ace.require加载模式并设置到会话上:
var JavaScriptMode = ace.require("ace/mode/javascript").Mode; editor.session.setMode(new JavaScriptMode());ace.require返回模块对象,其中Mode类负责词汇/语法级的高亮与缩进规则;实际高亮规则定义在同名的javascript_highlight_rules.js中(src/mode/javascript_highlight_rules.js)。editor.session即EditSession(src/edit_session.js),它承载文档模型、折叠、标记(Marker)等状态。
3.3 销毁编辑器
当页面不再需要编辑器时,需要显式销毁以释放事件监听与 DOM 引用:
editor.destroy(); editor.container.remove();destroy()会触发destroy事件——从 src/ace.js#L66-L68 可以看到,编辑器销毁时会清理env.editor.container.env引用,避免旧版本 IE 下的内存泄漏;随后再手动移除容器节点。
3.4 全局配置项(Configuring-Ace)
Ace 的核心配置由 src/config.js 暴露的config单例管理,其预置选项(src/config.js#L11-L22)包括:
| 配置项 | 默认值 | 说明 |
|---|---|---|
packaged | false | 是否运行在打包构建版本中 |
workerPath | null | Web Worker 脚本所在路径(实时语法检查用) |
modePath | null | 语言模式模块路径前缀 |
themePath | null | 主题模块路径前缀 |
basePath | "" | 上述路径未指定时使用的公共基础路径 |
suffix | ".js" | 模块文件后缀 |
loadWorkerFromBlob | true | 是否通过 Blob 加载 Worker |
sharedPopups | false | 是否共享弹出层(如自动补全弹窗) |
useStrictCSP | null | 严格 CSP 模式开关 |
使用方式为ace.config.set("themePath", "/vendor/ace/")或ace.config.get(key)(src/config.js#L29-L47)。当modePath/themePath未设置时,模块 URL 由moduleUrl()依据basePath、组件名与连字符命名规则推导(src/config.js#L63-L89)。此外还可通过ace.config.setModuleUrl(name, url)为单个模块指定精确地址(src/config.js#L95-L97),或用ace.config.setLoader(fn)自定义模块加载器。
四、本地运行 Ace:零构建,开箱即用
官方 README 明确说明:clone 之后 Ace 即可直接运行,无需任何构建步骤。仓库根目录的 static.js 是一个用 Node.js 内置http模块实现的迷你 HTTP 服务器(约 170 行),启动方式:
node ./static.js随后在浏览器打开:
http://localhost:8888/kitchen-sink.html从 static.js 源码可以看到几个实用的运行细节:
- 端口与监听地址可通过环境变量覆盖:
PORT(默认8888)与IP(默认0.0.0.0),启动时会打印实际的访问地址(static.js#L7-L8、static.js#L170); - 服务器支持目录索引浏览(自动生成带文件大小的 HTML 目录页,static.js#L89-L124),并做了目录穿越防护(static.js#L42-L44);
- 支持
OPTIONS/PUT方法:默认禁止写入,需显式加--allow-save参数开启浏览器端文件保存(static.js#L32-L34、static.js#L51-L55); - 静态文件响应头带有
Access-Control-Allow-Origin: file://,允许file://协议页面跨源读取(static.js#L79-L84)。
如果希望直接以file:///URL 打开编辑器页面(不经由 HTTP 服务器),可以查阅仓库内 wiki 相关说明(Running-Ace-from-file)。
五、构建 Ace:何时需要,如何操作
大多数情况下你不需要自行构建:ace-builds 发行仓库会持续维护最新构建产物,直接复制其中某个src*子目录到项目即可。但若需要自定义打包,只需安装 Node.js 与 npm,然后:
npm install node ./Makefile.dryice.jsAce 的打包工具是 dryice(由 Mozilla Skywriter 团队开发)。运行node Makefile.dryice.js即开始打包,该构建脚本支持以下选项:
-m minify build files with uglify-js -nc namespace require and define calls with "ace" -bm builds the bookmarklet version --target ./path specify relative path for output folder (default value is "./build")各参数含义(与 Makefile.dryice.js 中的帮助文本对应,见 showHelp):
-m:用 uglify-js 压缩构建产物,对应源码中compress标记(Makefile.dryice.js#L130);-nc:将require/define调用命名空间化为ace前缀,避免与页面中其他 AMD 库冲突;-bm:额外产出 Bookmarklet 版本;--target ./path:指定输出目录(默认./build),对应BUILD_DIR的覆盖逻辑(Makefile.dryice.js#L108-L110);- 另有未写入 README 的
-s(shrinkwrap,将所有输出合并为单文件)等标志,可通过-h查看完整帮助。
构建还支持若干目标类型,用法为node Makefile.dryice.js <type>:
| type | 作用 |
|---|---|
minimal | 默认值,将必要文件输出到 build 目录 |
normal | 依次构建 minimal、minimal-noconflict、minimal-min、minimal-noconflict-min 四种组合 |
demo | 构建 kitchen-sink 演示应用 |
full | 上述全部 |
css | 抽取 CSS 样式文件 |
nls | 抽取多语言(NLS)消息文件 |
要生成 ace-builds 仓库中的全套文件,运行:
node Makefile.dryice.js full --target ../ace-builds从实现细节看,构建的第一步是generateAmdModules()(Makefile.dryice.js#L48-L91):它遍历 src 目录,用 TypeScript 编译器把每个.js模块转译为 ES5 并包裹进define(function(require, exports, module){ ... }),输出到lib/ace(即 README 所说 requireJS 加载的lib/ace内容来源)。随后buildAce根据-m/-nc/-s组合出不同发行变体,buildTypes(Makefile.dryice.js#L197-L254)还会同步生成ace.d.ts类型声明、webpack-resolver.js与esm-resolver.js加载器,方便 Webpack 与原生 ESM 环境使用。
六、运行单元测试:Node 与浏览器两种方式
Ace 的单元测试可以在 Node.js 上直接运行。假设已经执行过npm install,只需:
npm run test该命令对应 package.json 中的"test": "mocha \"./src/**/*_test.js\" --exit -p --color",即用 mocha 递归执行src下所有*_test.js测试文件(如 src/document_test.js、src/search_test.js、src/editor_test.js 等数百个测试模块)。
也可以在浏览器中运行测试,便于调试失败的用例:
http://localhost:8888/src/test/tests.html浏览器测试入口为 src/test/tests.html,它通过 src/test/all.js 聚合全部测试模块;测试基础设施还包括 mock DOM(src/test/mockdom.js)与 mock 渲染器(src/test/mockrenderer.js),使得编辑器可以在无真实浏览器布局的环境中被驱动验证。此外,仓库还提供覆盖率统计(npm run cover,基于 c8)与类型检查(npm run typecheck,基于 TypeScript 与 tsconfig.json)。
七、更多资源与参与贡献
- 事件监听、语法高亮扩展等进阶用法,见仓库文档目录 doc/README.md 与 doc/index.md;
- API 文档可参考仓库内的类型声明文件 ace.d.ts 与 types/ace-lib.d.ts;
- kitchen-sink 演示应用的完整示例代码即 demo/kitchen-sink/demo.js,其中展示了多编辑器布局、
ace/ext/rtl、ace/ext/diff、ace/ext/whitespace、增量搜索、令牌悬停提示(TokenTooltip)等扩展的接法; - diff 视图的独立示例见 demo/diff/index.html,静态高亮示例见 demo/static-highlighter/client.html;
- 遇到问题可以到项目 discussions 页面提问。
Ace 是社区项目,官方鼓励并支持一切形式的贡献。源码以 BSD License 发布(见 LICENSE),该许可非常宽松,对开源与非开源项目都友好——你可以 fork 后任意改进,也可以按需为编辑器添加自己喜爱的语言高亮与键位绑定。若你认为改动对 Ace 或社区有益,欢迎提交 Pull Request;贡献规范详见 CONTRIBUTING.md。
【免费下载链接】aceAce (Ajax.org Cloud9 Editor)项目地址: https://gitcode.com/gh_mirrors/ac/ace
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考