travel/admin/node_modules/posthtml/lib/api.js

137 lines
3.2 KiB
JavaScript

'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
})
}