import { Transform } from 'stream' ; import applySourceMap from 'vinyl-sourcemaps-apply' ; import { LooseObject , BalmError } from '@balm-core/index' ; const PLUGIN_NAME = 'postcss' ; function gulpPostcss ( cb ) { return function ( plugins , options ) { if ( Array . isArray ( plugins ) ) { return cb ( ( ) => Promise . resolve ( { plugins : plugins , options : options } ) ) ; } else if ( typeof plugins === 'function' ) { return cb ( ( file ) => Promise . resolve ( plugins ( file ) ) ) ; } else { const postcssLoadConfig = require ( 'postcss-load-config' ) ; const contextOptions = plugins || { } ; return cb ( ( file ) => { let configPath ; if ( contextOptions . config ) { if ( path . isAbsolute ( contextOptions . config ) ) { configPath = contextOptions . config ; } else { configPath = path . join ( file . base , contextOptions . config ) ; } } else { configPath = file . dirname ; } return postcssLoadConfig ( { file : file , options : contextOptions } , configPath ) ; } ) ; } } ; } export default gulpPostcss ( ( loadConfig ) => { const stream = new Transform ( { objectMode : true } ) ; stream . _transform = function ( file , encoding , cb ) { if ( file . isNull ( ) ) { return cb ( null , file ) ; } if ( file . isStream ( ) ) { return handleError ( 'Streams are not supported!' ) ; } const isProtected = file . sourceMap ? { from : true , map : true } : { } ; const options = { from : file . path , to : file . path , map : file . sourceMap ? { annotation : false } : false } ; loadConfig ( file ) . then ( function ( config ) { const configOpts = config . options || { } ; for ( const opt in configOpts ) { if ( Object . prototype . hasOwnProperty . call ( configOpts , opt ) && ! isProtected [ opt ] ) { options [ opt ] = configOpts [ opt ] ; } else { BalmJS . logger . info ( PLUGIN_NAME , `${ file . relative }\nCannot override ${ opt } option, because it is required by gulp-sourcemaps` ) ; } } return require ( 'postcss' ) ( config . plugins || [ ] ) . process ( file . contents , options ) ; } ) . then ( handleResult , handleError ) ; function handleResult ( result ) { let map ; const warnings = result . warnings ( ) . join ( '\n' ) ; file . contents = Buffer . from ( result . css ) ; if ( file . sourceMap ) { map = result . map . toJSON ( ) ; map . file = file . relative ; map . sources = [ ] . map . call ( map . sources , function ( source ) { return path . join ( path . dirname ( file . relative ) , source ) ; } ) ; applySourceMap ( file , map ) ; } if ( warnings ) { BalmJS . logger . info ( PLUGIN_NAME , `${ file . relative }\nwarnings` ) ; } setImmediate ( function ( ) { cb ( null , file ) ; } ) ; } function handleError ( error ) { const errorOptions = { fileName : file . path , showStack : true } ; if ( error . name === 'CssSyntaxError' ) { errorOptions . error = error ; errorOptions . fileName = error . file || file . path ; errorOptions . lineNumber = error . line ; errorOptions . showProperties = false ; errorOptions . showStack = false ; error = `${ error . message }\n\n${ error . showSourceCode ( ) }\n` ; } setImmediate ( function ( ) { cb ( new PluginError ( 'gulp-postcss' , error as BalmError , errorOptions ) ) ; } ) ; } } ; return stream ; } ) ;