首页 > 编程语言 >Turndown 源码分析:五、节点相关`root-node.js`和`node.js`

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

时间:2023-06-19 17:57:14浏览次数:52  
标签:node return 空白 js sibling 源码 && options

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
}

标签:node,return,空白,js,sibling,源码,&&,options
From: https://www.cnblogs.com/apachecn/p/17491771.html

相关文章

  • 【uniapp框架错误】[ERROR] reportJSException >>>> exception function:createInstance,
    【uniapp框架错误】[ERROR]reportJSException>>>>exceptionfunction:createInstance,exception h5端运行正常,一用基座连接手机端就会报这个错误reportJSException>>>>exceptionfunction:createInstanceContext,exception:whitescreencausecreateinstanceContextfaile......
  • js substr方法截取截断emoji图标问题
    functionsafeSubstring(str,start,length){varend=start+length;varresult="";varemojiFlag=false;for(vari=start;i<end;i++){varcharCode=str.charCodeAt(i);if(charCode>=0xd800&&charCode<=......
  • node.js安装与卸载
    一、安装:官网安装 Node.js(nodejs.org)Node安装C盘与其他盘区别,安装哪个最好!-主要区别在于权限 区别是C盘属于管理员权限,其他盘属于用户权限Node安装C盘时npminstall包cmd以管理员身份运行,必须需要管理员Node安装其他盘时,不是C盘npminstall包需要普通用户权限就可......
  • 利用react-json-view最JSON数据进行渲染
    1.安装npminstall--savereact-json-view2.使用importReactJsonfrom"react-json-view";constA=()=>{letsrc={"content-length":"675","x-b3-parentspanid":"06c634eea567252a",&quo......
  • StencilJs学习之组件装饰器
    stenciljs可以方便的构建交互式组件支持以下装饰器componentstatepropwatchmethodelementeventlistenComponent装饰器@Component是一个装饰器,它将TypeScript类指定为Stencil组件。每个模板组件在构建时都会转换为Webcomponent。import{Component}from......
  • Mongodb 为什么提起处理JSON 就是MOGNODB 的,因为我没得选
    提到JSON的数据处理,大部分人想到的一定是MONGODB,如果不是可以自己好好的反思一下,自己的数据库餐盘是不是缺少MOGNODB这道硬菜,最近也有人问我一个问题,关于使用mongodb的原因是什么,我回答的比较简单,但是我更原因用这样的方式来回答这个问题。提到MOGNODB的特长,必须提到JSON,在数......
  • Js_最常用的55个经典技巧
     1.οncοntextmenu="window.event.returnValue=false"将彻底屏蔽鼠标右键<tableborderοncοntextmenu=return(false)><td>no</table>可用于Table2.<bodyonselectstart="returnfalse">取消选取、防止复制3.οnpaste="returnfalse"......
  • (六)模板字符串、JS中的数据
    一、模板字符串 二、JS中的数据 ......
  • Turndown 源码分析:二、规则`commonmark-ruiles.js` REV1
    import{repeat}from'./utilities'varrules={}//段落rules.paragraph={filter:'p',replacement:function(content){//前后加两个换行return'\n\n'+content+'\n\n'}}//换行rules.lineBrea......
  • JavaScript的数学计算库:decimal.js
    Anarbitrary-precisionDecimaltypeforJavaScript.功能整数和浮点数简单但功能齐全的API复制JavaScript和对象的许多方法Number.prototypeMath还处理十六进制、二进制和八进制值比Java的BigDecimalJavaScript版本更快,更小,也许更容易使用无依赖关系广泛的平......