|
1 | | -import postcss, { Root } from 'postcss'; |
2 | | - |
| 1 | +import postcss, { Root, Parser } from 'postcss'; |
3 | 2 | export interface TransformAPI { |
4 | 3 | /** |
5 | 4 | * Parse a raw CSS string into an abstract syntax tree and return a PostCSS `Root` node. |
6 | 5 | */ |
7 | 6 | parse(source: string): Root; |
8 | 7 | } |
9 | 8 |
|
10 | | -const parse: TransformAPI['parse'] = source => { |
11 | | - return postcss.parse(source); |
| 9 | +const createAPIParse = ({ |
| 10 | + parser, |
| 11 | +}: { |
| 12 | + parser?: Parser; |
| 13 | +}): TransformAPI['parse'] => { |
| 14 | + const parse: TransformAPI['parse'] = source => { |
| 15 | + const result = postcss().process(source, { |
| 16 | + // Silence a warning about sourcemaps. Not relevant to this use case. |
| 17 | + from: undefined, |
| 18 | + parser, |
| 19 | + }); |
| 20 | + |
| 21 | + // Explicitly destructure root, which lazy evaluates and populates an error |
| 22 | + // if one occurs. The error field can then be checked. |
| 23 | + const { root } = result; |
| 24 | + |
| 25 | + // Re-surface an PostCSS parsing errors. |
| 26 | + // https://github.com/postcss/postcss/issues/1708 |
| 27 | + if ((result as any).error) { |
| 28 | + throw (result as any).error; |
| 29 | + } |
| 30 | + |
| 31 | + if (root?.type === 'root') { |
| 32 | + return root; |
| 33 | + } else { |
| 34 | + throw new Error(`Unexpected root node: ${root}`); |
| 35 | + } |
| 36 | + }; |
| 37 | + |
| 38 | + return parse; |
12 | 39 | }; |
13 | 40 |
|
14 | | -export const api: TransformAPI = { parse }; |
| 41 | +export const createAPI = ({ |
| 42 | + parser, |
| 43 | +}: { parser?: Parser } = {}): TransformAPI => { |
| 44 | + const api: TransformAPI = { |
| 45 | + parse: createAPIParse({ parser }), |
| 46 | + }; |
| 47 | + |
| 48 | + return api; |
| 49 | +}; |
0 commit comments