npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

monaco-editor-full

v0.55.1-full.3

Published

A browser based code editor

Readme

Monaco Editor(xiezhongfu fork)

本仓库microsoft/monaco-editor 的个人 fork,在官方版本基础上新增了若干扩展功能。官方文档请参阅 上游 README


与官方版本的差异

| # | 差异项 | 官方版本 | 本 fork | |---|--------|----------|---------| | 1 | 核心依赖 | monaco-editor-core | monaco-editor-core-full(更多未裁剪模块),当前 0.55.1-full.2 | | 1 | 构建产物 / 包名 | out/monaco-editor / monaco-editor | out/monaco-editor-full / monaco-editor-full,版本号追加 -full 后缀 | | 2 | Hover 自定义 DOM 渲染 | 不支持,MarkdownString.domElement 会被过滤或经 DOMPurify 清洗 | 支持,domElement 字段存在时直接挂载,完全绕过 DOMPurify | | 2 | exports 通配符映射 | ./*./esm/vs/*(强制重定向) | ./*./*(顶层直通,任意路径可导入) | | 3 | ML 语言自动检测 | 不支持(workbench 层能力,浏览器侧无) | 内置,支持神经网络 + 正则双模型,自动 / 手动两种模式 | | 4 | LLM 语言检测 | 不支持 | 内置,适配器模式,手动触发,LRU 缓存 |


1. 依赖 monaco-editor-core-full & 输出包名变更

官方 monaco-editor 依赖 monaco-editor-core;本 fork 切换为自定义的 monaco-editor-core-full(同样由 VS Code 源码生成,但包含了更多未裁剪的模块),当前版本为 0.55.1-full.2

构建产物也相应重命名:输出目录由 out/monaco-editor 改为 out/monaco-editor-full,发布包名为 monaco-editor-full,版本号在原版本号后追加 -full 后缀(如 0.55.1-full)。


2. monaco-editor-core-full 补丁整合

monaco-editor-core-full 依赖包打了三处补丁,弥补上游缺失的能力。补丁通过 patch-package 管理,npm install 后自动应用到 node_modules,消费方无需任何额外操作。


① 支持在 Hover 中直接渲染 DOM 节点

  • 改动文件esm/vs/base/common/htmlContent.jsisEmptyMarkdownString
  • 问题:上游 isEmptyMarkdownString 只检查 value 字段是否为空,当 MarkdownString 携带自定义 domElement 字段时会被误判为空串,导致 Hover 内容被过滤掉、永远不渲染。
  • 改动:在 isMarkdownString 分支中优先判断 domElement instanceof HTMLElement,若存在则直接返回 false(非空)。
  • 效果domElement 字段的 MarkdownString 能正常进入渲染流程,不再被提前丢弃。

② Hover 渲染时绕过 DOMPurify sanitize

  • 改动文件esm/vs/editor/contrib/hover/browser/markdownHoverParticipant.jsrenderMarkdown
  • 问题:上游 renderMarkdown 统一走 markdownRendererService.render() 渲染路径,该路径内部会经过 DOMPurify 清洗。当 Hover 内容是业务方自行构造的 DOM 节点时(如带有自定义交互逻辑的富文本),DOMPurify 会剥离事件监听器、自定义属性等,导致渲染结果不符合预期。
  • 改动:在 renderMarkdown 中检测 markdownString.domElement instanceof HTMLElement,若存在则直接 appendChild 挂载到容器并调用 onFinishedRendering(),完全跳过 markdownRendererService.render() 流程;否则仍走原有路径。
  • 效果:业务方可通过在 MarkdownString 上挂载 domElement 属性,将任意 DOM 节点原样渲染进 Hover 弹层,保留完整的事件绑定和自定义属性,不受 DOMPurify 干扰。

