| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136 | 'use strict'/** * # API * @author Ivan Voischev (@voischev), *         Anton Winogradov (@awinogradov), *         Alexej Yaroshevich (@zxqfox), *         Vasiliy (@Yeti-or) * @module API * @namespace tree */module.exports = {  /**   * walk the tree and pass all nodes to callback   *   * @memberof tree   * @param  {Function} cb - Callback   * @return {Function}    - Node in callback   *   ***Usage**   * ```js   * export const walk = (tree) => {   *   tree.walk((node) => {   *     let classes = node.attrs && node.attrs.class.split(' ') || []   *   *     if (classes.includes(className)) return cb(node)   *       return node   *   })   * }   * ```   */  walk: function (cb) {    return traverse(this, cb)  },  /**   * match expression to search nodes in the tree   *   * @memberof tree   * @param  {String|RegExp|Object|Array} expression - Matcher(s) to search   * @param  {Function} cb - Callback   * @return {Function}    - Node in callback   *   ***Usage**   * ```js   * export const match = (tree) => {   *   // Single matcher   *   tree.match({ tag: 'custom-tag' }, (node) => {   *     let tag = node.tag   *   *     Object.assign(node, { tag: 'div', attrs: {class: tag} })   *   *     return node   *   })   *   // Multiple matchers   *   tree.match([{ tag: 'b' }, { tag: 'strong' }], (node) => {   *     let style = 'font-weight: bold;'   *   *     node.tag = 'span'   *   *     node.attrs   *       ? ( node.attrs.style   *         ? ( node.attrs.style += style )   *         : node.attrs.style = style   *       )   *       : node.attrs = { style: style }   *   *     return node   *   })   * }   * ```   */  match: function (expression, cb) {    return Array.isArray(expression)      ? traverse(this, function (node) {        for (var i = 0; i < expression.length; i++) {          if (compare(expression[i], node)) return cb(node)        }        return node      })      : traverse(this, function (node) {        if (compare(expression, node)) return cb(node)        return node      })  }}/** @private */function traverse (tree, cb) {  if (Array.isArray(tree)) {    for (var i = 0; i < tree.length; i++) {      tree[i] = traverse(cb(tree[i]), cb)    }  } else if (      tree &&      typeof tree === 'object' &&      tree.hasOwnProperty('content')  ) traverse(tree.content, cb)  return tree}/** @private */function compare (expected, actual) {  if (expected instanceof RegExp) {    if (typeof actual === 'object') return false    if (typeof actual === 'string') return expected.test(actual)  }  if (typeof expected !== typeof actual) return false  if (typeof expected !== 'object' || expected === null) {    return expected === actual  }  if (Array.isArray(expected)) {    return expected.every(function (exp) {      return [].some.call(actual, function (act) {        return compare(exp, act)      })    })  }  return Object.keys(expected).every(function (key) {    var ao = actual[key]    var eo = expected[key]    if (typeof eo === 'object' && eo !== null && ao !== null) {      return compare(eo, ao)    }    if (typeof eo === 'boolean') {      return eo !== (ao == null)    }    return ao === eo  })}
 |