: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
function isPromise(obj) {
return typeof obj === 'object' && typeof obj.then === 'function'
function getEvents(node) {
let type = TYPE_TO_CLASS_NAME[node.type]
if (node.type === 'decl') {
key = node.prop.toLowerCase()
} else if (node.type === 'atrule') {
key = node.name.toLowerCase()
if (key && node.append) {
return [type, type + '-' + key, type + 'Exit', type + 'Exit-' + key]
} else if (node.append) {
return [type, CHILDREN, type + 'Exit']
return [type, type + 'Exit']
if (node.type === 'document') {
events = ['Document', CHILDREN, 'DocumentExit']
} else if (node.type === 'root') {
events = ['Root', CHILDREN, 'RootExit']
function cleanMarks(node) {
if (node.nodes) node.nodes.forEach(i => cleanMarks(i))
constructor(processor, css, opts) {
typeof css === 'object' &&
(css.type === 'root' || css.type === 'document')
} else if (css instanceof LazyResult || css instanceof Result) {
root = cleanMarks(css.root)
if (typeof opts.map === 'undefined') opts.map = {}
if (!opts.map.inline) opts.map.inline = false
if (opts.syntax) parser = opts.syntax.parse
if (opts.parser) parser = opts.parser
if (parser.parse) parser = parser.parse
this.result = new Result(processor, root, opts)
this.helpers = { ...postcss, postcss, result: this.result }
this.plugins = this.processor.plugins.map(plugin => {
if (typeof plugin === 'object' && plugin.prepare) {
return { ...plugin, ...plugin.prepare(this.result) }
if (this.error) return Promise.reject(this.error)
if (this.processed) return Promise.resolve(this.result)
this.processing = this.runAsync()
return this.async().catch(onRejected)
return this.async().then(onFinally, onFinally)
throw new Error('Use process(css).then(cb) to work with async plugins')
handleError(error, node) {
let plugin = this.result.lastPlugin
if (node) node.addToError(error)
if (error.name === 'CssSyntaxError' && !error.plugin) {
error.plugin = plugin.postcssPlugin
} else if (plugin.postcssVersion) {
// eslint-disable-next-line no-console
if (console && console.error) console.error(err)
let add = (plugin, type, cb) => {
if (!this.listeners[type]) this.listeners[type] = []
this.listeners[type].push([plugin, cb])
for (let plugin of this.plugins) {
if (typeof plugin === 'object') {
for (let event in plugin) {
if (!PLUGIN_PROPS[event] && /^[A-Z]/.test(event)) {
`Unknown event ${event} in ${plugin.postcssPlugin}. ` +
`Try to update PostCSS (${this.processor.version} now).`
if (!NOT_VISITORS[event]) {
if (typeof plugin[event] === 'object') {
for (let filter in plugin[event]) {
add(plugin, event, plugin[event][filter])
event + '-' + filter.toLowerCase(),
} else if (typeof plugin[event] === 'function') {
add(plugin, event, plugin[event])
this.hasListener = Object.keys(this.listeners).length > 0
for (let i = 0; i < this.plugins.length; i++) {
let plugin = this.plugins[i]
let promise = this.runOnRoot(plugin)
if (isPromise(promise)) {
throw this.handleError(error)
let root = this.result.root
let stack = [toStack(root)]
while (stack.length > 0) {
let promise = this.visitTick(stack)
if (isPromise(promise)) {
let node = stack[stack.length - 1].node
throw this.handleError(e, node)
if (this.listeners.OnceExit) {
for (let [plugin, visitor] of this.listeners.OnceExit) {
this.result.lastPlugin = plugin
if (root.type === 'document') {
let roots = root.nodes.map(subRoot =>
visitor(subRoot, this.helpers)
await visitor(root, this.helpers)
throw this.handleError(e)
this.result.lastPlugin = plugin
if (typeof plugin === 'object' && plugin.Once) {
if (this.result.root.type === 'document') {
let roots = this.result.root.nodes.map(root =>
plugin.Once(root, this.helpers)
if (isPromise(roots[0])) {
return Promise.all(roots)
return plugin.Once(this.result.root, this.helpers)
} else if (typeof plugin === 'function') {
return plugin(this.result.root, this.result)
throw this.handleError(error)
if (this.error) throw this.error
if (this.stringified) return this.result
let opts = this.result.opts
if (opts.syntax) str = opts.syntax.stringify
if (opts.stringifier) str = opts.stringifier
if (str.stringify) str = str.stringify
let map = new MapGenerator(str, this.result.root, this.result.opts)
let data = map.generate()
this.result.css = data[0]
this.result.map = data[1]
if (this.error) throw this.error
if (this.processed) return this.result
throw this.getAsyncError()
for (let plugin of this.plugins) {
let promise = this.runOnRoot(plugin)
if (isPromise(promise)) {
throw this.getAsyncError()
let root = this.result.root
if (this.listeners.OnceExit) {
if (root.type === 'document') {
for (let subRoot of root.nodes) {
this.visitSync(this.listeners.OnceExit, subRoot)
this.visitSync(this.listeners.OnceExit, root)
then(onFulfilled, onRejected) {
return this.async().then(onFulfilled, onRejected)
visitSync(visitors, node) {
for (let [plugin, visitor] of visitors) {
this.result.lastPlugin = plugin
promise = visitor(node, this.helpers)
throw this.handleError(e, node.proxyOf)
if (node.type !== 'root' && node.type !== 'document' && !node.parent) {
if (isPromise(promise)) {
throw this.getAsyncError()
let visit = stack[stack.length - 1]
let { node, visitors } = visit
if (node.type !== 'root' && node.type !== 'document' && !node.parent) {
if (visitors.length > 0 && visit.visitorIndex < visitors.length) {
let [plugin, visitor] = visitors[visit.visitorIndex]
if (visit.visitorIndex === visitors.length) {
this.result.lastPlugin = plugin
return visitor(node.toProxy(), this.helpers)
throw this.handleError(e, node)
if (visit.iterator !== 0) {
let iterator = visit.iterator
while ((child = node.nodes[node.indexes[iterator]])) {
node.indexes[iterator] += 1
stack.push(toStack(child))
delete node.indexes[iterator]
let events = visit.events
while (visit.eventIndex < events.length) {
let event = events[visit.eventIndex]
if (event === CHILDREN) {
if (node.nodes && node.nodes.length) {
visit.iterator = node.getIterator()
} else if (this.listeners[event]) {
visit.visitors = this.listeners[event]
let events = getEvents(node)
for (let event of events) {
if (event === CHILDREN) {
if (!child[isClean]) this.walkSync(child)
let visitors = this.listeners[event]
if (this.visitSync(visitors, node.toProxy())) return
return this.sync().warnings()
return this.stringify().content
return this.stringify().css
return this.stringify().map
return this.sync().messages
return this.result.processor
get [Symbol.toStringTag]() {
LazyResult.registerPostcss = dependant => {
module.exports = LazyResult