modern-monaco 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cache.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/cache.ts
2
- import { defineProperty, openIDB, promisifyIDBRequest, toURL } from "./util.mjs";
2
+ import { defineProperty, normalizeURL, openIDB, promisifyIDBRequest } from "./util.mjs";
3
3
  var IndexedDB = class {
4
4
  #db;
5
5
  constructor(name) {
@@ -43,7 +43,7 @@ var Cache = class {
43
43
  }
44
44
  }
45
45
  async fetch(url) {
46
- url = toURL(url);
46
+ url = normalizeURL(url);
47
47
  const storedRes = await this.query(url);
48
48
  if (storedRes) {
49
49
  return storedRes;
@@ -75,7 +75,7 @@ var Cache = class {
75
75
  return res;
76
76
  }
77
77
  async query(key) {
78
- const url = toURL(key).href;
78
+ const url = normalizeURL(key).href;
79
79
  const file = await this._db.get(url);
80
80
  if (file && file.headers) {
81
81
  const headers = new Headers(file.headers);
package/dist/core.mjs CHANGED
@@ -1,42 +1,55 @@
1
- // src/core.ts
2
- import { getExtnameFromLanguageId, getLanguageIdFromPath, grammars, initShiki, setDefaultWasmLoader, themes } from "./shiki.mjs";
3
- import { initShikiMonacoTokenizer, registerShikiMonacoTokenizer } from "./shiki.mjs";
4
- import { render } from "./shiki.mjs";
5
- import { getWasmInstance } from "./shiki-wasm.mjs";
6
- import { ErrorNotFound, Workspace } from "./workspace.mjs";
7
-
8
- // src/util.ts
9
- var dec = /* @__PURE__ */ new TextDecoder();
10
- function decode(data) {
11
- return data instanceof Uint8Array ? dec.decode(data) : data;
1
+ // node_modules/.pnpm/@esm.sh+import-map@0.1.1/node_modules/@esm.sh/import-map/dist/import-map.mjs
2
+ function parseImportMapFromJson(json, baseURL) {
3
+ const importMap = {
4
+ $baseURL: new URL(baseURL ?? ".", "file:///").href,
5
+ imports: {},
6
+ scopes: {}
7
+ };
8
+ const v = JSON.parse(json);
9
+ if (isObject(v)) {
10
+ const { imports, scopes } = v;
11
+ if (isObject(imports)) {
12
+ validateImports(imports);
13
+ importMap.imports = imports;
14
+ }
15
+ if (isObject(scopes)) {
16
+ validateScopes(scopes);
17
+ importMap.scopes = scopes;
18
+ }
19
+ }
20
+ return importMap;
12
21
  }
13
- function isDigital(v) {
14
- return typeof v === "number" || typeof v === "string" && /^\d+$/.test(v);
22
+ function validateImports(imports) {
23
+ for (const [k, v] of Object.entries(imports)) {
24
+ if (!v || typeof v !== "string") {
25
+ delete imports[k];
26
+ }
27
+ }
15
28
  }
16
- function debunce(fn, delay) {
17
- let timer = null;
18
- return () => {
19
- if (timer !== null) {
20
- clearTimeout(timer);
29
+ function validateScopes(imports) {
30
+ for (const [k, v] of Object.entries(imports)) {
31
+ if (isObject(v)) {
32
+ validateImports(v);
33
+ } else {
34
+ delete imports[k];
21
35
  }
22
- timer = setTimeout(() => {
23
- timer = null;
24
- fn();
25
- }, delay);
26
- };
36
+ }
27
37
  }
28
- function promiseWithResolvers() {
29
- let resolve;
30
- let reject;
31
- const promise = new Promise((res, rej) => {
32
- resolve = res;
33
- reject = rej;
34
- });
35
- return { promise, resolve, reject };
38
+ function isObject(v) {
39
+ return typeof v === "object" && v !== null && !Array.isArray(v);
36
40
  }
37
41
 
42
+ // package.json
43
+ var version = "0.2.2";
44
+
38
45
  // src/core.ts
39
- import { init as initLS } from "./lsp/language-service.mjs";
46
+ import { getExtnameFromLanguageId, getLanguageIdFromPath, grammars, initShiki, setDefaultWasmLoader, themes } from "./shiki.mjs";
47
+ import { initShikiMonacoTokenizer, registerShikiMonacoTokenizer } from "./shiki.mjs";
48
+ import { render } from "./shiki.mjs";
49
+ import { getWasmInstance } from "./shiki-wasm.mjs";
50
+ import { ErrorNotFound, Workspace } from "./workspace.mjs";
51
+ import { debunce, decode, isDigital } from "./util.mjs";
52
+ import { init as initLspClient } from "./lsp/client.mjs";
40
53
  var editorProps = [
41
54
  "autoDetectHighContrast",
42
55
  "automaticLayout",
@@ -71,9 +84,9 @@ var editorProps = [
71
84
  var errors = {
72
85
  NotFound: ErrorNotFound
73
86
  };
87
+ var cdnUrl = `https://esm.sh/modern-monaco@${version}`;
74
88
  var syntaxes = [];
75
89
  var lspProviders = {};
76
- var { promise: editorWorkerPromise, resolve: onDidEditorWorkerResolve } = promiseWithResolvers();
77
90
  var attr = (el, name) => el.getAttribute(name);
78
91
  var style = (el, style2) => Object.assign(el.style, style2);
79
92
  async function init(options) {
@@ -243,7 +256,7 @@ async function lazy(options) {
243
256
  }
244
257
  }
245
258
  }
246
- async function createEditor() {
259
+ {
247
260
  const monaco = await (monacoPromise ?? (monacoPromise = loadMonaco(highlighter, workspace, options?.lsp)));
248
261
  const editor = monaco.editor.create(containerEl, renderOptions);
249
262
  if (workspace) {
@@ -300,34 +313,49 @@ async function lazy(options) {
300
313
  editor.setModel(monaco.editor.createModel(""));
301
314
  }
302
315
  if (prerenderEl) {
303
- editorWorkerPromise.then(() => {
304
- setTimeout(() => {
305
- const animate = prerenderEl.animate?.([{ opacity: 1 }, { opacity: 0 }], { duration: 150 });
306
- if (animate) {
307
- animate.finished.then(() => prerenderEl.remove());
308
- } else {
309
- setTimeout(() => prerenderEl.remove(), 150);
310
- }
311
- }, 100);
312
- });
316
+ setTimeout(() => {
317
+ const animate = prerenderEl.animate?.([{ opacity: 1 }, { opacity: 0 }], { duration: 200 });
318
+ if (animate) {
319
+ animate.finished.then(() => prerenderEl.remove());
320
+ } else {
321
+ setTimeout(() => prerenderEl.remove(), 200);
322
+ }
323
+ }, 200);
313
324
  }
314
325
  }
315
- await createEditor();
316
326
  }
317
327
  }
318
328
  );
319
329
  }
320
- await editorWorkerPromise;
321
330
  }
322
331
  function hydrate(options) {
323
332
  return lazy(options);
324
333
  }
325
334
  async function loadMonaco(highlighter, workspace, lsp) {
326
- const monaco = await import("./editor-core.mjs");
327
- const lspProviderMap = { ...lspProviders, ...lsp?.providers };
335
+ let importmap = null;
336
+ let editorCoreModuleUrl = `${cdnUrl}/es2022/editor-core.mjs`;
337
+ let lspModuleUrl = `${cdnUrl}/es2022/lsp.mjs`;
338
+ if (importmap = document.querySelector("script[type='importmap']")) {
339
+ try {
340
+ const { imports = {} } = parseImportMapFromJson(importmap.textContent);
341
+ if (imports["modern-monaco/editor-core"]) {
342
+ editorCoreModuleUrl = imports["modern-monaco/editor-core"];
343
+ }
344
+ if (imports["modern-monaco/lsp"]) {
345
+ lspModuleUrl = imports["modern-monaco/lsp"];
346
+ }
347
+ } catch (error) {
348
+ }
349
+ }
350
+ const builtinLSP = globalThis.MonacoEnvironment?.builtinLSP;
351
+ const [monaco, { builtinLSPProviders }] = await Promise.all([
352
+ import(editorCoreModuleUrl),
353
+ builtinLSP ? import(lspModuleUrl) : Promise.resolve({ builtinLSPProviders: {} })
354
+ ]);
355
+ const lspProviderMap = { ...builtinLSPProviders, ...lspProviders, ...lsp?.providers };
328
356
  workspace?.setupMonaco(monaco);
329
357
  if (Object.keys(lspProviderMap).length > 0) {
330
- initLS(monaco);
358
+ initLspClient(monaco);
331
359
  }
332
360
  if (!document.getElementById("monaco-editor-core-css")) {
333
361
  const styleEl = document.createElement("style");
@@ -339,13 +367,7 @@ async function loadMonaco(highlighter, workspace, lsp) {
339
367
  Reflect.set(globalThis, "MonacoEnvironment", {
340
368
  getWorker: async (_workerId, label) => {
341
369
  if (label === "editorWorkerService") {
342
- const worker = monaco.createEditorWorkerMain();
343
- const onMessage = (e) => {
344
- worker.removeEventListener("message", onMessage);
345
- onDidEditorWorkerResolve();
346
- };
347
- worker.addEventListener("message", onMessage);
348
- return worker;
370
+ return monaco.createEditorWorkerMain();
349
371
  }
350
372
  },
351
373
  getLanguageIdFromUri: (uri) => getLanguageIdFromPath(uri.path),
@@ -198377,10 +198377,10 @@ function createEditorWorkerMain() {
198377
198377
  if (workerUrl.origin !== location.origin) {
198378
198378
  return new Worker(
198379
198379
  URL.createObjectURL(new Blob([`import "${workerUrl.href}"`], { type: "application/javascript" })),
198380
- { type: "module" }
198380
+ { type: "module", name: "editor-worker-main" }
198381
198381
  );
198382
198382
  }
198383
- return new Worker(new URL("./editor-worker-main.mjs", import.meta.url), { type: "module" });
198383
+ return new Worker(workerUrl, { type: "module", name: "editor-worker-main" });
198384
198384
  }
198385
198385
  export {
198386
198386
  CancellationTokenSource2 as CancellationTokenSource,
package/dist/index.mjs CHANGED
@@ -693,28 +693,6 @@ var vitesse_dark_default = {
693
693
  type: "dark"
694
694
  };
695
695
 
696
- // src/lsp/index.ts
697
- var builtinLSPProviders = {
698
- html: {
699
- // @ts-expect-error 'setup.js' is generated at build time
700
- import: () => import("./lsp/html/setup.mjs")
701
- },
702
- css: {
703
- aliases: ["less", "sass"],
704
- // @ts-expect-error 'setup.js' is generated at build time
705
- import: () => import("./lsp/css/setup.mjs")
706
- },
707
- json: {
708
- // @ts-expect-error 'setup.js' is generated at build time
709
- import: () => import("./lsp/json/setup.mjs")
710
- },
711
- typescript: {
712
- aliases: ["javascript", "jsx", "tsx"],
713
- // @ts-expect-error 'setup.js' is generated at build time
714
- import: () => import("./lsp/typescript/setup.mjs")
715
- }
716
- };
717
-
718
696
  // node_modules/.pnpm/tm-grammars@1.24.10/node_modules/tm-grammars/grammars/html.json
719
697
  var html_default = {
720
698
  displayName: "HTML",
@@ -29343,15 +29321,13 @@ var syntaxes = [
29343
29321
  ];
29344
29322
 
29345
29323
  // src/index.ts
29346
- import { registerLSPProvider, registerSyntax, registerTheme } from "./core.mjs";
29324
+ import { registerSyntax, registerTheme } from "./core.mjs";
29347
29325
  import { errors, hydrate, init, lazy, Workspace } from "./core.mjs";
29348
- for (const [lang, provider] of Object.entries(builtinLSPProviders)) {
29349
- registerLSPProvider(lang, provider);
29350
- }
29351
29326
  for (const syntax of syntaxes) {
29352
29327
  registerSyntax(syntax);
29353
29328
  }
29354
29329
  registerTheme(vitesse_dark_default);
29330
+ Reflect.set(globalThis, "MonacoEnvironment", { builtinLSP: true });
29355
29331
  export {
29356
29332
  Workspace,
29357
29333
  errors,
@@ -1181,7 +1181,7 @@ var Is;
1181
1181
  Is2.typedArray = typedArray;
1182
1182
  })(Is || (Is = {}));
1183
1183
 
1184
- // src/lsp/language-service.ts
1184
+ // src/lsp/client.ts
1185
1185
  import { cache } from "../cache.mjs";
1186
1186
  var monaco;
1187
1187
  function init(monacoNS) {
@@ -1222,7 +1222,7 @@ function registerBasicFeatures(languageId, worker, completionTriggerCharacters,
1222
1222
  const { editor, languages } = monaco;
1223
1223
  const onDispose = async (model) => {
1224
1224
  const workerProxy = await worker.withSyncedResources([]);
1225
- workerProxy.removeDocumentCache(model.uri.toString());
1225
+ workerProxy.releaseDocument(model.uri.toString());
1226
1226
  };
1227
1227
  editor.onDidChangeModelLanguage(({ model, oldLanguage }) => {
1228
1228
  if (oldLanguage === languageId) {
@@ -1263,12 +1263,6 @@ function registerBasicFeatures(languageId, worker, completionTriggerCharacters,
1263
1263
  worker.getProxy().then((proxy) => proxy.fsNotify(kind, path, type));
1264
1264
  }
1265
1265
  });
1266
- (async () => {
1267
- const workerProxy = await worker.getProxy();
1268
- for await (const [path, type] of workspace.fs.walk()) {
1269
- workerProxy.fsNotify("create", path, type);
1270
- }
1271
- })();
1272
1266
  }
1273
1267
  }
1274
1268
  function registerDiagnostics(languageId, worker) {
@@ -1,5 +1,6 @@
1
1
  // src/lsp/css/setup.ts
2
- import * as ls from "../language-service.mjs";
2
+ import { walk } from "../../workspace.mjs";
3
+ import * as client from "../client.mjs";
3
4
  async function setup(monaco, languageId, languageSettings, formattingOptions, workspace) {
4
5
  const { tabSize, insertSpaces, insertFinalNewline, trimFinalNewlines } = formattingOptions ?? {};
5
6
  const createData = {
@@ -18,26 +19,26 @@ async function setup(monaco, languageId, languageSettings, formattingOptions, wo
18
19
  spaceAroundSelectorSeparator: false,
19
20
  braceStyle: "collapse"
20
21
  },
21
- workspace: !!workspace
22
+ fs: workspace ? await walk(workspace.fs, "/") : void 0
22
23
  };
23
24
  const worker = monaco.editor.createWebWorker({
24
25
  worker: getWorker(createData),
25
- host: ls.createHost(workspace)
26
+ host: client.createHost(workspace)
26
27
  });
27
- ls.registerBasicFeatures(languageId, worker, ["/", "-", ":", "("], workspace);
28
- ls.registerCodeAction(languageId, worker);
29
- ls.registerColorPresentation(languageId, worker);
30
- ls.registerDocumentLinks(languageId, worker);
28
+ client.registerBasicFeatures(languageId, worker, ["/", "-", ":", "("], workspace);
29
+ client.registerCodeAction(languageId, worker);
30
+ client.registerColorPresentation(languageId, worker);
31
+ client.registerDocumentLinks(languageId, worker);
31
32
  }
32
33
  function createWebWorker() {
33
34
  const workerUrl = new URL("./worker.mjs", import.meta.url);
34
35
  if (workerUrl.origin !== location.origin) {
35
36
  return new Worker(
36
37
  URL.createObjectURL(new Blob([`import "${workerUrl.href}"`], { type: "application/javascript" })),
37
- { type: "module" }
38
+ { type: "module", name: "css-worker" }
38
39
  );
39
40
  }
40
- return new Worker(new URL("./worker.mjs", import.meta.url), { type: "module" });
41
+ return new Worker(workerUrl, { type: "module", name: "css-worker" });
41
42
  }
42
43
  function getWorker(createData) {
43
44
  const worker = createWebWorker();
@@ -48125,21 +48125,36 @@ function getLESSLanguageService(options = defaultLanguageServiceOptions) {
48125
48125
 
48126
48126
  // src/lsp/worker-base.ts
48127
48127
  var WorkerBase = class {
48128
- constructor(_ctx, _createData, _createLanguageDocument) {
48129
- this._ctx = _ctx;
48130
- this._createData = _createData;
48131
- this._createLanguageDocument = _createLanguageDocument;
48132
- }
48133
- #documentCache = /* @__PURE__ */ new Map();
48128
+ #ctx;
48134
48129
  #fs;
48130
+ #documentCache = /* @__PURE__ */ new Map();
48131
+ #createLanguageDocument;
48132
+ constructor(ctx, createData, createLanguageDocument) {
48133
+ this.#ctx = ctx;
48134
+ if (createData.fs) {
48135
+ const dirs = /* @__PURE__ */ new Set(["/"]);
48136
+ this.#fs = new Map(createData.fs.map((path) => {
48137
+ const dir = path.slice(0, path.lastIndexOf("/"));
48138
+ if (dir) {
48139
+ dirs.add(dir);
48140
+ }
48141
+ return ["file://" + path, 1];
48142
+ }));
48143
+ for (const dir of dirs) {
48144
+ this.#fs.set("file://" + dir, 2);
48145
+ }
48146
+ createData.fs.length = 0;
48147
+ }
48148
+ this.#createLanguageDocument = createLanguageDocument;
48149
+ }
48135
48150
  get hasFileSystemProvider() {
48136
- return !!this._createData.workspace;
48151
+ return !!this.#fs;
48137
48152
  }
48138
48153
  get host() {
48139
- return this._ctx.host;
48154
+ return this.#ctx.host;
48140
48155
  }
48141
48156
  getMirrorModels() {
48142
- return this._ctx.getMirrorModels();
48157
+ return this.#ctx.getMirrorModels();
48143
48158
  }
48144
48159
  hasModel(fileName) {
48145
48160
  const models = this.getMirrorModels();
@@ -48180,10 +48195,10 @@ var WorkerBase = class {
48180
48195
  if (cached && cached[0] === version && cached[2]) {
48181
48196
  return cached[2];
48182
48197
  }
48183
- if (!this._createLanguageDocument) {
48198
+ if (!this.#createLanguageDocument) {
48184
48199
  throw new Error("createLanguageDocument is not provided");
48185
48200
  }
48186
- const languageDocument = this._createLanguageDocument(document);
48201
+ const languageDocument = this.#createLanguageDocument(document);
48187
48202
  this.#documentCache.set(uri, [version, document, languageDocument]);
48188
48203
  return languageDocument;
48189
48204
  }
@@ -48194,10 +48209,12 @@ var WorkerBase = class {
48194
48209
  if (path.startsWith(uri)) {
48195
48210
  const name = path.slice(uri.length);
48196
48211
  if (!name.includes("/")) {
48197
- if (type === 2) {
48198
- entries.push([name, 2 /* Directory */]);
48199
- } else if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
48200
- entries.push([name, 1 /* File */]);
48212
+ if (type === 1) {
48213
+ if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
48214
+ entries.push([name, 1]);
48215
+ }
48216
+ } else if (type === 2) {
48217
+ entries.push([name, 2]);
48201
48218
  }
48202
48219
  }
48203
48220
  }
@@ -48206,8 +48223,8 @@ var WorkerBase = class {
48206
48223
  return entries;
48207
48224
  }
48208
48225
  getFileSystemProvider() {
48209
- if (this.hasFileSystemProvider) {
48210
- const host = this._ctx.host;
48226
+ if (this.#fs) {
48227
+ const host = this.#ctx.host;
48211
48228
  return {
48212
48229
  readDirectory: (uri) => {
48213
48230
  return Promise.resolve(this.readDir(uri));
@@ -48224,29 +48241,27 @@ var WorkerBase = class {
48224
48241
  }
48225
48242
  // resolveReference implementes the `DocumentContext` interface
48226
48243
  resolveReference(ref, baseUrl) {
48227
- const url = new URL(ref, baseUrl);
48228
- const href = url.href;
48229
- if (url.protocol === "file:" && url.pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
48244
+ const { protocol, pathname, href } = new URL(ref, baseUrl);
48245
+ if (protocol === "file:" && pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
48230
48246
  return void 0;
48231
48247
  }
48232
48248
  return href;
48233
48249
  }
48234
48250
  // #region methods used by the host
48235
- async removeDocumentCache(uri) {
48251
+ async releaseDocument(uri) {
48236
48252
  this.#documentCache.delete(uri);
48237
48253
  }
48238
48254
  async fsNotify(kind, path, type) {
48239
- const url = "file://" + path;
48240
- const entries = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
48255
+ const fs = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
48241
48256
  if (kind === "create") {
48242
48257
  if (type) {
48243
- entries.set(url, type);
48258
+ fs.set(path, type);
48244
48259
  }
48245
48260
  } else if (kind === "remove") {
48246
- if (entries.get(url) === 1 /* File */) {
48247
- this.#documentCache.delete(url);
48261
+ if (fs.get(path) === 1) {
48262
+ this.#documentCache.delete(path);
48248
48263
  }
48249
- entries.delete(url);
48264
+ fs.delete(path);
48250
48265
  }
48251
48266
  }
48252
48267
  // #endregion
@@ -1,5 +1,6 @@
1
1
  // src/lsp/html/setup.ts
2
- import * as ls from "../language-service.mjs";
2
+ import { walk } from "../../workspace.mjs";
3
+ import * as client from "../client.mjs";
3
4
  async function setup(monaco, languageId, languageSettings, formattingOptions, workspace) {
4
5
  const { editor, languages } = monaco;
5
6
  const { tabSize, insertSpaces, insertFinalNewline, trimFinalNewlines } = formattingOptions ?? {};
@@ -26,18 +27,18 @@ async function setup(monaco, languageId, languageSettings, formattingOptions, wo
26
27
  useDefaultDataProvider: true,
27
28
  dataProviders: Array.isArray(languageSettings?.customTags) ? { custom: { version: 1.1, tags: languageSettings.customTags } } : void 0
28
29
  },
29
- workspace: !!workspace
30
+ fs: workspace ? await walk(workspace.fs, "/") : void 0
30
31
  };
31
32
  const htmlWorker = editor.createWebWorker({
32
33
  worker: getWorker(createData),
33
- host: ls.createHost(workspace)
34
+ host: client.createHost(workspace)
34
35
  });
35
- const workerWithEmbeddedLanguages = ls.createWorkerWithEmbeddedLanguages(htmlWorker);
36
- ls.registerEmbedded(languageId, workerWithEmbeddedLanguages, ["css", "javascript", "importmap"]);
37
- ls.registerBasicFeatures(languageId, workerWithEmbeddedLanguages, ["<", "/", "=", '"'], workspace);
38
- ls.registerAutoComplete(languageId, workerWithEmbeddedLanguages, [">", "/", "="]);
39
- ls.registerColorPresentation(languageId, workerWithEmbeddedLanguages);
40
- ls.registerDocumentLinks(languageId, workerWithEmbeddedLanguages);
36
+ const workerWithEmbeddedLanguages = client.createWorkerWithEmbeddedLanguages(htmlWorker);
37
+ client.registerEmbedded(languageId, workerWithEmbeddedLanguages, ["css", "javascript", "importmap"]);
38
+ client.registerBasicFeatures(languageId, workerWithEmbeddedLanguages, ["<", "/", "=", '"'], workspace);
39
+ client.registerAutoComplete(languageId, workerWithEmbeddedLanguages, [">", "/", "="]);
40
+ client.registerColorPresentation(languageId, workerWithEmbeddedLanguages);
41
+ client.registerDocumentLinks(languageId, workerWithEmbeddedLanguages);
41
42
  languages.registerCodeLensProvider(languageId, {
42
43
  provideCodeLenses: (model, _token) => {
43
44
  const m = model.findNextMatch(
@@ -81,10 +82,10 @@ function createWebWorker() {
81
82
  if (workerUrl.origin !== location.origin) {
82
83
  return new Worker(
83
84
  URL.createObjectURL(new Blob([`import "${workerUrl.href}"`], { type: "application/javascript" })),
84
- { type: "module" }
85
+ { type: "module", name: "html-worker" }
85
86
  );
86
87
  }
87
- return new Worker(new URL("./worker.mjs", import.meta.url), { type: "module" });
88
+ return new Worker(workerUrl, { type: "module", name: "html-worker" });
88
89
  }
89
90
  function getWorker(createData) {
90
91
  const worker = createWebWorker();
@@ -22052,21 +22052,36 @@ function getAttributeLanguage(attributeName) {
22052
22052
 
22053
22053
  // src/lsp/worker-base.ts
22054
22054
  var WorkerBase = class {
22055
- constructor(_ctx, _createData, _createLanguageDocument) {
22056
- this._ctx = _ctx;
22057
- this._createData = _createData;
22058
- this._createLanguageDocument = _createLanguageDocument;
22059
- }
22060
- #documentCache = /* @__PURE__ */ new Map();
22055
+ #ctx;
22061
22056
  #fs;
22057
+ #documentCache = /* @__PURE__ */ new Map();
22058
+ #createLanguageDocument;
22059
+ constructor(ctx, createData, createLanguageDocument) {
22060
+ this.#ctx = ctx;
22061
+ if (createData.fs) {
22062
+ const dirs = /* @__PURE__ */ new Set(["/"]);
22063
+ this.#fs = new Map(createData.fs.map((path) => {
22064
+ const dir = path.slice(0, path.lastIndexOf("/"));
22065
+ if (dir) {
22066
+ dirs.add(dir);
22067
+ }
22068
+ return ["file://" + path, 1];
22069
+ }));
22070
+ for (const dir of dirs) {
22071
+ this.#fs.set("file://" + dir, 2);
22072
+ }
22073
+ createData.fs.length = 0;
22074
+ }
22075
+ this.#createLanguageDocument = createLanguageDocument;
22076
+ }
22062
22077
  get hasFileSystemProvider() {
22063
- return !!this._createData.workspace;
22078
+ return !!this.#fs;
22064
22079
  }
22065
22080
  get host() {
22066
- return this._ctx.host;
22081
+ return this.#ctx.host;
22067
22082
  }
22068
22083
  getMirrorModels() {
22069
- return this._ctx.getMirrorModels();
22084
+ return this.#ctx.getMirrorModels();
22070
22085
  }
22071
22086
  hasModel(fileName) {
22072
22087
  const models = this.getMirrorModels();
@@ -22107,10 +22122,10 @@ var WorkerBase = class {
22107
22122
  if (cached && cached[0] === version && cached[2]) {
22108
22123
  return cached[2];
22109
22124
  }
22110
- if (!this._createLanguageDocument) {
22125
+ if (!this.#createLanguageDocument) {
22111
22126
  throw new Error("createLanguageDocument is not provided");
22112
22127
  }
22113
- const languageDocument = this._createLanguageDocument(document);
22128
+ const languageDocument = this.#createLanguageDocument(document);
22114
22129
  this.#documentCache.set(uri, [version, document, languageDocument]);
22115
22130
  return languageDocument;
22116
22131
  }
@@ -22121,10 +22136,12 @@ var WorkerBase = class {
22121
22136
  if (path.startsWith(uri)) {
22122
22137
  const name = path.slice(uri.length);
22123
22138
  if (!name.includes("/")) {
22124
- if (type === 2) {
22125
- entries.push([name, 2 /* Directory */]);
22126
- } else if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
22127
- entries.push([name, 1 /* File */]);
22139
+ if (type === 1) {
22140
+ if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
22141
+ entries.push([name, 1]);
22142
+ }
22143
+ } else if (type === 2) {
22144
+ entries.push([name, 2]);
22128
22145
  }
22129
22146
  }
22130
22147
  }
@@ -22133,8 +22150,8 @@ var WorkerBase = class {
22133
22150
  return entries;
22134
22151
  }
22135
22152
  getFileSystemProvider() {
22136
- if (this.hasFileSystemProvider) {
22137
- const host = this._ctx.host;
22153
+ if (this.#fs) {
22154
+ const host = this.#ctx.host;
22138
22155
  return {
22139
22156
  readDirectory: (uri) => {
22140
22157
  return Promise.resolve(this.readDir(uri));
@@ -22151,29 +22168,27 @@ var WorkerBase = class {
22151
22168
  }
22152
22169
  // resolveReference implementes the `DocumentContext` interface
22153
22170
  resolveReference(ref, baseUrl) {
22154
- const url = new URL(ref, baseUrl);
22155
- const href = url.href;
22156
- if (url.protocol === "file:" && url.pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
22171
+ const { protocol, pathname, href } = new URL(ref, baseUrl);
22172
+ if (protocol === "file:" && pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
22157
22173
  return void 0;
22158
22174
  }
22159
22175
  return href;
22160
22176
  }
22161
22177
  // #region methods used by the host
22162
- async removeDocumentCache(uri) {
22178
+ async releaseDocument(uri) {
22163
22179
  this.#documentCache.delete(uri);
22164
22180
  }
22165
22181
  async fsNotify(kind, path, type) {
22166
- const url = "file://" + path;
22167
- const entries = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
22182
+ const fs = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
22168
22183
  if (kind === "create") {
22169
22184
  if (type) {
22170
- entries.set(url, type);
22185
+ fs.set(path, type);
22171
22186
  }
22172
22187
  } else if (kind === "remove") {
22173
- if (entries.get(url) === 1 /* File */) {
22174
- this.#documentCache.delete(url);
22188
+ if (fs.get(path) === 1) {
22189
+ this.#documentCache.delete(path);
22175
22190
  }
22176
- entries.delete(url);
22191
+ fs.delete(path);
22177
22192
  }
22178
22193
  }
22179
22194
  // #endregion
@@ -0,0 +1,20 @@
1
+ // src/lsp/index.ts
2
+ var builtinLSPProviders = {
3
+ html: {
4
+ import: () => import("./html/setup.mjs")
5
+ },
6
+ css: {
7
+ aliases: ["less", "sass"],
8
+ import: () => import("./css/setup.mjs")
9
+ },
10
+ json: {
11
+ import: () => import("./json/setup.mjs")
12
+ },
13
+ typescript: {
14
+ aliases: ["javascript", "jsx", "tsx"],
15
+ import: () => import("./typescript/setup.mjs")
16
+ }
17
+ };
18
+ export {
19
+ builtinLSPProviders
20
+ };
@@ -111,7 +111,8 @@ var schemas = [
111
111
  ];
112
112
 
113
113
  // src/lsp/json/setup.ts
114
- import * as ls from "../language-service.mjs";
114
+ import { walk } from "../../workspace.mjs";
115
+ import * as client from "../client.mjs";
115
116
  async function setup(monaco, languageId, languageSettings, formattingOptions, workspace) {
116
117
  const { editor, languages } = monaco;
117
118
  const createData = {
@@ -132,11 +133,11 @@ async function setup(monaco, languageId, languageSettings, formattingOptions, wo
132
133
  trimFinalNewlines: true,
133
134
  ...formattingOptions
134
135
  },
135
- workspace: !!workspace
136
+ fs: workspace ? await walk(workspace.fs, "/") : void 0
136
137
  };
137
138
  const worker = editor.createWebWorker({
138
139
  worker: getWorker(createData),
139
- host: ls.createHost(workspace)
140
+ host: client.createHost(workspace)
140
141
  });
141
142
  const resetSchema = async (uri) => {
142
143
  (await worker.getProxy()).resetSchema(uri.toString());
@@ -151,9 +152,9 @@ async function setup(monaco, languageId, languageSettings, formattingOptions, wo
151
152
  resetSchema(event.model.uri);
152
153
  }
153
154
  });
154
- ls.registerBasicFeatures(languageId, worker, [" ", ":", '"'], workspace);
155
- ls.registerColorPresentation(languageId, worker);
156
- ls.registerDocumentLinks(languageId, worker);
155
+ client.registerBasicFeatures(languageId, worker, [" ", ":", '"'], workspace);
156
+ client.registerColorPresentation(languageId, worker);
157
+ client.registerDocumentLinks(languageId, worker);
157
158
  languages.registerCodeLensProvider(languageId, {
158
159
  provideCodeLenses: function(model, _token) {
159
160
  const isImportMap = model.uri.scheme == "file" && ["importmap.json", "import_map.json", "import-map.json", "importMap.json"].some((name) => model.uri.path === "/" + name);
@@ -249,10 +250,10 @@ function createWebWorker() {
249
250
  if (workerUrl.origin !== location.origin) {
250
251
  return new Worker(
251
252
  URL.createObjectURL(new Blob([`import "${workerUrl.href}"`], { type: "application/javascript" })),
252
- { type: "module" }
253
+ { type: "module", name: "json-worker" }
253
254
  );
254
255
  }
255
- return new Worker(new URL("./worker.mjs", import.meta.url), { type: "module" });
256
+ return new Worker(workerUrl, { type: "module", name: "json-worker" });
256
257
  }
257
258
  function getWorker(createData) {
258
259
  const worker = createWebWorker();
@@ -7682,21 +7682,36 @@ function getLanguageService(params) {
7682
7682
 
7683
7683
  // src/lsp/worker-base.ts
7684
7684
  var WorkerBase = class {
7685
- constructor(_ctx, _createData, _createLanguageDocument) {
7686
- this._ctx = _ctx;
7687
- this._createData = _createData;
7688
- this._createLanguageDocument = _createLanguageDocument;
7689
- }
7690
- #documentCache = /* @__PURE__ */ new Map();
7685
+ #ctx;
7691
7686
  #fs;
7687
+ #documentCache = /* @__PURE__ */ new Map();
7688
+ #createLanguageDocument;
7689
+ constructor(ctx, createData, createLanguageDocument) {
7690
+ this.#ctx = ctx;
7691
+ if (createData.fs) {
7692
+ const dirs = /* @__PURE__ */ new Set(["/"]);
7693
+ this.#fs = new Map(createData.fs.map((path) => {
7694
+ const dir = path.slice(0, path.lastIndexOf("/"));
7695
+ if (dir) {
7696
+ dirs.add(dir);
7697
+ }
7698
+ return ["file://" + path, 1];
7699
+ }));
7700
+ for (const dir of dirs) {
7701
+ this.#fs.set("file://" + dir, 2);
7702
+ }
7703
+ createData.fs.length = 0;
7704
+ }
7705
+ this.#createLanguageDocument = createLanguageDocument;
7706
+ }
7692
7707
  get hasFileSystemProvider() {
7693
- return !!this._createData.workspace;
7708
+ return !!this.#fs;
7694
7709
  }
7695
7710
  get host() {
7696
- return this._ctx.host;
7711
+ return this.#ctx.host;
7697
7712
  }
7698
7713
  getMirrorModels() {
7699
- return this._ctx.getMirrorModels();
7714
+ return this.#ctx.getMirrorModels();
7700
7715
  }
7701
7716
  hasModel(fileName) {
7702
7717
  const models = this.getMirrorModels();
@@ -7737,10 +7752,10 @@ var WorkerBase = class {
7737
7752
  if (cached && cached[0] === version && cached[2]) {
7738
7753
  return cached[2];
7739
7754
  }
7740
- if (!this._createLanguageDocument) {
7755
+ if (!this.#createLanguageDocument) {
7741
7756
  throw new Error("createLanguageDocument is not provided");
7742
7757
  }
7743
- const languageDocument = this._createLanguageDocument(document);
7758
+ const languageDocument = this.#createLanguageDocument(document);
7744
7759
  this.#documentCache.set(uri, [version, document, languageDocument]);
7745
7760
  return languageDocument;
7746
7761
  }
@@ -7751,10 +7766,12 @@ var WorkerBase = class {
7751
7766
  if (path.startsWith(uri)) {
7752
7767
  const name = path.slice(uri.length);
7753
7768
  if (!name.includes("/")) {
7754
- if (type === 2) {
7755
- entries.push([name, 2 /* Directory */]);
7756
- } else if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
7757
- entries.push([name, 1 /* File */]);
7769
+ if (type === 1) {
7770
+ if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
7771
+ entries.push([name, 1]);
7772
+ }
7773
+ } else if (type === 2) {
7774
+ entries.push([name, 2]);
7758
7775
  }
7759
7776
  }
7760
7777
  }
@@ -7763,8 +7780,8 @@ var WorkerBase = class {
7763
7780
  return entries;
7764
7781
  }
7765
7782
  getFileSystemProvider() {
7766
- if (this.hasFileSystemProvider) {
7767
- const host = this._ctx.host;
7783
+ if (this.#fs) {
7784
+ const host = this.#ctx.host;
7768
7785
  return {
7769
7786
  readDirectory: (uri) => {
7770
7787
  return Promise.resolve(this.readDir(uri));
@@ -7781,29 +7798,27 @@ var WorkerBase = class {
7781
7798
  }
7782
7799
  // resolveReference implementes the `DocumentContext` interface
7783
7800
  resolveReference(ref, baseUrl) {
7784
- const url = new URL(ref, baseUrl);
7785
- const href = url.href;
7786
- if (url.protocol === "file:" && url.pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
7801
+ const { protocol, pathname, href } = new URL(ref, baseUrl);
7802
+ if (protocol === "file:" && pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
7787
7803
  return void 0;
7788
7804
  }
7789
7805
  return href;
7790
7806
  }
7791
7807
  // #region methods used by the host
7792
- async removeDocumentCache(uri) {
7808
+ async releaseDocument(uri) {
7793
7809
  this.#documentCache.delete(uri);
7794
7810
  }
7795
7811
  async fsNotify(kind, path, type) {
7796
- const url = "file://" + path;
7797
- const entries = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
7812
+ const fs = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
7798
7813
  if (kind === "create") {
7799
7814
  if (type) {
7800
- entries.set(url, type);
7815
+ fs.set(path, type);
7801
7816
  }
7802
7817
  } else if (kind === "remove") {
7803
- if (entries.get(url) === 1 /* File */) {
7804
- this.#documentCache.delete(url);
7818
+ if (fs.get(path) === 1) {
7819
+ this.#documentCache.delete(path);
7805
7820
  }
7806
- entries.delete(url);
7821
+ fs.delete(path);
7807
7822
  }
7808
7823
  }
7809
7824
  // #endregion
@@ -95,8 +95,8 @@ function isSameImports(a, b) {
95
95
 
96
96
  // src/lsp/typescript/setup.ts
97
97
  import { cache } from "../../cache.mjs";
98
- import { ErrorNotFound } from "../../workspace.mjs";
99
- import * as ls from "../language-service.mjs";
98
+ import { ErrorNotFound, walk } from "../../workspace.mjs";
99
+ import * as client from "../client.mjs";
100
100
  var worker = null;
101
101
  async function setup(monaco, languageId, languageSettings, formattingOptions, workspace) {
102
102
  if (!worker) {
@@ -105,10 +105,10 @@ async function setup(monaco, languageId, languageSettings, formattingOptions, wo
105
105
  if (worker instanceof Promise) {
106
106
  worker = await worker;
107
107
  }
108
- ls.registerBasicFeatures(languageId, worker, [".", "/", '"', "'", "<"], workspace);
109
- ls.registerAutoComplete(languageId, worker, [">", "/"]);
110
- ls.registerSignatureHelp(languageId, worker, ["(", ","]);
111
- ls.registerCodeAction(languageId, worker);
108
+ client.registerBasicFeatures(languageId, worker, [".", "/", '"', "'", "<"], workspace);
109
+ client.registerAutoComplete(languageId, worker, [">", "/"]);
110
+ client.registerSignatureHelp(languageId, worker, ["(", ","]);
111
+ client.registerCodeAction(languageId, worker);
112
112
  }
113
113
  async function createWorker(monaco, workspace, languageSettings, formattingOptions) {
114
114
  const fs = workspace?.fs;
@@ -168,7 +168,7 @@ async function createWorker(monaco, workspace, languageSettings, formattingOptio
168
168
  },
169
169
  importMap,
170
170
  types: typesStore.types,
171
- workspace: !!workspace
171
+ fs: workspace ? await walk(workspace.fs, "/") : void 0
172
172
  };
173
173
  const worker2 = monaco.editor.createWebWorker({
174
174
  worker: getWorker(createData),
@@ -282,10 +282,10 @@ function createWebWorker() {
282
282
  if (workerUrl.origin !== location.origin) {
283
283
  return new Worker(
284
284
  URL.createObjectURL(new Blob([`import "${workerUrl.href}"`], { type: "application/javascript" })),
285
- { type: "module" }
285
+ { type: "module", name: "typescript-worker" }
286
286
  );
287
287
  }
288
- return new Worker(new URL("./worker.mjs", import.meta.url), { type: "module" });
288
+ return new Worker(workerUrl, { type: "module", name: "typescript-worker" });
289
289
  }
290
290
  function getWorker(createData) {
291
291
  const worker2 = createWebWorker();
@@ -1466,21 +1466,36 @@ function getWellformedEdit(textEdit) {
1466
1466
 
1467
1467
  // src/lsp/worker-base.ts
1468
1468
  var WorkerBase = class {
1469
- constructor(_ctx, _createData, _createLanguageDocument) {
1470
- this._ctx = _ctx;
1471
- this._createData = _createData;
1472
- this._createLanguageDocument = _createLanguageDocument;
1473
- }
1474
- #documentCache = /* @__PURE__ */ new Map();
1469
+ #ctx;
1475
1470
  #fs;
1471
+ #documentCache = /* @__PURE__ */ new Map();
1472
+ #createLanguageDocument;
1473
+ constructor(ctx, createData, createLanguageDocument) {
1474
+ this.#ctx = ctx;
1475
+ if (createData.fs) {
1476
+ const dirs = /* @__PURE__ */ new Set(["/"]);
1477
+ this.#fs = new Map(createData.fs.map((path) => {
1478
+ const dir = path.slice(0, path.lastIndexOf("/"));
1479
+ if (dir) {
1480
+ dirs.add(dir);
1481
+ }
1482
+ return ["file://" + path, 1];
1483
+ }));
1484
+ for (const dir of dirs) {
1485
+ this.#fs.set("file://" + dir, 2);
1486
+ }
1487
+ createData.fs.length = 0;
1488
+ }
1489
+ this.#createLanguageDocument = createLanguageDocument;
1490
+ }
1476
1491
  get hasFileSystemProvider() {
1477
- return !!this._createData.workspace;
1492
+ return !!this.#fs;
1478
1493
  }
1479
1494
  get host() {
1480
- return this._ctx.host;
1495
+ return this.#ctx.host;
1481
1496
  }
1482
1497
  getMirrorModels() {
1483
- return this._ctx.getMirrorModels();
1498
+ return this.#ctx.getMirrorModels();
1484
1499
  }
1485
1500
  hasModel(fileName) {
1486
1501
  const models = this.getMirrorModels();
@@ -1521,10 +1536,10 @@ var WorkerBase = class {
1521
1536
  if (cached && cached[0] === version && cached[2]) {
1522
1537
  return cached[2];
1523
1538
  }
1524
- if (!this._createLanguageDocument) {
1539
+ if (!this.#createLanguageDocument) {
1525
1540
  throw new Error("createLanguageDocument is not provided");
1526
1541
  }
1527
- const languageDocument = this._createLanguageDocument(document2);
1542
+ const languageDocument = this.#createLanguageDocument(document2);
1528
1543
  this.#documentCache.set(uri, [version, document2, languageDocument]);
1529
1544
  return languageDocument;
1530
1545
  }
@@ -1535,10 +1550,12 @@ var WorkerBase = class {
1535
1550
  if (path.startsWith(uri)) {
1536
1551
  const name = path.slice(uri.length);
1537
1552
  if (!name.includes("/")) {
1538
- if (type === 2) {
1539
- entries.push([name, 2 /* Directory */]);
1540
- } else if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
1541
- entries.push([name, 1 /* File */]);
1553
+ if (type === 1) {
1554
+ if (!extensions || extensions.some((ext) => name.endsWith(ext))) {
1555
+ entries.push([name, 1]);
1556
+ }
1557
+ } else if (type === 2) {
1558
+ entries.push([name, 2]);
1542
1559
  }
1543
1560
  }
1544
1561
  }
@@ -1547,8 +1564,8 @@ var WorkerBase = class {
1547
1564
  return entries;
1548
1565
  }
1549
1566
  getFileSystemProvider() {
1550
- if (this.hasFileSystemProvider) {
1551
- const host = this._ctx.host;
1567
+ if (this.#fs) {
1568
+ const host = this.#ctx.host;
1552
1569
  return {
1553
1570
  readDirectory: (uri) => {
1554
1571
  return Promise.resolve(this.readDir(uri));
@@ -1565,29 +1582,27 @@ var WorkerBase = class {
1565
1582
  }
1566
1583
  // resolveReference implementes the `DocumentContext` interface
1567
1584
  resolveReference(ref, baseUrl) {
1568
- const url = new URL(ref, baseUrl);
1569
- const href = url.href;
1570
- if (url.protocol === "file:" && url.pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
1585
+ const { protocol, pathname, href } = new URL(ref, baseUrl);
1586
+ if (protocol === "file:" && pathname !== "/" && this.#fs && !this.#fs.has(href.endsWith("/") ? href.slice(0, -1) : href)) {
1571
1587
  return void 0;
1572
1588
  }
1573
1589
  return href;
1574
1590
  }
1575
1591
  // #region methods used by the host
1576
- async removeDocumentCache(uri) {
1592
+ async releaseDocument(uri) {
1577
1593
  this.#documentCache.delete(uri);
1578
1594
  }
1579
1595
  async fsNotify(kind, path, type) {
1580
- const url = "file://" + path;
1581
- const entries = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
1596
+ const fs = this.#fs ?? (this.#fs = /* @__PURE__ */ new Map());
1582
1597
  if (kind === "create") {
1583
1598
  if (type) {
1584
- entries.set(url, type);
1599
+ fs.set(path, type);
1585
1600
  }
1586
1601
  } else if (kind === "remove") {
1587
- if (entries.get(url) === 1 /* File */) {
1588
- this.#documentCache.delete(url);
1602
+ if (fs.get(path) === 1) {
1603
+ this.#documentCache.delete(path);
1589
1604
  }
1590
- entries.delete(url);
1605
+ fs.delete(path);
1591
1606
  }
1592
1607
  }
1593
1608
  // #endregion
@@ -1639,14 +1654,14 @@ var TypeScriptWorker = class extends WorkerBase {
1639
1654
  const dirname = path.slice("file:///node_modules/".length);
1640
1655
  return Object.keys(this.#importMap.imports).filter((key) => key !== "@jsxRuntime" && (dirname.length === 0 || key.startsWith(dirname))).map((key) => dirname.length > 0 ? key.slice(dirname.length) : key).filter((key) => key !== "/" && key.includes("/")).map((key) => key.split("/")[0]);
1641
1656
  }
1642
- return this.readDir(path).filter(([_, type]) => type === 2 /* Directory */).map(([name, _]) => name);
1657
+ return this.readDir(path).filter(([_, type]) => type === 2).map(([name, _]) => name);
1643
1658
  }
1644
1659
  readDirectory(path, extensions, exclude, include, depth) {
1645
1660
  if (path.startsWith("file:///node_modules/")) {
1646
1661
  const dirname = path.slice("file:///node_modules/".length);
1647
1662
  return Object.keys(this.#importMap.imports).filter((key) => key !== "@jsxRuntime" && (dirname.length === 0 || key.startsWith(dirname))).map((key) => dirname.length > 0 ? key.slice(dirname.length) : key).filter((key) => !key.includes("/"));
1648
1663
  }
1649
- return this.readDir(path, extensions).filter(([_, type]) => type === 1 /* File */).map(([name, _]) => name);
1664
+ return this.readDir(path, extensions).filter(([_, type]) => type === 1).map(([name, _]) => name);
1650
1665
  }
1651
1666
  fileExists(filename) {
1652
1667
  if (filename.startsWith("/node_modules/")) return false;
@@ -2298,7 +2313,7 @@ var TypeScriptWorker = class extends WorkerBase {
2298
2313
  if (types) {
2299
2314
  for (const uri of Object.keys(this.#types)) {
2300
2315
  if (!(uri in types)) {
2301
- this.removeDocumentCache(uri);
2316
+ this.releaseDocument(uri);
2302
2317
  }
2303
2318
  }
2304
2319
  this.#types = types;
package/dist/shiki.mjs CHANGED
@@ -7917,7 +7917,7 @@ function hashCode(s) {
7917
7917
  return [...s].reduce((hash, c) => Math.imul(31, hash) + c.charCodeAt(0) | 0, 0);
7918
7918
  }
7919
7919
  function normalizeFontFamily(fontFamily) {
7920
- return fontFamily.split(",").map((f) => f.replace(/['"]+/g, "").trim()).filter(Boolean).map((f) => f.includes(" ") ? `'${f}'` : f).join(", ");
7920
+ return fontFamily.split(",").map((f) => f.trim().replace(/['"]+/g, "")).filter(Boolean).map((f) => f.includes(" ") ? `'${f}'` : f).join(", ");
7921
7921
  }
7922
7922
 
7923
7923
  // src/shiki-monaco.ts
@@ -8117,7 +8117,7 @@ function loadTMTheme(src, cdn = "https://esm.sh") {
8117
8117
  return cache.fetch(url2).then((res) => res.json());
8118
8118
  }
8119
8119
  const url = typeof src === "string" ? new URL(src, globalThis.location?.href) : src;
8120
- if (url.protocol === "http" || url.protocol === "https") {
8120
+ if (url.protocol === "http:" || url.protocol === "https:") {
8121
8121
  return cache.fetch(url).then((res) => res.json());
8122
8122
  }
8123
8123
  throw new Error(`Unsupported theme source: ${src}`);
@@ -8131,7 +8131,7 @@ function loadTMGrammar(src, cdn = "https://esm.sh") {
8131
8131
  }
8132
8132
  }
8133
8133
  const url = typeof src === "string" ? new URL(src, globalThis.location?.href) : src;
8134
- if (url.protocol === "http" || url.protocol === "https") {
8134
+ if (url.protocol === "http:" || url.protocol === "https:") {
8135
8135
  return cache.fetch(url).then((res) => res.json());
8136
8136
  }
8137
8137
  throw new Error(`Unsupported grammar source: ${src}`);
package/dist/util.mjs CHANGED
@@ -10,7 +10,7 @@ function decode(data) {
10
10
  function defineProperty(obj, prop, value) {
11
11
  Object.defineProperty(obj, prop, { value });
12
12
  }
13
- function toURL(uri) {
13
+ function normalizeURL(uri) {
14
14
  return uri instanceof URL ? uri : new URL(uri, "file:///");
15
15
  }
16
16
  function filenameToURL(filename) {
@@ -131,10 +131,10 @@ function promisifyIDBRequest(req) {
131
131
  });
132
132
  }
133
133
  async function openIDB(name, version = 1, ...stores) {
134
- const req = indexedDB.open(name, version);
134
+ const openRequest = indexedDB.open(name, version);
135
135
  const promises = [];
136
- req.onupgradeneeded = () => {
137
- const db2 = req.result;
136
+ openRequest.onupgradeneeded = () => {
137
+ const db2 = openRequest.result;
138
138
  for (const { name: name2, keyPath, onCreate } of stores) {
139
139
  if (!db2.objectStoreNames.contains(name2)) {
140
140
  const store = db2.createObjectStore(name2, { keyPath });
@@ -144,15 +144,15 @@ async function openIDB(name, version = 1, ...stores) {
144
144
  }
145
145
  }
146
146
  };
147
- const db = await promisifyIDBRequest(req);
147
+ const db = await promisifyIDBRequest(openRequest);
148
148
  await Promise.all(promises);
149
149
  return db;
150
150
  }
151
151
  function openIDBCursor(store, range, callback, direction) {
152
152
  return new Promise((resolve, reject) => {
153
- const ocr = store.openCursor(range, direction);
154
- ocr.onsuccess = () => {
155
- const cursor = ocr.result;
153
+ const corsor = store.openCursor(range, direction);
154
+ corsor.onsuccess = () => {
155
+ const cursor = corsor.result;
156
156
  if (cursor) {
157
157
  if (callback(cursor) !== false) {
158
158
  cursor.continue();
@@ -161,12 +161,15 @@ function openIDBCursor(store, range, callback, direction) {
161
161
  }
162
162
  resolve();
163
163
  };
164
- ocr.onerror = () => {
165
- reject(ocr.error);
164
+ corsor.onerror = () => {
165
+ reject(corsor.error);
166
166
  };
167
167
  });
168
168
  }
169
169
  function promiseWithResolvers() {
170
+ if (Promise.withResolvers) {
171
+ return Promise.withResolvers();
172
+ }
170
173
  let resolve;
171
174
  let reject;
172
175
  const promise = new Promise((res, rej) => {
@@ -187,10 +190,10 @@ export {
187
190
  filenameToURL,
188
191
  isDigital,
189
192
  isPlainObject,
193
+ normalizeURL,
190
194
  openIDB,
191
195
  openIDBCursor,
192
196
  promiseWithResolvers,
193
197
  promisifyIDBRequest,
194
- supportLocalStorage,
195
- toURL
198
+ supportLocalStorage
196
199
  };
@@ -5,12 +5,12 @@ import {
5
5
  decode,
6
6
  encode,
7
7
  filenameToURL,
8
+ normalizeURL,
8
9
  openIDB,
9
10
  openIDBCursor,
10
11
  promiseWithResolvers,
11
12
  promisifyIDBRequest,
12
- supportLocalStorage,
13
- toURL
13
+ supportLocalStorage
14
14
  } from "./util.mjs";
15
15
  var Workspace = class {
16
16
  _monaco;
@@ -21,14 +21,14 @@ var Workspace = class {
21
21
  constructor(options = {}) {
22
22
  const { name = "default", browserHistory, initialFiles, entryFile, customFS } = options;
23
23
  this._monaco = promiseWithResolvers();
24
- this._fs = customFS ?? new FS("modern-monaco-workspace(" + name + ")");
24
+ this._fs = customFS ?? new IndexedDBFileSystem("modern-monaco-workspace(" + name + ")");
25
25
  this._viewState = new WorkspaceStateStorage("modern-monaco-state(" + name + ")");
26
26
  this._entryFile = entryFile;
27
27
  if (initialFiles) {
28
28
  for (const [name2, data] of Object.entries(initialFiles)) {
29
29
  void this._fs.stat(name2).catch(async (err) => {
30
30
  if (err instanceof ErrorNotFound) {
31
- const { pathname, href: url } = filenameToURL(name2);
31
+ const { pathname } = filenameToURL(name2);
32
32
  const dir = pathname.slice(0, pathname.lastIndexOf("/"));
33
33
  if (dir) {
34
34
  await this._fs.createDirectory(dir);
@@ -68,11 +68,10 @@ var Workspace = class {
68
68
  const monaco = await this._monaco.promise;
69
69
  return this._openTextDocument(uri, monaco.editor.getEditors()[0], void 0, content);
70
70
  }
71
- // @internal
72
71
  async _openTextDocument(uri, editor, selectionOrPosition, readonlyContent) {
73
72
  const monaco = await this._monaco.promise;
74
73
  const fs = this._fs;
75
- const href = toURL(uri).href;
74
+ const href = normalizeURL(uri).href;
76
75
  const content = readonlyContent ?? await fs.readTextFile(href);
77
76
  const viewState = await this.viewState.get(href);
78
77
  const modelUri = monaco.Uri.parse(href);
@@ -137,7 +136,7 @@ var Workspace = class {
137
136
  return monaco.showQuickPick(items, options, token);
138
137
  }
139
138
  };
140
- var FS = class {
139
+ var IndexedDBFileSystem = class {
141
140
  _watchers = /* @__PURE__ */ new Set();
142
141
  _db;
143
142
  constructor(scope) {
@@ -155,13 +154,6 @@ var FS = class {
155
154
  const transaction = (await this._db.open()).transaction(["fs-meta", "fs-blob"], readwrite ? "readwrite" : "readonly");
156
155
  return [transaction.objectStore("fs-meta"), transaction.objectStore("fs-blob")];
157
156
  }
158
- async *walk() {
159
- const metaStore = await this._getIdbObjectStore("fs-meta");
160
- const entries = await promisifyIDBRequest(metaStore.getAll());
161
- for (const entry of entries) {
162
- yield [new URL(entry.url).pathname, entry.type];
163
- }
164
- }
165
157
  async stat(name) {
166
158
  const url = filenameToURL(name).href;
167
159
  if (url === "file:///") {
@@ -428,6 +420,18 @@ var ErrorNotFound = class extends Error {
428
420
  super("No such file or directory: " + name);
429
421
  }
430
422
  };
423
+ async function walk(fs, dir = "/") {
424
+ const entries = [];
425
+ for (const [name, type] of await fs.readDirectory(dir || "/")) {
426
+ const path = (dir.endsWith("/") ? dir.slice(0, -1) : dir) + "/" + name;
427
+ if (type === 2) {
428
+ entries.push(...await walk(fs, path));
429
+ } else {
430
+ entries.push(path);
431
+ }
432
+ }
433
+ return entries;
434
+ }
431
435
  var WorkspaceDatabase = class {
432
436
  _db;
433
437
  constructor(name, ...stores) {
@@ -455,12 +459,12 @@ var WorkspaceStateStorage = class {
455
459
  );
456
460
  }
457
461
  async get(uri) {
458
- const url = toURL(uri).href;
462
+ const url = normalizeURL(uri).href;
459
463
  const store = (await this.#db.open()).transaction("store", "readonly").objectStore("store");
460
464
  return promisifyIDBRequest(store.get(url)).then((result) => result?.state);
461
465
  }
462
466
  async save(uri, state) {
463
- const url = toURL(uri).href;
467
+ const url = normalizeURL(uri).href;
464
468
  const store = (await this.#db.open()).transaction("store", "readwrite").objectStore("store");
465
469
  await promisifyIDBRequest(store.put({ url, state }));
466
470
  }
@@ -584,5 +588,6 @@ var BrowserHistory = class {
584
588
  };
585
589
  export {
586
590
  ErrorNotFound,
587
- Workspace
591
+ Workspace,
592
+ walk
588
593
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "modern-monaco",
3
3
  "description": "A modern version of Monaco Editor",
4
- "version": "0.2.1",
4
+ "version": "0.2.2",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
7
7
  "module": "./dist/index.mjs",
@@ -43,6 +43,9 @@
43
43
  "./util": {
44
44
  "import": "./dist/util.mjs"
45
45
  },
46
+ "./lsp": {
47
+ "import": "./dist/lsp/index.mjs"
48
+ },
46
49
  "./lsp/*": {
47
50
  "import": "./dist/lsp/*.mjs"
48
51
  }
@@ -43,9 +43,23 @@ export interface WorkspaceHistory {
43
43
  onChange(callback: (state: WorkspaceHistoryState) => void): () => void;
44
44
  }
45
45
 
46
- /** 0: unknown, 1: file, 2: directory, 64: symlink */
46
+ /**
47
+ * The type of a file system entry.
48
+ * - `0`: unknown
49
+ * - `1`: file
50
+ * - `2`: directory
51
+ * - `64`: symlink
52
+ */
47
53
  export type FileSystemEntryType = 0 | 1 | 2 | 64;
48
54
 
55
+ export interface FileSystemWatchContext {
56
+ isModelContentChange?: boolean;
57
+ }
58
+
59
+ export interface FileSystemWatchHandle {
60
+ (kind: "create" | "modify" | "remove", filename: string, type?: number, context?: FileSystemWatchContext): void;
61
+ }
62
+
49
63
  export interface FileStat {
50
64
  readonly type: FileSystemEntryType;
51
65
  readonly ctime: number;
@@ -63,14 +77,9 @@ export interface FileSystem {
63
77
  readTextFile(filename: string): Promise<string>;
64
78
  rename(oldName: string, newName: string, options?: { overwrite: boolean }): Promise<void>;
65
79
  stat(filename: string): Promise<FileStat>;
66
- writeFile(filename: string, content: string | Uint8Array, context?: { isModelContentChange: boolean }): Promise<void>;
80
+ writeFile(filename: string, content: string | Uint8Array, context?: FileSystemWatchContext): Promise<void>;
67
81
  watch(filename: string, options: { recursive: boolean }, handle: FileSystemWatchHandle): () => void;
68
82
  watch(filename: string, handle: FileSystemWatchHandle): () => void;
69
- walk(): AsyncIterable<[string, FileSystemEntryType]>;
70
- }
71
-
72
- export interface FileSystemWatchHandle {
73
- (kind: "create" | "modify" | "remove", filename: string, type?: number, context?: { isModelContentChange: boolean }): void;
74
83
  }
75
84
 
76
85
  export class ErrorNotFound extends Error {}