Turndown 源码分析:三、规则集`rules.js` REV1

简介: Turndown 源码分析:三、规则集`rules.js` REV1
/**
 * Manages a collection of rules used to convert HTML to Markdown
 */
export default function Rules (options) {
  // 配置
  this.options = options
  // 保留规则列表
  this._keep = []
  // 移除规则列表
  this._remove = []
  // 空白规则
  this.blankRule = {
    replacement: options.blankReplacement
  }
  // 保留规则
  this.keepReplacement = options.keepReplacement
  // 默认规则
  this.defaultRule = {
    replacement: options.defaultReplacement
  }
  // 初始化常规规则列表
  this.array = []
  for (var key in options.rules) this.array.push(options.rules[key])
}
Rules.prototype = {
  add: function (key, rule) {
    // 在规则表前端插入指定规则,
    // 遍历的顺序是从前向后,所以新插入的规则会优先匹配。
    this.array.unshift(rule)
  },
  keep: function (filter) {
    // 在保留列表中插入指定的过滤器。
    this._keep.unshift({
      filter: filter,
      replacement: this.keepReplacement
    })
  },
  remove: function (filter) {
    // 在移除列表中插入指定的过滤器。
    this._remove.unshift({
      filter: filter,
      replacement: function () {
        return ''
      }
    })
  },
  forNode: function (node) {
    // 判断节点是否是空白,如果是的话返回空白规则
    if (node.isBlank) return this.blankRule
    var rule
    // 依次在常规、保留、移除规则列表中寻找匹配节点的规则,如果成功就返回
    if ((rule = findRule(this.array, node, this.options))) return rule
    if ((rule = findRule(this._keep, node, this.options))) return rule
    if ((rule = findRule(this._remove, node, this.options))) return rule
    // 都没找到就返回默认规则
    return this.defaultRule
  },
  // 等价于 this.array.forEach
  forEach: function (fn) {
    for (var i = 0; i < this.array.length; i++) fn(this.array[i], i)
  }
}
function findRule (rules, node, options) {
  // 遍历规则集的每个规则
  for (var i = 0; i < rules.length; i++) {
    var rule = rules[i]
    // 将其与节点匹配,成功则返回当前规则
    if (filterValue(rule, node, options)) return rule
  }
  // 否则返回空值
  return void 0
}
function filterValue (rule, node, options) {
  var filter = rule.filter
  if (typeof filter === 'string') {
    // 如果过滤器是字符串,判断是否和节点名称一致
    if (filter === node.nodeName.toLowerCase()) return true
  } else if (Array.isArray(filter)) {
    // 如果过滤器是数组,查看是否包含节点名称
    if (filter.indexOf(node.nodeName.toLowerCase()) > -1) return true
  } else if (typeof filter === 'function') {
    // 如果过滤器是函数,在节点上调用它来得到匹配结果
    if (filter.call(rule, node, options)) return true
  } else {
    // 否则抛出异常
    throw new TypeError('`filter` needs to be a string, array, or function')
  }
}
相关文章
|
6月前
|
JavaScript
Turndown 源码分析:五、节点相关`root-node.js`和`node.js`
Turndown 源码分析:五、节点相关`root-node.js`和`node.js`
69 0
|
6月前
Turndown 源码分析:二、规则`commonmark-ruiles.js` REV1
Turndown 源码分析:二、规则`commonmark-ruiles.js` REV1
44 0
|
6月前
Turndown 源码分析:四、`turndown.js`
Turndown 源码分析:四、`turndown.js`
63 0
|
6月前
|
JavaScript 前端开发
JavaScript标识符(命名规则)
JavaScript标识符(命名规则)
64 0
|
30天前
|
JavaScript 前端开发
JS隐式类型转换规则
【10月更文挑战第9天】 不同的 JavaScript 引擎可能在隐式类型转换的具体实现上存在一些细微差别。理解这些隐式类型转换规则对于正确处理数据和避免错误非常重要。
16 0
|
3月前
|
JavaScript 前端开发
JavaScript的命名规则
JavaScript的命名规则
100 0
|
3月前
|
JavaScript 前端开发
js中的命名规则
js中的命名规则
|
5月前
|
JavaScript 前端开发
JavaScript变量命名规则及关键字详解
JavaScript变量命名规则及关键字详解
|
6月前
|
JavaScript
js的一些运算符规则
js的一些运算符规则
38 1
|
6月前
|
JavaScript 前端开发 数据处理
JavaScript 游戏规则:setTimeout和setInterval的对决
JavaScript 游戏规则:setTimeout和setInterval的对决
46 1