③ 修复 package.json exports 通配符映射

  • 改动文件package.jsonexports 字段(源头修改,构建时自动带入产物)
  • 问题:上游 exports 将 ./*.js./* 强制重定向到 ./esm/vs/*.js,导致消费方无法按完整路径(如 esm/vs/editor/editor.main.jsmin/vs/…)直接导入,只能访问 esm/vs/ 子目录下的文件。
  • 改动:将通配符映射改为顶层直通:
    - "./*.js": "./esm/vs/*.js",
    - "./*":    "./esm/vs/*.js"
    + "./*.js": "./*.js",
    + "./*":    "./*"
  • 效果:消费方可按包内任意路径导入文件,esm/min/、根目录文件均可正常解析,不再受路径重映射限制。

实现方式

| 文件 | 作用 | |------|------| | patches/monaco-editor-core+0.55.1-full.2.patch | patch-package 格式的 patch 文件,包含改动 ① ② | | build/postinstall.ts | npm install 后自动调用 patch-package,将 patch 应用到 node_modules | | package.jsonexports | 直接在源头修改,npm run build 时由 build-monaco-editor.ts 自动写入产物的 package.json,覆盖改动 ③ |


3. ML 语言自动检测功能(Language Detection)

src/features/languageDetection/ 下新增了一套完整的语言自动检测模块,将 VS Code 工作区层(workbench)的语言检测能力移植到了浏览器侧独立运行。官方 monaco-editor 不包含此功能。

核心文件

| 文件 | 说明 | |------|------| | register.ts | 公开入口,调用 registerLanguageDetection() 即可启用自动检测 | | browser/languageDetectionService.ts | 主线程服务,负责历史偏置计算和 Worker 通信 | | browser/languageDetectionWorker.ts | Web Worker 内部逻辑,运行神经网络模型和正则模型 | | browser/languageDetectionWorkerMain.ts | Worker 入口,调用 bootstrapWebWorker 启动 | | browser/languageDetectionProtocol.ts | 主线程↔Worker 的 RPC 协议定义 |

功能亮点

  • 神经网络检测:通过 @vscode/vscode-languagedetection(TF.js 驱动)识别代码语言,支持 url 模式(动态加载远程模型)和 bundle 模式(跳过神经网络,仅用正则)。
  • 正则兜底检测:可选接入 vscode-regexp-languagedetection(通过 regexpModelUrl 配置),在神经网络无结果时作为降级方案。两种模型的优先级可通过 preferHistoryModel 反转。
  • 历史偏置加权:复刻 VS Code 的偏置算法(session +7、workspace +5、历史 workspace +3、全局历史 +1),让检测结果向用户近期使用的语言倾斜。
  • 持久化支持:通过 storage.read/write 回调将历史记录持久化到 localStorage 等任意存储。
  • 自动 & 手动两种模式:默认自动监听所有 model 的创建和内容变更(节流 600 ms,与 VS Code 一致);设置 autoDetect: false 后可手动调用 detectLanguage()
  • 无侵入:只在 model 无文件扩展名且语言为 plaintext 时才介入,已有语言设置或用户手动切换后不再覆盖。

快速接入示例

import { registerLanguageDetection } from 'monaco-editor-full/src/features/languageDetection/register';

// ① 神经网络 + 正则双保险(推荐)
const service = registerLanguageDetection({
  modelLoadMode: 'url',
  indexJsUrl:   'https://cdn.jsdelivr.net/npm/@vscode/vscode-languagedetection/dist/lib/index.js',
  modelJsonUrl:  'https://cdn.jsdelivr.net/npm/@vscode/vscode-languagedetection/model/model.json',
  weightsUrl:    'https://cdn.jsdelivr.net/npm/@vscode/vscode-languagedetection/model/group1-shard1of1.bin',
  // 正则兜底:神经网络无结果时自动回落
  regexpModelUrl: 'https://cdn.jsdelivr.net/npm/vscode-regexp-languagedetection/dist/index.js',
  storage: {
    read:  (key) => localStorage.getItem(key),
    write: (key, val) => localStorage.setItem(key, val),
  },
  onLanguageDetected: (model, languageId) => {
    console.log(`检测到语言:${languageId}`);
  },
});

// ② 仅正则模型(轻量,无需加载 TF.js)
const service = registerLanguageDetection({
  modelLoadMode: 'bundle',   // 禁用神经网络
  regexpModelUrl: 'https://cdn.jsdelivr.net/npm/vscode-regexp-languagedetection/dist/index.js',
});

// ③ 正则优先,神经网络兜底
const service = registerLanguageDetection({
  modelLoadMode: 'url',
  /* ...其他 url 配置... */
  regexpModelUrl: 'https://cdn.jsdelivr.net/npm/vscode-regexp-languagedetection/dist/index.js',
  preferHistoryModel: true,  // 正则先跑,有结果就用,无结果再走神经网络
});

