Skip to content

Commit 703057e

Browse files
author
Loïc Mangeonjean
committed
feat: use default export of imported css files
to load them in the shadow dom if available
1 parent ae369f9 commit 703057e

File tree

6 files changed

+81
-2
lines changed

6 files changed

+81
-2
lines changed

rollup/plugins/css-import-plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export default ({
5353
styles[id] = code
5454

5555
return {
56-
code: `renderCSS(${JSON.stringify(code)})`
56+
code: `renderCSS(${JSON.stringify(code)}); export default 'fakeExport'`
5757
}
5858
},
5959

rollup/rollup.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ const input = {
4444
'missing-services': './src/missing-services.ts',
4545
tools: './src/tools.ts',
4646
monaco: './src/monaco.ts',
47+
css: './src/css.ts',
4748
...Object.fromEntries(
4849
fs
4950
.readdirSync(nodePath.resolve(SRC_DIR, 'service-override'), { withFileTypes: true })

rollup/tools/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const OVERRIDE_PATH = nodePath.resolve(BASE_DIR, 'src/override')
2626

2727
const externals = Object.keys({ ...pkg.dependencies })
2828
export const external = (source: string, importer?: string): boolean => {
29-
if (source === 'monaco-editor') {
29+
if (source === 'monaco-editor' || source === '@codingame/monaco-vscode-api/css') {
3030
return true
3131
}
3232
if (importer != null && importer.startsWith(VSCODE_DIR) && source === 'vscode') {

rollup/tools/vscode.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as nodePath from 'node:path'
88
import {
99
DIST_DIR,
1010
DIST_DIR_MAIN,
11+
MAIN_PACKAGE_NAME,
1112
OVERRIDE_PATH,
1213
SRC_DIR,
1314
VSCODE_DIR,
@@ -128,10 +129,12 @@ export function transformVSCodeCode(id: string, code: string): string {
128129
'$2.__decorator = $1'
129130
)
130131

132+
let cssImportCounter = 0
131133
const ast = recast.parse(patchedCode, {
132134
parser: babylonParser
133135
})
134136
let transformed: boolean = false
137+
let cssImported: boolean = false
135138
function addComment(
136139
node: recast.types.namedTypes.NewExpression | recast.types.namedTypes.CallExpression
137140
) {
@@ -173,6 +176,30 @@ export function transformVSCodeCode(id: string, code: string): string {
173176
}
174177
this.traverse(path)
175178
},
179+
visitImportDeclaration(path) {
180+
const node = path.node
181+
182+
if (
183+
(node.specifiers == null || node.specifiers.length === 0) &&
184+
(node.source.value as string).endsWith('.css')
185+
) {
186+
const varName = `css${cssImportCounter++}`
187+
node.specifiers = [
188+
recast.types.builders.importNamespaceSpecifier(recast.types.builders.identifier(varName))
189+
]
190+
const injectCall = recast.types.builders.expressionStatement(
191+
recast.types.builders.callExpression(recast.types.builders.identifier('registerCss'), [
192+
recast.types.builders.identifier(varName)
193+
])
194+
)
195+
196+
path.insertAfter(injectCall)
197+
transformed = true
198+
cssImported = true
199+
}
200+
201+
this.traverse(path)
202+
},
176203
visitClassDeclaration(path) {
177204
/**
178205
* The whole point of this method is to transform to static field declarations
@@ -250,6 +277,16 @@ export function transformVSCodeCode(id: string, code: string): string {
250277
this.traverse(path)
251278
}
252279
})
280+
281+
if (cssImported) {
282+
ast.program.body.unshift(
283+
recast.types.builders.importDeclaration(
284+
[recast.types.builders.importSpecifier(recast.types.builders.identifier('registerCss'))],
285+
recast.types.builders.literal(`${MAIN_PACKAGE_NAME}/css`)
286+
)
287+
)
288+
}
289+
253290
if (transformed) {
254291
patchedCode = recast.print(ast).code
255292
patchedCode = patchedCode.replace(/\/\*#__PURE__\*\/\s+/g, '/*#__PURE__*/ ') // Remove space after PURE comment

src/css.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
const styles: string[] = []
2+
3+
export function registerCss(module: unknown) {
4+
const cssContent = (module as { default?: string }).default
5+
if (typeof cssContent === 'string') {
6+
// Font faces should always be added outside of the shadow dom
7+
const sheet = new CSSStyleSheet()
8+
sheet.replaceSync(cssContent)
9+
const fontFaces = Array.from(sheet.cssRules)
10+
.filter((rule) => rule instanceof CSSFontFaceRule)
11+
.map((r) => r.cssText)
12+
if (fontFaces.length > 0) {
13+
const fontFaceStyle = document.createElement('style')
14+
fontFaceStyle.setAttribute('type', 'text/css')
15+
fontFaceStyle.appendChild(document.createTextNode(fontFaces.join('\n')))
16+
document.head.insertBefore(fontFaceStyle, document.head.firstChild)
17+
}
18+
19+
styles.push(cssContent)
20+
}
21+
}
22+
23+
function getInjectElement(target: HTMLElement) {
24+
const root = target.getRootNode()
25+
if (root instanceof ShadowRoot) {
26+
return root
27+
}
28+
return document.head
29+
}
30+
31+
export function injectCss(target: HTMLElement) {
32+
const root = getInjectElement(target)
33+
34+
for (const style of styles) {
35+
const styleEl = document.createElement('style')
36+
styleEl.appendChild(document.createTextNode(style))
37+
root.appendChild(styleEl)
38+
}
39+
}

src/services.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import getEnvironmentServiceOverride from './service-override/environment'
5050
import getLayoutServiceOverride from './service-override/layout'
5151
import getHostServiceOverride from './service-override/host'
5252
import getBaseServiceOverride from './service-override/base'
53+
import { injectCss } from './css'
5354

5455
declare global {
5556
interface Window {
@@ -73,6 +74,7 @@ export async function initialize(
7374
): Promise<void> {
7475
checkServicesNotInitialized()
7576

77+
injectCss(container)
7678
initializeWorkbench(container, configuration, env)
7779

7880
const instantiationService = StandaloneServices.initialize({

0 commit comments

Comments
 (0)