Skip to content

Commit 54464d6

Browse files
znckyyx990803
authored andcommitted
feat: Add async style compilation support (#13)
1 parent a3bb34e commit 54464d6

File tree

4 files changed

+77
-4
lines changed

4 files changed

+77
-4
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ interface StyleCompileOptions {
116116
map?: any
117117
scoped?: boolean
118118
trim?: boolean
119+
preprocessLang?: string
120+
preprocessOptions?: any
121+
postcssOptions?: any
122+
postcssPlugins?: any[]
119123
}
120124

121125
interface StyleCompileResults {
@@ -125,3 +129,7 @@ interface StyleCompileResults {
125129
errors: string[]
126130
}
127131
```
132+
133+
### compileStyleAsync(StyleCompileOptions)
134+
135+
Same as `compileStyle(StyleCompileOptions)` but it returns a Promise resolving to `StyleCompileResults`. It can be used with async postcss plugins.

lib/compileStyle.ts

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ export interface StyleCompileOptions {
1717
postcssPlugins?: any[]
1818
}
1919

20+
export interface AsyncStyleCompileOptions extends StyleCompileOptions {
21+
isAsync?: boolean
22+
}
23+
2024
export interface StyleCompileResults {
2125
code: string
2226
map: any | void
@@ -26,6 +30,18 @@ export interface StyleCompileResults {
2630

2731
export function compileStyle (
2832
options: StyleCompileOptions
33+
): StyleCompileResults {
34+
return doCompileStyle({ ...options, isAsync: false })
35+
}
36+
37+
export function compileStyleAsync (
38+
options: StyleCompileOptions
39+
): Promise<StyleCompileResults> {
40+
return Promise.resolve(doCompileStyle({ ...options, isAsync: true }))
41+
}
42+
43+
export function doCompileStyle (
44+
options: AsyncStyleCompileOptions
2945
): StyleCompileResults {
3046
const {
3147
filename,
@@ -63,12 +79,30 @@ export function compileStyle (
6379
}
6480

6581
let result, code, outMap
66-
const errors = []
82+
const errors: any[] = []
6783
if (preProcessedSource && preProcessedSource.errors.length) {
6884
errors.push(...preProcessedSource.errors)
6985
}
7086
try {
7187
result = postcss(plugins).process(source, postCSSOptions)
88+
89+
// In async mode, return a promise.
90+
if (options.isAsync) {
91+
return result
92+
.then((result: LazyResult): StyleCompileResults => ({
93+
code: result.css || '',
94+
map: result.map && result.map.toJSON(),
95+
errors,
96+
rawResult: result
97+
}))
98+
.catch((error: Error): StyleCompileResults => ({
99+
code: '',
100+
map: undefined,
101+
errors: [...errors, error.message],
102+
rawResult: undefined
103+
}))
104+
}
105+
72106
// force synchronous transform (we know we only have sync plugins)
73107
code = result.css
74108
outMap = result.map

lib/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313

1414
import {
1515
compileStyle,
16+
compileStyleAsync,
1617
StyleCompileOptions,
1718
StyleCompileResults
1819
} from './compileStyle'
@@ -21,7 +22,8 @@ import {
2122
export {
2223
parse,
2324
compileTemplate,
24-
compileStyle
25+
compileStyle,
26+
compileStyleAsync
2527
}
2628

2729
// types

test/compileStyle.spec.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { parse } from '../lib/parse'
2-
import { compileStyle } from '../lib/compileStyle'
2+
import { compileStyle, compileStyleAsync } from '../lib/compileStyle'
33

44
test('preprocess less', () => {
55
const style = parse({
@@ -122,5 +122,34 @@ test('custom postcss options', () => {
122122
postcssOptions: { random: 'foo' }
123123
})
124124

125-
expect((<any>result.rawResult).opts.random).toBe('foo')
125+
expect((result.rawResult).opts.random).toBe('foo')
126+
})
127+
128+
test('async postcss plugin in sync mode', () => {
129+
const result = compileStyle({
130+
id: 'v-scope-xxx',
131+
filename: 'example.vue',
132+
source: '.foo { color: red }',
133+
scoped: false,
134+
postcssPlugins: [require('postcss').plugin('test-plugin', () => async (result) => result)]
135+
})
136+
137+
expect(result.errors).toHaveLength(1)
138+
})
139+
140+
141+
test('async postcss plugin', async () => {
142+
const promise = compileStyleAsync({
143+
id: 'v-scope-xxx',
144+
filename: 'example.vue',
145+
source: '.foo { color: red }',
146+
scoped: false,
147+
postcssPlugins: [require('postcss').plugin('test-plugin', () => async (result) => result)]
148+
})
149+
150+
expect(promise instanceof Promise).toBe(true)
151+
152+
const result = await promise
153+
expect(result.errors).toHaveLength(0)
154+
expect(result.code).toEqual(expect.stringContaining('color: red'))
126155
})

0 commit comments

Comments
 (0)