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,
|
2019-12-10 03:19:39 +08:00
|
|
|
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
|
2019-12-10 03:19:39 +08:00
|
|
|
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 {
|
2019-11-28 23:49:39 +08:00
|
|
|
return preprocessor.render(options.source, options.map, {
|
|
|
|
filename: options.filename,
|
|
|
|
...options.preprocessOptions
|
|
|
|
})
|
2019-11-07 10:58:15 +08:00
|
|
|
}
|