vue3-yuanma/packages/compiler-sfc/src/compileStyle.ts

145 lines
3.4 KiB
TypeScript
Raw Normal View History

2019-11-07 10:58:15 +08:00
// const postcss = require('postcss')
import postcss, { ProcessOptions, LazyResult, Result, ResultMap } from 'postcss'
import trimPlugin from './stylePluginTrim'
import scopedPlugin from './stylePluginScoped'
import {
processors,
StylePreprocessor,
StylePreprocessorResults,
PreprocessLang
2019-11-07 10:58:15 +08:00
} from './stylePreprocessors'
2019-12-12 02:33:45 +08:00
import { RawSourceMap } from 'source-map'
2019-11-07 10:58:15 +08:00
2019-12-14 00:24:09 +08:00
export interface SFCStyleCompileOptions {
2019-11-07 10:58:15 +08:00
source: string
filename: string
id: string
2019-12-12 02:33:45 +08:00
map?: RawSourceMap
2019-11-07 10:58:15 +08:00
scoped?: boolean
trim?: boolean
preprocessLang?: PreprocessLang
2019-11-07 10:58:15 +08:00
preprocessOptions?: any
postcssOptions?: any
postcssPlugins?: any[]
}
2019-12-14 00:24:09 +08:00
export interface SFCAsyncStyleCompileOptions extends SFCStyleCompileOptions {
2019-11-07 10:58:15 +08:00
isAsync?: boolean
}
2019-12-14 00:24:09 +08:00
export interface SFCStyleCompileResults {
2019-11-07 10:58:15 +08:00
code: string
2019-12-12 02:33:45 +08:00
map: RawSourceMap | undefined
2019-11-07 10:58:15 +08:00
rawResult: LazyResult | Result | undefined
2019-12-12 02:33:45 +08:00
errors: Error[]
2019-11-07 10:58:15 +08:00
}
export function compileStyle(
2019-12-14 00:24:09 +08:00
options: SFCStyleCompileOptions
): SFCStyleCompileResults {
return doCompileStyle({
...options,
isAsync: false
}) as SFCStyleCompileResults
2019-11-07 10:58:15 +08:00
}
export function compileStyleAsync(
2019-12-14 00:24:09 +08:00
options: SFCStyleCompileOptions
): Promise<SFCStyleCompileResults> {
2019-11-07 10:58:15 +08:00
return doCompileStyle({ ...options, isAsync: true }) as Promise<
2019-12-14 00:24:09 +08:00
SFCStyleCompileResults
2019-11-07 10:58:15 +08:00
>
}
export function doCompileStyle(
2019-12-14 00:24:09 +08:00
options: SFCAsyncStyleCompileOptions
): SFCStyleCompileResults | Promise<SFCStyleCompileResults> {
2019-11-07 10:58:15 +08:00
const {
filename,
id,
scoped = true,
trim = true,
preprocessLang,
postcssOptions,
postcssPlugins
} = options
const preprocessor = preprocessLang && processors[preprocessLang]
const preProcessedSource = preprocessor && preprocess(options, preprocessor)
const map = preProcessedSource ? preProcessedSource.map : options.map
const source = preProcessedSource ? preProcessedSource.code : options.source
const plugins = (postcssPlugins || []).slice()
if (trim) {
plugins.push(trimPlugin())
}
if (scoped) {
plugins.push(scopedPlugin(id))
}
const postCSSOptions: ProcessOptions = {
...postcssOptions,
to: filename,
from: filename
}
if (map) {
postCSSOptions.map = {
inline: false,
annotation: false,
prev: map
}
}
let result: LazyResult | undefined
let code: string | undefined
let outMap: ResultMap | undefined
2019-12-12 02:33:45 +08:00
const errors: Error[] = []
2019-11-07 10:58:15 +08:00
if (preProcessedSource && preProcessedSource.errors.length) {
errors.push(...preProcessedSource.errors)
}
try {
result = postcss(plugins).process(source, postCSSOptions)
// In async mode, return a promise.
if (options.isAsync) {
return result
.then(result => ({
code: result.css || '',
2019-12-12 02:33:45 +08:00
map: result.map && (result.map.toJSON() as any),
2019-11-07 10:58:15 +08:00
errors,
rawResult: result
}))
.catch(error => ({
code: '',
map: undefined,
2019-12-12 02:33:45 +08:00
errors: [...errors, error],
2019-11-07 10:58:15 +08:00
rawResult: undefined
}))
}
// force synchronous transform (we know we only have sync plugins)
code = result.css
outMap = result.map
} catch (e) {
errors.push(e)
}
return {
code: code || ``,
2019-12-12 02:33:45 +08:00
map: outMap && (outMap.toJSON() as any),
2019-11-07 10:58:15 +08:00
errors,
rawResult: result
}
}
function preprocess(
2019-12-14 00:24:09 +08:00
options: SFCStyleCompileOptions,
2019-11-07 10:58:15 +08:00
preprocessor: StylePreprocessor
): StylePreprocessorResults {
return preprocessor.render(options.source, options.map, {
filename: options.filename,
...options.preprocessOptions
})
2019-11-07 10:58:15 +08:00
}