Skip to content

Commit 05b2386

Browse files
authored
Merge pull request #617 from CodinGame/shadow-root
Support shadow root
2 parents 8161745 + 71d0e99 commit 05b2386

20 files changed

+2277
-1122
lines changed

README.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,80 @@ npm run start:debugServer
323323

324324
See the [VSCode Server](https://github.com/CodinGame/monaco-vscode-api/wiki/How-to-install-and-use-VSCode-server-with-monaco‐vscode‐api) wiki page.
325325

326+
## Shadow dom (⚠️ beta ⚠️)
327+
328+
The library supports shadow-dom.
329+
330+
⚠️ VSCode itself doesn't support shadow dom, and there are multiple parts that needed to be patched in order for it to work.
331+
332+
There are multiple benefits of using it:
333+
- Your custom global style won't impact the VSCode workbench style (for instance if you did override the default [box-sizing](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing))
334+
- The VSCode styles won't impact other parts of your app
335+
- You page head won't be polluted with dozen of css files from VSCode
336+
337+
### How to use it
338+
339+
If the provided container element is a child of a shadow dom element, the styles will be injected in both the main page and the shadow root. That's it.
340+
341+
### ⚠️ Xterm notice ⚠️
342+
343+
The webgl renderer of xterm, which VSCode is using, doesn't support being used inside a shadom dom (see https://github.com/xtermjs/xterm.js/pull/5334).
344+
Until it's fixed and deployed, either do not use the terminal service override, or apply the patch on your side (using [patch-package](https://www.npmjs.com/package/patch-package) for instance).
345+
346+
### Prerequisites
347+
348+
In order to be able to load the static css files in the shadow dom as well. Your bundler configuration needs to be adapted so that importing css files doesn't load their content in the page head, but instead just returns the file content as default (either as a string or a `CSSStyleSheet`). It can be achieved with most bundlers with some configurations.
349+
350+
Note that the bundler should still resolve referenced assets in the css files, so you can't just use the `raw` loader, or the `assets/source` webpack module type.
351+
352+
#### Webpack
353+
354+
Add this rule in your configuration:
355+
356+
```typescript
357+
{
358+
test: /node_modules\/(@codingame\/monaco-vscode|vscode|monaco-editor).*\.css$/,
359+
use: [
360+
{
361+
loader: 'css-loader',
362+
options: {
363+
esModule: false,
364+
exportType: 'css-style-sheet', // or 'string', both are working
365+
url: true,
366+
import: true
367+
}
368+
}
369+
]
370+
}
371+
```
372+
373+
You should also make sure that no other loader is interfering with it, by either use a `oneOf` or exclusing those files in the other css loaders.
374+
375+
#### Vite
376+
377+
Add this plugin in your configuration:
378+
379+
```typescript
380+
{
381+
name: 'load-vscode-css-as-string',
382+
enforce: 'pre',
383+
async resolveId(source, importer, options) {
384+
const resolved = (await this.resolve(source, importer, options))!
385+
if (
386+
resolved.id.match(
387+
/node_modules\/(@codingame\/monaco-vscode|vscode|monaco-editor).*\.css$/
388+
)
389+
) {
390+
return {
391+
...resolved,
392+
id: resolved.id + '?inline'
393+
}
394+
}
395+
return undefined
396+
}
397+
}
398+
```
399+
326400
## Troubleshooting
327401

328402
If something doesn't work, make sure to check out the [Troubleshooting](https://github.com/CodinGame/monaco-vscode-api/wiki/Troubleshooting) wiki page.

demo/package-lock.json

Lines changed: 1133 additions & 308 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

demo/package.json

Lines changed: 32 additions & 19 deletions
Large diffs are not rendered by default.

demo/patches/@xterm+addon-webgl+0.19.0-beta.99.patch

Lines changed: 20 additions & 0 deletions
Large diffs are not rendered by default.

demo/src/main.workbench.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,13 @@ document.querySelector('#customEditorPanel')!.addEventListener('click', async ()
2929
document.querySelector('#clearStorage')!.addEventListener('click', async () => {
3030
await clearStorage()
3131
})
32+
33+
document.querySelector('#toggleShadowDom')!.addEventListener('click', async () => {
34+
const url = new URL(window.location.href)
35+
if (url.searchParams.has('disableShadowDom')) {
36+
url.searchParams.delete('disableShadowDom')
37+
} else {
38+
url.searchParams.set('disableShadowDom', 'true')
39+
}
40+
window.location.href = url.toString()
41+
})

demo/src/setup.common.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ export const remotePath =
9595
remoteAuthority != null ? (params.get('remotePath') ?? undefined) : undefined
9696
export const resetLayout = params.has('resetLayout')
9797
export const useHtmlFileSystemProvider = params.has('htmlFileSystemProvider')
98+
export const disableShadowDom = params.has('disableShadowDom')
9899
params.delete('resetLayout')
99100

100101
window.history.replaceState({}, document.title, url.href)

demo/src/setup.workbench.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,30 @@ import {
1717
constructOptions,
1818
envOptions,
1919
remoteAuthority,
20-
userDataProvider
20+
userDataProvider,
21+
disableShadowDom
2122
} from './setup.common'
2223

23-
const container = document.createElement('div')
24+
let container = document.createElement('div')
2425
container.style.height = '100vh'
2526

2627
document.body.replaceChildren(container)
2728

29+
if (!disableShadowDom) {
30+
const shadowRoot = container.attachShadow({
31+
mode: 'open'
32+
})
33+
34+
const workbenchElement = document.createElement('div')
35+
workbenchElement.style.height = '100vh'
36+
shadowRoot.appendChild(workbenchElement)
37+
container = workbenchElement
38+
}
39+
2840
const buttons = document.createElement('div')
2941
buttons.innerHTML = `
3042
<button id="toggleHTMLFileSystemProvider">Toggle HTML filesystem provider</button>
43+
<button id="toggleShadowDom">Toggle Shadow Dom usage</button>
3144
<button id="customEditorPanel">Open custom editor panel</button>
3245
<button id="clearStorage">Clear user data</button>
3346
<button id="resetLayout">Reset layout</button>

demo/vite.config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,24 @@ export default defineConfig({
1717
format: 'es'
1818
},
1919
plugins: [
20+
{
21+
name: 'load-vscode-css-as-string',
22+
enforce: 'pre',
23+
async resolveId(source, importer, options) {
24+
const resolved = (await this.resolve(source, importer, options))!
25+
if (
26+
resolved.id.match(
27+
/node_modules\/(@codingame\/monaco-vscode|vscode|monaco-editor).*\.css$/
28+
)
29+
) {
30+
return {
31+
...resolved,
32+
id: resolved.id + '?inline'
33+
}
34+
}
35+
return undefined
36+
}
37+
},
2038
{
2139
// For the *-language-features extensions which use SharedArrayBuffer
2240
name: 'configure-response-headers',

demo/vite.netlify.config.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,26 @@ export default defineConfig({
1313
target: 'esnext',
1414
assetsInlineLimit: 0
1515
},
16+
plugins: [
17+
{
18+
name: 'load-vscode-css-as-string',
19+
enforce: 'pre',
20+
async resolveId(source, importer, options) {
21+
const resolved = (await this.resolve(source, importer, options))!
22+
if (
23+
resolved.id.match(
24+
/node_modules\/(@codingame\/monaco-vscode|vscode|monaco-editor).*\.css$/
25+
)
26+
) {
27+
return {
28+
...resolved,
29+
id: resolved.id + '?inline'
30+
}
31+
}
32+
return undefined
33+
}
34+
}
35+
],
1636
worker: {
1737
format: 'es'
1838
},

docs/vscode_monaco_upgrade.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
- Update dependencies
3131
- Implement improvements dependening on the new features available from vscode (optional)
3232
- Don't forget to check the `Window` output (in the `OUTPUT` panel tab) to check for errors
33+
- Check all possible combinations
34+
- Full workbench mode or not
35+
- Shadow dom mode or not
36+
- Using VSCode server
37+
- Using HTML file system provider
38+
- ...
3339

3440
## monaco-vscode-api demo
3541

0 commit comments

Comments
 (0)