modern-monaco 0.0.0-beta.5 → 0.1.1

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
@@ -1,20 +1,20 @@
1
1
  > [!WARNING]
2
- > **This project is currently under active development, the API may change at any time. Use at your own risk.**
2
+ > **This project is currently under active development. The API may change at any time. Use at your own risk.**
3
3
  > Please report any issues or feature requests on the [issues](https://github.com/esm-dev/modern-monaco/issues) page.
4
4
 
5
5
  # Modern Monaco
6
6
 
7
- Meeting the modern version of [Monaco Editor](https://www.npmjs.com/package/monaco-editor):
7
+ Meet the modern version of [Monaco Editor](https://www.npmjs.com/package/monaco-editor):
8
8
 
9
- - Easy to use, no `MonacoEnvironment` setup and web-worker/css loader needed.
10
- - Using [Shiki](https://shiki.style) for syntax highlighting with tons of grammars and themes.
11
- - Lazy loading: pre-highlighting code with Shiki while loading `monaco-editor-core` in background.
12
- - Support server-side rendering(SSR).
13
- - Workspace (edit history, file system provider, persist protocol, etc).
14
- - Automatically loading `.d.ts` from [esm.sh](https://esm.sh) CDN for type checking.
15
- - Using [import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) for resolving **bare specifier** imports in JavaScript/TypeScript.
9
+ - Easy to use, no `MonacoEnvironment` setup, web workers, or CSS loaders required.
10
+ - Uses [Shiki](https://shiki.style) for syntax highlighting with extensive grammars and themes.
11
+ - Lazy loading: pre-highlight code with Shiki while loading `monaco-editor-core` in the background.
12
+ - Supports server-side rendering (SSR).
13
+ - Workspace features (edit history, file system provider, persist protocol, etc.).
14
+ - Automatically loads `.d.ts` files from [esm.sh](https://esm.sh) CDN for type checking.
15
+ - Uses [import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap) for resolving **bare specifier** imports in JavaScript/TypeScript.
16
16
  - VSCode `window` APIs like `showInputBox`, `showQuickPick`, etc.
17
- - Embedded languages(importmap/CSS/JavaScript) in HTML.
17
+ - Embedded languages (importmap/CSS/JavaScript) in HTML.
18
18
  - Inline `html` and `css` in JavaScript/TypeScript.
19
19
  - Auto-closing HTML/JSX tags.
20
20
 
@@ -27,9 +27,9 @@ npm i modern-monaco typescript
27
27
  ```
28
28
 
29
29
  > [!Note]
30
- > The `typescript` package is required by JavaScript/TypeScript LSP worker. We recommend `typescript@5.5.x` or later.
30
+ > The `typescript` package is required by the JavaScript/TypeScript LSP worker. We recommend `typescript@5.5.x` or later.
31
31
 
32
- or import it from [esm.sh](https://esm.sh/) CDN in browser without build step:
32
+ Or import it from [esm.sh](https://esm.sh/) CDN in the browser without a build step:
33
33
 
34
34
  ```js
35
35
  import * from "https://esm.sh/modern-monaco"
@@ -40,38 +40,46 @@ import * from "https://esm.sh/modern-monaco"
40
40
  `modern-monaco` provides three modes to create a browser-based code editor:
41
41
 
42
42
  - **Lazy**: pre-highlight code with Shiki while loading the `editor-core.js` in the background.
43
- - **SSR**: render a mock editor on the server side, and hydrate it on the client side.
44
- - **Manual**: create a monaco editor instance manually.
43
+ - **SSR**: render a mock editor on the server side and hydrates it on the client side.
44
+ - **Manual**: create a Monaco editor instance manually.
45
45
 
46
46
  ### Lazy Mode
47
47
 
48
- [monaco-editor](https://www.npmjs.com/package/monaco-editor) is a large package with extra CSS/Worker modules, and needs the `MonacoEnvironment` setup for language service support. `modern-monaco` provides a lazy but smart way to load the editor modules on demand.
48
+ [monaco-editor](https://www.npmjs.com/package/monaco-editor) is a large package with additional CSS/Worker modules that requires `MonacoEnvironment` setup for language service support. `modern-monaco` provides a simple yet smart way to load editor modules on demand.
49
49
 
50
- By pre-highlighting code with Shiki while loading editor modules in the background, `modern-monaco` can reduce the loading screen time.
50
+ By pre-highlighting code with Shiki while loading editor modules in the background, `modern-monaco` can significantly reduce loading screen time.
51
+
52
+ To create a Monaco editor lazily, you need to add a `<monaco-editor>` custom element in your app's HTML, then call the `lazy` function from modern-monaco. You also need to provide a workspace object to manage files for the editor.
51
53
 
52
54
  ```html
55
+ <!-- index.html -->
53
56
  <monaco-editor></monaco-editor>
57
+ <script src="app.js" type="module"></script>
58
+ ```
54
59
 
55
- <script type="module">
56
- import { lazy, Workspace } from "modern-monaco";
60
+ ```js
61
+ // app.js
62
+ import { lazy, Workspace } from "modern-monaco";
57
63
 
58
- // create a workspace with initial files
59
- const workspace = new Workspace({
60
- initialFiles: {
61
- "index.html": `<html><head><title>Hello, world!</title></head><body><script src="main.js"></script></body></html>`,
62
- "main.js": `console.log("Hello, world!")`
63
- },
64
- entryFile: "index.html",
65
- });
64
+ // create a workspace with initial files
65
+ const workspace = new Workspace({
66
+ initialFiles: {
67
+ "index.html": `<html>...</body></html>`,
68
+ "main.js": `console.log("Hello, world!")`
69
+ },
70
+ entryFile: "index.html",
71
+ });
66
72
 
67
- // initialize the editor lazily
68
- lazy({ workspace });
69
- </script>
73
+ // initialize the editor lazily
74
+ await lazy({ workspace });
75
+
76
+ // open a file in the workspace
77
+ workspace.openTextDocument("main.js");
70
78
  ```
71
79
 
72
80
  ### SSR Mode
73
81
 
74
- SSR mode returns an instant pre-rendered editor on the server side, and hydrate it on the client side.
82
+ SSR mode returns an instant pre-rendered editor on the server side and hydrates it on the client side.
75
83
 
76
84
  ```js
77
85
  import { renderToWebComponent } from "modern-monaco/ssr";
@@ -103,7 +111,7 @@ export default {
103
111
 
104
112
  ### Manual Mode
105
113
 
106
- You can also create a [monaco editor](https://microsoft.github.io/monaco-editor/docs.html) instance manually.
114
+ You can also create a [Monaco editor](https://microsoft.github.io/monaco-editor/docs.html) instance manually. It loads themes and language grammars automatically.
107
115
 
108
116
  ```html
109
117
  <div id="editor"></div>
@@ -114,7 +122,7 @@ You can also create a [monaco editor](https://microsoft.github.io/monaco-editor/
114
122
  // load monaco-editor-core.js
115
123
  const monaco = await init();
116
124
 
117
- // create a monaco editor instance
125
+ // create a Monaco editor instance
118
126
  const editor = monaco.editor.create(document.getElementById("editor"));
119
127
 
120
128
  // create and attach a model to the editor
@@ -124,21 +132,21 @@ You can also create a [monaco editor](https://microsoft.github.io/monaco-editor/
124
132
 
125
133
  ## Using Workspace
126
134
 
127
- `modern-monaco` provides VSCode-like workspace features, like edit history, file system provider, etc.
135
+ `modern-monaco` provides VSCode-like workspace features, such as edit history, file system provider, and more.
128
136
 
129
137
  ```js
130
138
  import { lazy, Workspace } from "modern-monaco";
131
139
 
132
140
  // 1. create a workspace with initial files
133
141
  const workspace = new Workspace({
134
- /** the name of the workspace, used for project isolation, default is "default". */
142
+ /** The name of the workspace, used for project isolation. Default is "default". */
135
143
  name: "project-name",
136
- /** initial files in the workspace. */
144
+ /** Initial files in the workspace. */
137
145
  initialFiles: {
138
146
  "index.html": `<html><head><title>Hello, world!</title></head><body><script src="main.js"></script></body></html>`,
139
147
  "main.js": `console.log("Hello, world!")`,
140
148
  },
141
- /** file to open when the editor is loaded for the first time. */
149
+ /** File to open when the editor is loaded for the first time. */
142
150
  entryFile: "index.html",
143
151
  });
144
152
 
@@ -205,7 +213,7 @@ const workspace = new Workspace({
205
213
  });
206
214
  ```
207
215
 
208
- You can also provide an importmap object as the `lsp.typescript.importMap` option in the `lazy`, `init`, or `hydrate` function.
216
+ You can also provide an import map object as the `lsp.typescript.importMap` option in the `lazy`, `init`, or `hydrate` functions.
209
217
 
210
218
  ```js
211
219
  lazy({
@@ -221,22 +229,42 @@ lazy({
221
229
  ```
222
230
 
223
231
  > [!Note]
224
- > By default, `modern-monaco` uses `react` or `preact` in the `importmap` script as the `jsxImportSource` option for typescript worker.
225
- > To use a custom `jsxImportSource` option, add `@jsxRuntime` specifier in the `importmap` script.
232
+ > By default, `modern-monaco` uses `react` or `preact` in the `importmap` script as the `jsxImportSource` option for the TypeScript worker.
233
+ > To use a custom `jsxImportSource` option, add the `@jsxRuntime` specifier in the `importmap` script.
234
+
235
+ ### Using Custom FileSystem
236
+
237
+ You can provide a custom filesystem implementation to override the default IndexedDB filesystem.
238
+
239
+ ```ts
240
+ import { lazy, type FileSystem, Workspace } from "modern-monaco";
241
+
242
+ class CustomFileSystem implements FileSystem {
243
+ // Custom FileSystem implementation
244
+ }
245
+
246
+ const workspace = new Workspace({
247
+ initialFiles: {
248
+ "index.html": indexHtml,
249
+ "app.tsx": appTsx,
250
+ },
251
+ customFs: new CustomFileSystem(),
252
+ });
253
+ ```
226
254
 
227
255
  ## Editor Theme & Language Grammars
228
256
 
229
- `modern-monaco` uses [Shiki](https://shiki.style) for syntax highlighting with tons of grammars and themes. By default, it loads themes and grammars from esm.sh on demand.
257
+ `modern-monaco` uses [Shiki](https://shiki.style) for syntax highlighting with extensive grammars and themes. By default, it loads themes and grammars from esm.sh on demand.
230
258
 
231
259
  ### Setting the Editor Theme
232
260
 
233
- To set the theme of the editor, you can add a `theme` attribute to the `<monaco-editor>` element.
261
+ To set the editor theme, you can add a `theme` attribute to the `<monaco-editor>` element.
234
262
 
235
263
  ```html
236
264
  <monaco-editor theme="OneDark-Pro"></monaco-editor>
237
265
  ```
238
266
 
239
- or set it in the `lazy`, `init`, or `hydrate` function.
267
+ Or set it in the `lazy`, `init`, or `hydrate` function.
240
268
 
241
269
  ```js
242
270
  lazy({
@@ -253,13 +281,13 @@ lazy({
253
281
  import OneDark from "tm-themes/themes/OneDark-Pro.json" with { type: "json" };
254
282
 
255
283
  lazy({
256
- theme: OneDark
284
+ theme: OneDark,
257
285
  });
258
286
  ```
259
287
 
260
288
  ### Pre-loading Language Grammars
261
289
 
262
- By default, `modern-monaco` loads language grammars when a specific language mode is attached in the editor. You can also pre-load language grammars by adding the `langs` option to the `lazy`, `init`, or `hydrate` function. The `langs` option is an array of language grammars, which can be a language grammar object, a language ID, or a URL to the language grammar.
290
+ By default, `modern-monaco` loads language grammars when a specific language mode is attached to the editor. You can also pre-load language grammars by adding the `langs` option to the `lazy`, `init`, or `hydrate` functions. The `langs` option is an array of language grammars, which can be a language grammar object, a language ID, or a URL to the language grammar.
263
291
 
264
292
  ```js
265
293
  import markdown from "tm-grammars/markdown.json" with { type: "json" };
@@ -278,7 +306,7 @@ lazy({
278
306
  // load language grammar from a local file
279
307
  "/assets/mylang.json",
280
308
 
281
- // use `tm-grammars` package without extra http requests, but increases the bundle size
309
+ // use `tm-grammars` package without extra HTTP requests, but increases the bundle size
282
310
  markdown,
283
311
 
284
312
  // dynamically import
@@ -291,14 +319,14 @@ lazy({
291
319
  patterns: [/* ... */],
292
320
  },
293
321
  ],
294
- // the CDN for loading language grammars and themes, default is "https://esm.sh"
295
- tmDownloadCDN: "https://unpkg.com",
322
+ // The CDN for loading language grammars and themes. Default is "https://esm.sh"
323
+ tmDownloadCDN: "https://esm.sh",
296
324
  });
297
325
  ```
298
326
 
299
327
  ## Editor Options
300
328
 
301
- You can set the editor options in the `<monaco-editor>` element as attributes. The editor options are the same as the [`editor.EditorOptions`](https://microsoft.github.io/monaco-editor/docs.html#variables/editor.EditorOptions.html).
329
+ You can set editor options as attributes in the `<monaco-editor>` element. The editor options are the same as [`editor.EditorOptions`](https://microsoft.github.io/monaco-editor/docs.html#variables/editor.EditorOptions.html).
302
330
 
303
331
  ```html
304
332
  <monaco-editor
@@ -308,7 +336,7 @@ You can set the editor options in the `<monaco-editor>` element as attributes. T
308
336
  ></monaco-editor>
309
337
  ```
310
338
 
311
- For SSR mode, you can set the editor options in the `renderToWebComponent` function.
339
+ For SSR mode, you can set editor options in the `renderToWebComponent` function.
312
340
 
313
341
  ```js
314
342
  import { renderToWebComponent } from "modern-monaco/ssr";
@@ -335,20 +363,20 @@ For manual mode, check [here](https://microsoft.github.io/monaco-editor/docs.htm
335
363
  - JavaScript/TypeScript
336
364
  - JSON
337
365
 
338
- Plus, `modern-monaco` also supports features like:
366
+ Additionally, `modern-monaco` supports features like:
339
367
 
340
368
  - File System Provider for import completions
341
369
  - Embedded languages in HTML
342
- - Inline `html` and `css` in JavaScript/TypeScript.
370
+ - Inline `html` and `css` in JavaScript/TypeScript
343
371
  - Auto-closing HTML/JSX tags
344
372
 
345
373
  > [!Note]
346
- > You don't need to set the `MonacoEnvironment.getWorker` for LSP support.
347
- > `modern-monaco` will automatically load the required LSP workers.
374
+ > You don't need to set `MonacoEnvironment.getWorker` for LSP support.
375
+ > `modern-monaco` automatically loads the required LSP workers.
348
376
 
349
- ### LSP language configuration
377
+ ### LSP Language Configuration
350
378
 
351
- You can configure built-in LSPs in the `lazy`, `init`, or `hydrate` function.
379
+ You can configure built-in LSPs in the `lazy`, `init`, or `hydrate` functions.
352
380
 
353
381
  ```js
354
382
  lazy({
@@ -386,7 +414,7 @@ export interface LSPLanguageConfig {
386
414
  }
387
415
  ```
388
416
 
389
- ## Using `core` module
417
+ ## Using the `core` Module
390
418
 
391
419
  `modern-monaco` includes built-in grammars and LSP providers for HTML, CSS, JavaScript/TypeScript, and JSON. If you don't need these features, you can use the `modern-monaco/core` sub-module to reduce the bundle size.
392
420
 
package/dist/core.js CHANGED
@@ -91,25 +91,15 @@ async function init(options) {
91
91
  return loadMonaco(hightlighter, options?.workspace, options?.lsp);
92
92
  }
93
93
  async function lazy(options, hydrate2) {
94
- const workspace = options?.workspace;
95
94
  const { promise: editorWorkerPromise, resolve: onDidEditorWorkerResolve } = promiseWithResolvers();
96
- let monacoCore = null;
97
- function load(highlighter) {
98
- if (monacoCore) {
99
- return monacoCore;
100
- }
101
- return monacoCore = loadMonaco(highlighter, workspace, options?.lsp, onDidEditorWorkerResolve).then((m) => monacoCore = m);
102
- }
103
- function setStyle(el, style) {
104
- Object.assign(el.style, style);
105
- }
106
- function getAttr(el, name) {
107
- return el.getAttribute(name);
108
- }
95
+ const getAttr = (el, name) => el.getAttribute(name);
96
+ const setStyle = (el, style) => Object.assign(el.style, style);
97
+ let monacoPromise = null;
109
98
  customElements.define(
110
99
  "monaco-editor",
111
100
  class extends HTMLElement {
112
101
  async connectedCallback() {
102
+ const workspace = options?.workspace;
113
103
  const renderOptions = {};
114
104
  for (const attrName of this.getAttributeNames()) {
115
105
  const key = editorProps.find((k) => k.toLowerCase() === attrName);
@@ -261,7 +251,7 @@ async function lazy(options, hydrate2) {
261
251
  }
262
252
  }
263
253
  async function createEditor() {
264
- const monaco = await load(highlighter);
254
+ const monaco = await (monacoPromise ?? (monacoPromise = loadMonaco(highlighter, workspace, options?.lsp, onDidEditorWorkerResolve)));
265
255
  const editor = monaco.editor.create(containerEl, renderOptions);
266
256
  if (workspace) {
267
257
  const storeViewState = () => {
@@ -324,9 +314,6 @@ async function lazy(options, hydrate2) {
324
314
  }
325
315
  );
326
316
  await editorWorkerPromise;
327
- return {
328
- workspace
329
- };
330
317
  }
331
318
  function hydrate(options) {
332
319
  return lazy(options, true);
package/dist/index.js CHANGED
@@ -715,7 +715,7 @@ var builtinLSPProviders = {
715
715
  }
716
716
  };
717
717
 
718
- // node_modules/.pnpm/tm-grammars@1.24.1/node_modules/tm-grammars/grammars/html.json
718
+ // node_modules/.pnpm/tm-grammars@1.24.3/node_modules/tm-grammars/grammars/html.json
719
719
  var html_default = {
720
720
  displayName: "HTML",
721
721
  injections: {
@@ -3344,7 +3344,7 @@ var html_default = {
3344
3344
  scopeName: "text.html.basic"
3345
3345
  };
3346
3346
 
3347
- // node_modules/.pnpm/tm-grammars@1.24.1/node_modules/tm-grammars/grammars/css.json
3347
+ // node_modules/.pnpm/tm-grammars@1.24.3/node_modules/tm-grammars/grammars/css.json
3348
3348
  var css_default = {
3349
3349
  displayName: "CSS",
3350
3350
  name: "css",
@@ -5206,7 +5206,7 @@ var css_default = {
5206
5206
  scopeName: "source.css"
5207
5207
  };
5208
5208
 
5209
- // node_modules/.pnpm/tm-grammars@1.24.1/node_modules/tm-grammars/grammars/javascript.json
5209
+ // node_modules/.pnpm/tm-grammars@1.24.3/node_modules/tm-grammars/grammars/javascript.json
5210
5210
  var javascript_default = {
5211
5211
  displayName: "JavaScript",
5212
5212
  name: "javascript",
@@ -11204,7 +11204,7 @@ var javascript_default = {
11204
11204
  scopeName: "source.js"
11205
11205
  };
11206
11206
 
11207
- // node_modules/.pnpm/tm-grammars@1.24.1/node_modules/tm-grammars/grammars/typescript.json
11207
+ // node_modules/.pnpm/tm-grammars@1.24.3/node_modules/tm-grammars/grammars/typescript.json
11208
11208
  var typescript_default = {
11209
11209
  displayName: "TypeScript",
11210
11210
  name: "typescript",
@@ -16953,7 +16953,7 @@ var typescript_default = {
16953
16953
  scopeName: "source.ts"
16954
16954
  };
16955
16955
 
16956
- // node_modules/.pnpm/tm-grammars@1.24.1/node_modules/tm-grammars/grammars/jsx.json
16956
+ // node_modules/.pnpm/tm-grammars@1.24.3/node_modules/tm-grammars/grammars/jsx.json
16957
16957
  var jsx_default = {
16958
16958
  displayName: "JSX",
16959
16959
  name: "jsx",
@@ -22951,7 +22951,7 @@ var jsx_default = {
22951
22951
  scopeName: "source.js.jsx"
22952
22952
  };
22953
22953
 
22954
- // node_modules/.pnpm/tm-grammars@1.24.1/node_modules/tm-grammars/grammars/tsx.json
22954
+ // node_modules/.pnpm/tm-grammars@1.24.3/node_modules/tm-grammars/grammars/tsx.json
22955
22955
  var tsx_default = {
22956
22956
  displayName: "TSX",
22957
22957
  name: "tsx",
@@ -28949,7 +28949,7 @@ var tsx_default = {
28949
28949
  scopeName: "source.tsx"
28950
28950
  };
28951
28951
 
28952
- // node_modules/.pnpm/tm-grammars@1.24.1/node_modules/tm-grammars/grammars/json.json
28952
+ // node_modules/.pnpm/tm-grammars@1.24.3/node_modules/tm-grammars/grammars/json.json
28953
28953
  var json_default = {
28954
28954
  displayName: "JSON",
28955
28955
  name: "json",