Turndown 源码分析:五、节点相关`root-node.js`和`node.js`

简介: Turndown 源码分析:五、节点相关`root-node.js`和`node.js`
import collapseWhitespace from './collapse-whitespace'
import HTMLParser from './html-parser'
import { isBlock, isVoid } from './utilities'
// 单独构造的根节点,防止输入字符串含有多个根元素
export default function RootNode (input, options) {
  var root
  if (typeof input === 'string') {
    // 如果输入是字符串
    var doc = htmlParser().parseFromString(
      // 用自定义元素包围输入字符串可以防止解析器添加 HTML、HEAD 和 BODY 标签
    // 也可以防止输入字符串存在多个根节点
      '<x-turndown id="turndown-root">' + input + '</x-turndown>',
      'text/html'
    )
  // 获取自定义标签作为根节点
    root = doc.getElementById('turndown-root')
  } else {
    // 将节点克隆一份
    root = input.cloneNode(true)
  }
  // 折叠空白字符
  collapseWhitespace({
    element: root,
    isBlock: isBlock,
    isVoid: isVoid,
    isPre: options.preformattedCode ? isPreOrCode : null
  })
  return root
}
// 缓存 HTML 解析器,防止重复创建
var _htmlParser
function htmlParser () {
  _htmlParser = _htmlParser || new HTMLParser()
  return _htmlParser
}
// 判断节点是不是代码块或者内联代码
function isPreOrCode (node) {
  return node.nodeName === 'PRE' || node.nodeName === 'CODE'
}
import { isBlock, isVoid, hasVoid, isMeaningfulWhenBlank, hasMeaningfulWhenBlank } from './utilities'
// 给节点添加一些额外属性之后返回
export default function Node (node, options) {
  // 是否是块级元素
  node.isBlock = isBlock(node)
  // 是否是代码元素或其子元素
  node.isCode = node.nodeName === 'CODE' || node.parentNode.isCode
  // 是否是空白元素
  node.isBlank = isBlank(node)
  // 两侧的空白
  node.flankingWhitespace = flankingWhitespace(node, options)
  return node
}
function isBlank (node) {
  // 空白元素:不是空元素,且不是有意义的空白元素,
  // 也不包含上述元素,并且内容为空或者全是空白字符
  return (
    !isVoid(node) &&
    !isMeaningfulWhenBlank(node) &&
    /^\s*$/i.test(node.textContent) &&
    !hasVoid(node) &&
    !hasMeaningfulWhenBlank(node)
  )
}
function flankingWhitespace (node, options) {
  // 如果是块级元素,不需要填充空白,都返回空串
  if (node.isBlock || (options.preformattedCode && node.isCode)) {
    return { leading: '', trailing: '' }
  }
  var edges = edgeWhitespace(node.textContent)
  // 如果左侧有空白,那么去掉当前节点的前导 ASCII 空白
  if (edges.leadingAscii && isFlankedByWhitespace('left', node, options)) {
    edges.leading = edges.leadingNonAscii
  }
  // 如果右侧有空白,那么去掉当前节点的尾随 ASCII 空白
  if (edges.trailingAscii && isFlankedByWhitespace('right', node, options)) {
    edges.trailing = edges.trailingNonAscii
  }
  return { leading: edges.leading, trailing: edges.trailing }
}
function edgeWhitespace (string) {
  // 通过单个正则获取前导和尾随空白,又进一步分为ASCII 和 非 ASCII 空白
  var m = string.match(/^(([ \t\r\n]*)(\s*))(?:(?=\S)[\s\S]*\S)?((\s*?)([ \t\r\n]*))$/)
  return {
    leading: m[1], // whole string for whitespace-only strings
    leadingAscii: m[2],
    leadingNonAscii: m[3],
    trailing: m[4], // empty for whitespace-only strings
    trailingNonAscii: m[5],
    trailingAscii: m[6]
  }
}
// 判断上一个或者下一个元素和当前元素之间是否有空白
function isFlankedByWhitespace (side, node, options) {
  var sibling
  var regExp
  var isFlanked
  // 根据方向选择相邻元素和正则
  if (side === 'left') {
    sibling = node.previousSibling
    regExp = / $/
  } else {
    sibling = node.nextSibling
    regExp = /^ /
  }
  if (sibling) {
    if (sibling.nodeType === 3) {
      // 如果相邻节点是文本,检查他的内容
      isFlanked = regExp.test(sibling.nodeValue)
    } else if (options.preformattedCode && sibling.nodeName === 'CODE') {
      // 如果它是代码,需要保持原样,返回否
      isFlanked = false
    } else if (sibling.nodeType === 1 && !isBlock(sibling)) {
      // 除此之外,检查元素的内容
      isFlanked = regExp.test(sibling.textContent)
    }
  }
  return isFlanked
}
相关文章
|
23天前
|
机器学习/深度学习 Kubernetes 监控
Kubernetes 节点故障自愈方案:结合 Node Problem Detector 与自动化脚本
本文深入探讨了Kubernetes节点故障自愈方案,结合Node Problem Detector(NPD)与自动化脚本,提供技术细节、完整代码示例及实战验证。文章分析了硬件、系统和内核层面的典型故障场景,指出现有监控体系的局限性,并提出基于NPD的实时事件捕获与自动化诊断树的改进方案。通过深度集成NPD、设计自动化修复引擎以及展示内核死锁恢复的实战案例,文章详细说明了自愈流程的实现步骤与性能优势。此外,还提供了生产环境部署指南、高可用架构设计及安全防护措施,并展望了机器学习增强故障预测和混沌工程验证的进阶优化方向。全文约1.2万字,适合希望提升Kubernetes集群稳定性的技术人员阅读。
|
3月前
|
存储 JavaScript 前端开发
在NodeJS中使用npm包进行JS代码的混淆加密
总的来说,使用“javascript-obfuscator”包可以帮助我们在Node.js中轻松地混淆JavaScript代码。通过合理的配置,我们可以使混淆后的代码更难以理解,从而提高代码的保密性。
237 9
|
8月前
|
Web App开发 JavaScript 前端开发
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念
Node.js 是一种基于 Chrome V8 引擎的后端开发技术,以其高效、灵活著称。本文将介绍 Node.js 的基础概念,包括事件驱动、单线程模型和模块系统;探讨其安装配置、核心模块使用、实战应用如搭建 Web 服务器、文件操作及实时通信;分析项目结构与开发流程,讨论其优势与挑战,并通过案例展示 Node.js 在实际项目中的应用,旨在帮助开发者更好地掌握这一强大工具。
213 1
|
4月前
|
Kubernetes API 网络安全
当node节点kubectl 命令无法连接到 Kubernetes API 服务器
当Node节点上的 `kubectl`无法连接到Kubernetes API服务器时,可以通过以上步骤逐步排查和解决问题。首先确保网络连接正常,验证 `kubeconfig`文件配置正确,检查API服务器和Node节点的状态,最后排除防火墙或网络策略的干扰,并通过重启服务恢复正常连接。通过这些措施,可以有效解决与Kubernetes API服务器通信的常见问题,从而保障集群的正常运行。
287 17
|
7月前
|
存储 JavaScript NoSQL
Node.js新作《循序渐进Node.js企业级开发实践》简介
《循序渐进Node.js企业级开发实践》由清华大学出版社出版,基于Node.js 22.3.0编写,包含26个实战案例和43个上机练习,旨在帮助读者从基础到进阶全面掌握Node.js技术,适用于初学者、进阶开发者及全栈工程师。
127 9
|
8月前
|
JSON JavaScript 前端开发
使用JavaScript和Node.js构建简单的RESTful API
使用JavaScript和Node.js构建简单的RESTful API
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
209 2
|
8月前
|
JavaScript 前端开发
JavaScript中的原型 保姆级文章一文搞懂
本文详细解析了JavaScript中的原型概念,从构造函数、原型对象、`__proto__`属性、`constructor`属性到原型链,层层递进地解释了JavaScript如何通过原型实现继承机制。适合初学者深入理解JS面向对象编程的核心原理。
110 1
JavaScript中的原型 保姆级文章一文搞懂
|
8月前
JS+CSS3文章内容背景黑白切换源码
JS+CSS3文章内容背景黑白切换源码是一款基于JS+CSS3制作的简单网页文章文字内容背景颜色黑白切换效果。
79 0

热门文章

最新文章