|
|
- const postcss = require('postcss')
- import { ProcessOptions, LazyResult } from 'postcss'
- import trimPlugin from './stylePlugins/trim'
- import scopedPlugin from './stylePlugins/scoped'
- import {
- processors,
- StylePreprocessor,
- StylePreprocessorResults
- } from './styleProcessors'
-
- export interface StyleCompileOptions {
- source: string
- filename: string
- id: string
- map?: any
- scoped?: boolean
- trim?: boolean
- preprocessLang?: string
- preprocessOptions?: any
- postcssOptions?: any
- postcssPlugins?: any[]
- }
-
- export interface AsyncStyleCompileOptions extends StyleCompileOptions {
- isAsync?: boolean
- }
-
- export interface StyleCompileResults {
- code: string
- map: any | void
- rawResult: LazyResult | void
- errors: string[]
- }
-
- export function compileStyle(
- options: StyleCompileOptions
- ): StyleCompileResults {
- return doCompileStyle({ ...options, isAsync: false })
- }
-
- export function compileStyleAsync(
- options: StyleCompileOptions
- ): Promise<StyleCompileResults> {
- return Promise.resolve(doCompileStyle({ ...options, isAsync: true }))
- }
-
- export function doCompileStyle(
- options: AsyncStyleCompileOptions
- ): StyleCompileResults {
- 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, code, outMap
- const errors: any[] = []
- 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: LazyResult): StyleCompileResults => ({
- code: result.css || '',
- map: result.map && result.map.toJSON(),
- errors,
- rawResult: result
- })
- )
- .catch(
- (error: Error): StyleCompileResults => ({
- code: '',
- map: undefined,
- errors: [...errors, error.message],
- 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 || ``,
- map: outMap && outMap.toJSON(),
- errors,
- rawResult: result
- }
- }
-
- function preprocess(
- options: StyleCompileOptions,
- preprocessor: StylePreprocessor
- ): StylePreprocessorResults {
- return preprocessor.render(
- options.source,
- options.map,
- Object.assign(
- {
- filename: options.filename
- },
- options.preprocessOptions
- )
- )
- }
|