modern-monaco 0.2.1 → 0.3.0

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/README.md CHANGED
@@ -249,7 +249,7 @@ lazy({
249
249
  },
250
250
  ],
251
251
  // The CDN for loading language grammars and themes. Default is "https://esm.sh"
252
- tmDownloadCDN: "https://esm.sh",
252
+ cdn: "https://esm.sh",
253
253
  });
254
254
  ```
255
255
 
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.3.0";
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 { NotFoundError, Workspace } from "./workspace.mjs";
51
+ import { debunce, decode, getCDNUrl, isDigital } from "./util.mjs";
52
+ import { init as initLspClient } from "./lsp/client.mjs";
40
53
  var editorProps = [
41
54
  "autoDetectHighContrast",
42
55
  "automaticLayout",
@@ -69,19 +82,18 @@ var editorProps = [
69
82
  "wordWrap"
70
83
  ];
71
84
  var errors = {
72
- NotFound: ErrorNotFound
85
+ NotFound: NotFoundError
73
86
  };
74
87
  var syntaxes = [];
75
88
  var lspProviders = {};
76
- var { promise: editorWorkerPromise, resolve: onDidEditorWorkerResolve } = promiseWithResolvers();
77
- var attr = (el, name) => el.getAttribute(name);
78
- var style = (el, style2) => Object.assign(el.style, style2);
89
+ var getAttr = (el, name) => el.getAttribute(name);
90
+ var setStyle = (el, style) => Object.assign(el.style, style);
79
91
  async function init(options) {
80
92
  const langs = (options?.langs ?? []).concat(syntaxes);
81
- const hightlighter = await initShiki({ ...options, langs });
82
- return loadMonaco(hightlighter, options?.workspace, options?.lsp);
93
+ const shiki = await initShiki({ ...options, langs });
94
+ return loadMonaco(shiki, options?.workspace, options?.lsp, options?.cdn);
83
95
  }
84
- async function lazy(options) {
96
+ function lazy(options) {
85
97
  if (!customElements.get("monaco-editor")) {
86
98
  let monacoPromise = null;
87
99
  customElements.define(
@@ -93,7 +105,7 @@ async function lazy(options) {
93
105
  for (const attrName of this.getAttributeNames()) {
94
106
  const key = editorProps.find((k) => k.toLowerCase() === attrName);
95
107
  if (key) {
96
- let value = attr(this, attrName);
108
+ let value = getAttr(this, attrName);
97
109
  if (value === "") {
98
110
  value = key === "minimap" || key === "stickyScroll" ? { enabled: true } : true;
99
111
  } else {
@@ -157,13 +169,13 @@ async function lazy(options) {
157
169
  }
158
170
  firstEl.remove();
159
171
  }
160
- style(this, { display: "block", position: "relative" });
161
- let widthAttr = attr(this, "width");
162
- let heightAttr = attr(this, "height");
172
+ setStyle(this, { display: "block", position: "relative" });
173
+ let widthAttr = getAttr(this, "width");
174
+ let heightAttr = getAttr(this, "height");
163
175
  if (isDigital(widthAttr) && isDigital(heightAttr)) {
164
176
  const width = Number(widthAttr);
165
177
  const height = Number(heightAttr);
166
- style(this, { width: width + "px", height: height + "px" });
178
+ setStyle(this, { width: width + "px", height: height + "px" });
167
179
  renderOptions.dimension = { width, height };
168
180
  } else {
169
181
  if (isDigital(widthAttr)) {
@@ -177,7 +189,7 @@ async function lazy(options) {
177
189
  }
178
190
  const containerEl = document.createElement("div");
179
191
  containerEl.className = "monaco-editor-container";
180
- style(containerEl, { width: "100%", height: "100%" });
192
+ setStyle(containerEl, { width: "100%", height: "100%" });
181
193
  this.appendChild(containerEl);
182
194
  if (!filename && workspace) {
183
195
  if (workspace.history.state.current) {
@@ -200,14 +212,12 @@ async function lazy(options) {
200
212
  langs.push(lang);
201
213
  }
202
214
  }
203
- if (renderOptions.theme) {
204
- renderOptions.theme = renderOptions.theme.toLowerCase().replace(/ +/g, "-");
215
+ let theme = options?.theme ?? renderOptions.theme;
216
+ if (typeof theme === "string") {
217
+ theme = theme.toLowerCase().replace(/ +/g, "-");
205
218
  }
206
- const highlighter = await initShiki({
207
- ...options,
208
- theme: renderOptions.theme ?? options?.theme,
209
- langs
210
- });
219
+ const highlighter = await initShiki({ ...options, theme, langs });
220
+ renderOptions.theme = highlighter.getLoadedThemes()[0];
211
221
  let prerenderEl;
212
222
  for (const el of this.children) {
213
223
  if (el.className === "monaco-editor-prerender") {
@@ -223,14 +233,14 @@ async function lazy(options) {
223
233
  prerenderEl.className = "monaco-editor-prerender";
224
234
  prerenderEl.innerHTML = render(highlighter, decode(code2), { ...renderOptions, language });
225
235
  } catch (error) {
226
- if (error instanceof ErrorNotFound) {
236
+ if (error instanceof NotFoundError) {
227
237
  } else {
228
238
  throw error;
229
239
  }
230
240
  }
231
241
  }
232
242
  if (prerenderEl) {
233
- style(prerenderEl, { position: "absolute", top: "0", left: "0" });
243
+ setStyle(prerenderEl, { position: "absolute", top: "0", left: "0" });
234
244
  this.appendChild(prerenderEl);
235
245
  if (filename && workspace) {
236
246
  const viewState = await workspace.viewState.get(filename);
@@ -243,8 +253,8 @@ async function lazy(options) {
243
253
  }
244
254
  }
245
255
  }
246
- async function createEditor() {
247
- const monaco = await (monacoPromise ?? (monacoPromise = loadMonaco(highlighter, workspace, options?.lsp)));
256
+ {
257
+ const monaco = await (monacoPromise ?? (monacoPromise = loadMonaco(highlighter, workspace, options?.lsp, options?.cdn)));
248
258
  const editor = monaco.editor.create(containerEl, renderOptions);
249
259
  if (workspace) {
250
260
  const storeViewState = () => {
@@ -272,7 +282,7 @@ async function lazy(options) {
272
282
  model.setValue(code);
273
283
  }
274
284
  } catch (error) {
275
- if (error instanceof ErrorNotFound) {
285
+ if (error instanceof NotFoundError) {
276
286
  if (code) {
277
287
  const dirname = filename.split("/").slice(0, -1).join("/");
278
288
  if (dirname) {
@@ -300,34 +310,49 @@ async function lazy(options) {
300
310
  editor.setModel(monaco.editor.createModel(""));
301
311
  }
302
312
  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
- });
313
+ setTimeout(() => {
314
+ const animate = prerenderEl.animate?.([{ opacity: 1 }, { opacity: 0 }], { duration: 200 });
315
+ if (animate) {
316
+ animate.finished.then(() => prerenderEl.remove());
317
+ } else {
318
+ setTimeout(() => prerenderEl.remove(), 200);
319
+ }
320
+ }, 200);
313
321
  }
314
322
  }
315
- await createEditor();
316
323
  }
317
324
  }
318
325
  );
319
326
  }
320
- await editorWorkerPromise;
321
327
  }
322
328
  function hydrate(options) {
323
329
  return lazy(options);
324
330
  }
325
- async function loadMonaco(highlighter, workspace, lsp) {
326
- const monaco = await import("./editor-core.mjs");
327
- const lspProviderMap = { ...lspProviders, ...lsp?.providers };
331
+ async function loadMonaco(highlighter, workspace, lsp, cdn) {
332
+ let editorCoreModuleUrl = getCDNUrl(`/modern-monaco@${version}/dist/editor-core.mjs`, cdn);
333
+ let lspModuleUrl = getCDNUrl(`/modern-monaco@${version}/dist/lsp/index.mjs`, cdn);
334
+ let importmapEl = null;
335
+ if (importmapEl = document.querySelector("script[type='importmap']")) {
336
+ try {
337
+ const { imports = {} } = parseImportMapFromJson(importmapEl.textContent);
338
+ if (imports["modern-monaco/editor-core"]) {
339
+ editorCoreModuleUrl = imports["modern-monaco/editor-core"];
340
+ }
341
+ if (imports["modern-monaco/lsp"]) {
342
+ lspModuleUrl = imports["modern-monaco/lsp"];
343
+ }
344
+ } catch (error) {
345
+ }
346
+ }
347
+ const useBuiltinLSP = globalThis.MonacoEnvironment?.useBuiltinLSP;
348
+ const [monaco, { builtinLSPProviders }] = await Promise.all([
349
+ import(editorCoreModuleUrl),
350
+ useBuiltinLSP ? import(lspModuleUrl) : Promise.resolve({ builtinLSPProviders: {} })
351
+ ]);
352
+ const allLspProviders = { ...builtinLSPProviders, ...lspProviders, ...lsp?.providers };
328
353
  workspace?.setupMonaco(monaco);
329
- if (Object.keys(lspProviderMap).length > 0) {
330
- initLS(monaco);
354
+ if (Object.keys(allLspProviders).length > 0) {
355
+ initLspClient(monaco);
331
356
  }
332
357
  if (!document.getElementById("monaco-editor-core-css")) {
333
358
  const styleEl = document.createElement("style");
@@ -339,13 +364,7 @@ async function loadMonaco(highlighter, workspace, lsp) {
339
364
  Reflect.set(globalThis, "MonacoEnvironment", {
340
365
  getWorker: async (_workerId, label) => {
341
366
  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;
367
+ return monaco.createEditorWorkerMain();
349
368
  }
350
369
  },
351
370
  getLanguageIdFromUri: (uri) => getLanguageIdFromPath(uri.path),
@@ -366,7 +385,7 @@ async function loadMonaco(highlighter, workspace, lsp) {
366
385
  await workspace._openTextDocument(resource.toString(), editor, selectionOrPosition);
367
386
  return true;
368
387
  } catch (err) {
369
- if (err instanceof ErrorNotFound) {
388
+ if (err instanceof NotFoundError) {
370
389
  return false;
371
390
  }
372
391
  throw err;
@@ -421,9 +440,9 @@ async function loadMonaco(highlighter, workspace, lsp) {
421
440
  }
422
441
  registerShikiMonacoTokenizer(monaco, highlighter, id);
423
442
  let lspLabel = id;
424
- let lspProvider = lspProviderMap[lspLabel];
443
+ let lspProvider = allLspProviders[lspLabel];
425
444
  if (!lspProvider) {
426
- const alias = Object.entries(lspProviderMap).find(([, lsp2]) => lsp2.aliases?.includes(id));
445
+ const alias = Object.entries(allLspProviders).find(([, lsp2]) => lsp2.aliases?.includes(id));
427
446
  if (alias) {
428
447
  [lspLabel, lspProvider] = alias;
429
448
  }