// ④ 手动检测模式
const service = registerLanguageDetection({ modelLoadMode: 'url', /* ... */, autoDetect: false });
const lang = await service.detectLanguage(myModel);
if (lang) myModel.setLanguage(lang);

// 不再使用时释放资源
service.dispose();

4. LLM 语言检测功能(LLM Language Detection)

src/features/llmLanguageDetection/ 下新增了一套由大语言模型(LLM)驱动的语言检测模块。与 ML 检测不同,本模块:

  • 纯手动触发:不自动监听内容变更,由调用方决定何时检测(如按钮点击)。
  • 候选语言可控:调用方声明 LLM 可以返回哪些语言,超出范围的结果一律视为 undefined
  • 适配器模式:通过 ILLMAdapter 接口解耦 LLM 调用细节(prompt 构造、鉴权、重试等)。
  • LRU 缓存:相同内容哈希在 TTL 内复用上次结果,避免重复调用 LLM。
  • 用户锁定保护:用户手动切换语言后,detectLanguage() 直接返回 undefined,不再覆盖。

核心文件

| 文件 | 说明 | |------|------| | src/features/llmLanguageDetection/register.ts | 公开入口,调用 registerLLMLanguageDetection() 创建服务 | | src/features/llmLanguageDetection/llmDetectionService.ts | 服务实现:LRU 缓存、用户锁定、适配器调用 |

配套 Sample

samples/browser-esm-vite-react-llm-detection/ 提供了完整的 React + Vite 演示:

  • 默认使用内置 mock 适配器(关键词启发式,无需 API Key,离线可用)。
  • 配置 VITE_OPENAI_API_KEY 环境变量后自动切换为真实 OpenAI 调用(gpt-4o-mini)。
  • 演示了手动触发检测、状态栏展示检测结果、用户锁定交互等完整流程。

快速接入示例

import {
  registerLLMLanguageDetection,
  type ILLMAdapter,
  type LLMLanguageCandidate,
} from 'monaco-editor-full/src/features/llmLanguageDetection/register';

// ① 实现适配器(你来决定 prompt 和 LLM 调用方式)
const myAdapter: ILLMAdapter = {
  async detect({ candidates, codeSnippet }) {
    const response = await fetch('/api/detect-language', {
      method: 'POST',
      body: JSON.stringify({ candidates, code: codeSnippet }),
    });
    const { languageId } = await response.json();
    return languageId; // 须为 candidates 中的某个 id,否则视为 undefined
  },
};

// ② 声明候选语言
const candidates: LLMLanguageCandidate[] = [
  {
    id: 'pgsql',
    description: 'PostgreSQL — 使用 :: 类型转换、ILIKE、$1 参数、RETURNING 子句。',
    examples: [`SELECT id, name::text FROM users WHERE email ILIKE '%@example.com' RETURNING id;`],
  },
  {
    id: 'mysql',
    description: 'MySQL — 使用反引号标识符、SHOW TABLES、GROUP_CONCAT、LIMIT n。',
    examples: [`SELECT user_id, GROUP_CONCAT(tag) FROM \`user_tags\` GROUP BY user_id LIMIT 100;`],
  },
  { id: 'python',     description: 'Python — def/class、缩进、print()、列表推导式。' },
  { id: 'typescript', description: 'TypeScript — 带类型注解的 JavaScript,含 interface 和泛型。' },
];

// ③ 注册服务(应用启动时调用一次)
const llmService = registerLLMLanguageDetection({
  adapter: myAdapter,
  candidates,
  maxContentLength: 1500,  // 发给 LLM 的最大字符数
  minContentLength: 30,    // 内容过短时跳过检测
  cacheTtl: 5 * 60_000,   // 5 分钟缓存
  onLanguageDetected: (model, languageId) => {
    console.log(`LLM 检测到语言:${languageId}`);
  },
  onDetectionError: (model, error) => {
    console.error('LLM 检测失败:', error);
  },
});

// ④ 手动触发检测(如绑定到按钮)
const languageId = await llmService.detectLanguage(editor.getModel());
// languageId 已被自动应用到 model,这里可用于更新 UI

// ⑤ 不再使用时释放资源
llmService.dispose();

License

Licensed under the MIT License.