Skip to content
This repository was archived by the owner on Jul 6, 2025. It is now read-only.

Commit cd1001c

Browse files
committed
breaking: support css out-of-the-box
1 parent d725578 commit cd1001c

File tree

8 files changed

+214
-231
lines changed

8 files changed

+214
-231
lines changed

compiler/css.ts

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import { Plugin, PluginCreator } from 'https://esm.sh/[email protected]'
2+
import util from '../shared/util.ts'
3+
4+
const postcssVersion = '8.2.8'
5+
const productionOnlyPostcssPlugins = ['autoprefixer']
6+
7+
export type PostCSSPlugin = string | [string, any] | Plugin | PluginCreator<any>
8+
9+
export class CSSProcessor {
10+
#isProd: boolean
11+
#postcssPlugins: PostCSSPlugin[]
12+
#postcss: any
13+
#cleanCSS: any
14+
15+
constructor() {
16+
this.#isProd = false
17+
this.#postcssPlugins = []
18+
this.#postcss = null
19+
this.#cleanCSS = null
20+
}
21+
22+
config(isProd: boolean, postcssPlugins: PostCSSPlugin[]) {
23+
this.#isProd = isProd
24+
this.#postcssPlugins = postcssPlugins
25+
}
26+
27+
async transform(url: string, content: string): Promise<{ code: string, map?: string }> {
28+
if (util.isLikelyHttpURL(url)) {
29+
return {
30+
code: [
31+
`import { applyCSS } from "https://deno.land/x/aleph/framework/core/style.ts"`,
32+
`applyCSS(${JSON.stringify(url)})`
33+
].join('\n')
34+
}
35+
}
36+
37+
if (this.#postcss == null) {
38+
const [postcss, cleanCSS] = await Promise.all([
39+
initPostCSS(this.#postcssPlugins),
40+
this.#isProd ? initCleanCSS() : Promise.resolve(null)
41+
])
42+
this.#postcss = postcss
43+
this.#cleanCSS = cleanCSS
44+
}
45+
46+
const { content: pcss } = await this.#postcss.process(content).async()
47+
const css = this.#isProd ? this.#cleanCSS.minify(pcss).styles : pcss
48+
49+
if (url.startsWith('#inline-style-')) {
50+
return {
51+
code: css,
52+
map: undefined
53+
}
54+
}
55+
56+
return {
57+
code: [
58+
`import { applyCSS } from "https://deno.land/x/aleph/framework/core/style.ts"`,
59+
`applyCSS(${JSON.stringify(url)}, ${JSON.stringify(css)})`
60+
].join('\n'),
61+
// todo: generate map
62+
}
63+
}
64+
}
65+
66+
async function initCleanCSS() {
67+
const { default: CleanCSS } = await import('https://esm.sh/[email protected]?no-check')
68+
return new CleanCSS({ compatibility: '*' /* Internet Explorer 10+ */ })
69+
}
70+
71+
async function initPostCSS(plugins: PostCSSPlugin[]) {
72+
const { default: PostCSS } = await import(`https://esm.sh/postcss@${postcssVersion}`)
73+
const isDev = Deno.env.get('BUILD_MODE') === 'development'
74+
return PostCSS(await Promise.all(plugins.filter(p => {
75+
if (isDev) {
76+
if (util.isNEString(p) && productionOnlyPostcssPlugins.includes(p)) {
77+
return false
78+
} else if (Array.isArray(p) && productionOnlyPostcssPlugins.includes(p[0])) {
79+
return false
80+
}
81+
}
82+
return true
83+
}).map(async p => {
84+
if (util.isNEString(p)) {
85+
return await importPostcssPluginByName(p)
86+
} else if (Array.isArray(p)) {
87+
const Plugin = await importPostcssPluginByName(p[0])
88+
return [Plugin, p[1]]
89+
} else {
90+
return p
91+
}
92+
})))
93+
}
94+
95+
async function importPostcssPluginByName(name: string) {
96+
const url = `https://esm.sh/${name}?external=postcss@${postcssVersion}&no-check`
97+
const { default: Plugin } = await import(url)
98+
return Plugin
99+
}

compiler/css_test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { assertEquals } from 'https://deno.land/[email protected]/testing/asserts.ts'
2+
import { CSSProcessor } from './css.ts'
3+
4+
Deno.test('css processor', async () => {
5+
const processor = new CSSProcessor()
6+
const { code } = await processor.transform(
7+
'/test.css',
8+
'h1 { font-size: 18px; }'
9+
)
10+
assertEquals(code, 'import { applyCSS } from "https://deno.land/x/aleph/framework/core/style.ts"\napplyCSS("/test.css", "h1 { font-size: 18px; }")')
11+
})
12+
13+
Deno.test('css loader for inline style', async () => {
14+
const processor = new CSSProcessor()
15+
const { code } = await processor.transform(
16+
'#inline-style-{}',
17+
'h1 { font-size: 18px; }'
18+
)
19+
assertEquals(code, 'h1 { font-size: 18px; }')
20+
})
21+
22+
Deno.test('css loader in production mode', async () => {
23+
const processor = new CSSProcessor()
24+
processor.config(true, [])
25+
const { code } = await processor.transform(
26+
'/test.css',
27+
'h1 { font-size: 18px; }'
28+
)
29+
30+
assertEquals(code, 'import { applyCSS } from "https://deno.land/x/aleph/framework/core/style.ts"\napplyCSS("/test.css", "h1{font-size:18px}")')
31+
})
32+
33+
Deno.test('css loader with postcss plugins', async () => {
34+
const processor = new CSSProcessor()
35+
processor.config(true, ['postcss-nested'])
36+
const { code } = await processor.transform(
37+
'/test.css',
38+
'.foo { .bar { font-size: 100%; } }'
39+
)
40+
assertEquals(code, 'import { applyCSS } from "https://deno.land/x/aleph/framework/core/style.ts"\napplyCSS("/test.css", ".foo .bar { font-size: 100%; }")')
41+
})

compiler/mod.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export enum SourceType {
1212
JSX = 'jsx',
1313
TS = 'ts',
1414
TSX = 'tsx',
15+
CSS = 'css',
1516
Unknown = '??',
1617
}
1718

plugins/css.ts

Lines changed: 0 additions & 134 deletions
This file was deleted.

plugins/css_test.ts

Lines changed: 0 additions & 46 deletions
This file was deleted.

0 commit comments

Comments
 (0)