Gyron 在线编辑器

126 阅读1分钟

经过一段时间的折腾,终于弄出一个简单版的在线编辑器,支持实时预览、语法纠错、语法高亮、智能跳转等功能。

语言的话目前支持 jsx、tsx、less,并且还支持加载在线资源,比如import { h } from 'https://cdn.jsdelivr.net/npm/gyron'

因为所有数据都不保存在远端,只保存在本地,所以没有使用 standalone 沙盒技术隔离运行环境,也没有防范 xss 攻击。

现在,可以访问gyron.cc/explorer这个地址在线体验。

核心理念

构建

首先,需要使用一个支持浏览器侧的打包工具,我选择的 esbuild

然后需要实现一套本地的虚拟文件系统,让打包工具能够正常访问到对应的本地资源。而在 esbuild 中实现一套虚拟文件系统其实很简单,只需要编写一个插件,然后用 resolve 和 load 两种勾子就可以将本地文件输出到 esbuild 中。

const buildModuleRuntime = {
  name: "buildModuleRuntime",
  setup(build) {
    build.onResolve({ filter: /.// }, (args) => {
      return {
        path: args.path,
        namespace: "localModule",
      };
    });
    build.onLoad({ filter: /.//, namespace: "localModule" }, async (args) => {
      // 具体实现可以去github https://github.com/gyronorg/core/blob/main/packages/babel-plugin-jsx/src/browser.ts
      const source = findSourceCode(config.sources, args.path);

      if (source) {
        const filename = getFileName(args, source.loader);
        const result = await transformWithBabel(
          source.code,
          filename,
          main,
          true
        );
        return {
          contents: result.code,
        };
      }
      return {
        contents: "",
        loader: "text",
        warnings: [
          {
            pluginName: "buildModuleRuntime",
            text: `Module "${args.path}" is not defined in the local editor`,
          },
        ],
      };
    });
  },
};

然后会输出一个 module 文件,最终只需要将文件塞到 script 中让其运行。

在页面中引用多个编辑器,需要注意的是在不用这个 module 文件后及时删除。可以使用命名空间给 module 加上一个标签,新增和删除都使用这个命名空间作为变量控制当前运行时的资源。