校对:soup
使用类似浏览器的 API 管理 HTML 字符串
为什么?
问题
为什么有必要? 为什么不用一个像Chieio那样的经过考验的真正工具呢? 有一整组工具来做这个.
那类工具在分析 它们将 HTML 解析为抽象语法树(AST),然后可以操纵 AST. 然后,当你准备好输出 HTML 时,你将 AST 序列化为字符串 .
如果HTML是完全有效的,而且没有怪异之处,那就太好了.
但我们正在建造两个使用案例:
- 电子邮件代码
- 用户源文件
电子邮件代码
电子邮件密码会有很多怪事 它将包含个性化语言,如液态和手杖. 我们需要能够解析HTML,但我们不能将其序列化为AST,因为它可能打破个性化语言.
例如,通过cheaio运行此 HTML :
<a href={{ url }}>Click me</a>
其结果是:
<a href="{{" url }}>Click me</a>
你可以看到这打破了液态语法.
用户源文件
用户源文件可能也有类似的怪异. 但更重要的是,我们希望在不更改文件的情况下编辑文件 整体 文档。 只是我们试图编辑的一部分.
一个例子是,如果我们试图增加一个类 div数字 :
<main class='main'>
<div class="button">Click me</div>
</main>
如果我们用"欢乐" 它会重新串行 全部 双引号的 HTML 中:
<main class="main">
<div class="button added-class">Click me</div>
</main>
这在程序上是精细的,但不是用户所期望的. 我们只是可能改变数百行代码, 但用户只改变一个单一属性.
如果用户没有百分之百的正确(即缺失标签),我们只是"固定"了——一个完全出乎意料的编辑!
解决办法
我们需要一个能够解析HTML的工具,但不能序列化. 我们需要一个可以编辑HTML而不修改整个文件的工具.
这里 html-mod 进来吧 这是一个可以解析HTML的工具,这样我们可以得到AST式的操纵. 但是,我们不是操纵AST,而是直接操纵HTML并操纵弦. 这样我们才能改变 HTML 想要改变的部分.
安装
npm install @ciolabs/html-mod
使用量
import { HtmlMod } from '@ciolabs/html-mod';
const h = new HtmlMod('<div>hello</div>');
h.querySelector('div')!.innerHTML = 'world';
console.log(h.toString());
//=> <div>world</div>
AST 同步
AST与字符串修改自动同步. 您可以自由修改和查询,无需任何手工步骤:
import { HtmlMod } from '@ciolabs/html-mod';
const h = new HtmlMod('<div>hello</div>');
h.querySelector('div')!.append('<div>world</div>');
// Queries always reflect the latest modifications
console.log(h.querySelectorAll('div').length); //=> 2
元素引用在修改中依然有效——无需在修改后再进行平整:
const h = new HtmlMod('<div><p>Hello</p></div>');
const div = h.querySelector('div')!;
div.setAttribute('class', 'active');
// Element reference is still valid
div.setAttribute('data-id', '123'); // ✅ Works perfectly
// Queries reflect all modifications
const p = h.querySelector('p'); // ✅ Finds the element
从旧版本迁移
如果你从需要手动的版本升级 flush() 电话,你可以安全取出。 这个 @ciolabs/html-mod/experimental 导入路径仍在工作,但已贬值——从 @ciolabs/html-mod 直接换成.
HtmlMod (英语)
这个 HtmlMod 类是本套件的主要类。 这是你用来查询的类 HtmlModElement 元素和操纵 HTML 字符串.
构造器( html: 字符串, 选项 ?)
选项
HtmlModOptions备选
完整的备选方案 htmlparser2 软件。这是用于解析 HTML 的基础解析器.
选项。 Html 模块
Class备选
用于 HtmlModElement 课。 这是用来操纵 HTML 的类. 默认情况下,它使用 HtmlModElement 此软件包中的类.
方法
三进制( ) @ info: whatsthis
从 HTML 字符串的开头和结尾去除所有空白.
三进制( ) @ info
从 HTML 字符串开头删除所有空白.
三进制( )% 1
从 HTML 字符串的结尾去除所有空白.
三联线( ) @ info
删除起始和结尾的空行.
是Empty () QQ布尔
回返 true 如果生成的 HTML 为空.
至 String () QQ 字符串
返回被操纵的 HTML 字符串 .
克隆( ) QQ HtmlMod (英语)
返回一个新的 HtmlMod 实例,使用相同的 HTML 字符串.
查询选择器( 选择器: 字符串) QQ Html ModElement 无效
返回第一个 HtmlModElement 和选择者匹配.
查询 选择器 全部( 选择器: 字符串) QQ HtmlModElement []
返回数组 HtmlModElement 和选择者匹配.
批(召回:()
用批量写入来运行回调, 然后一次全部应用 。 绕来绕去,使许多小写——每个无争吵的突变都支付一个完整的字符串相接器,加上一个AST位置在后各节点上更新,所以书写-重回的循环以文档大小为四倍. Batching将队列编辑应用在一个字符串重建中和一个位置通过中,随着文档的增长而保持平整(232KB文档上的一个3,600-write回路从~500ms下降到~7ms).
中断操作 : setAttribute, (中文(简体) ), removeAttribute (和所有建立在他们身上的东西) dataset, (中文(简体) ), id编号 :className 装置, toggleAttribute),加上结构插入 before, (中文(简体) ), after, (中文(简体) ), prepend,以及 append。所有其它文件立即应用,先冲出任何已排队的编辑.
const htmlMod = new HtmlMod(html);
htmlMod.batch(() => {
for (const element of htmlMod.querySelectorAll('*')) {
element.dataset.key = generateKey();
}
});
htmlMod.toString(); // all edits applied
其结果总是与未争吵的相同。 可以先观察待处理状态冲出批次的读取 : toString(), (中文(简体) ), innerHTML编号 :outerHTML,选择查询,属性读取在有队列编辑的元素上, children 正在等待插入时读取,并读取任何非争吵突变。 冲突写作( 同一属性两次, 重复一次 ) before编号 :after 在一个要素上, prepend编号 :append 混合)也先被冲出,所以分批可以安全地包围任何循环——最糟糕的情况是降解为无争斗的行为.
一个提醒:原始的AST位置字段 startIndex编号 :endIndex 在通过 children)改为 内部 显示批次前坐标。 它们相互一致,并在批量结束后成为最终的. 组合 AST 与源字符串相抵消的位置获取器(例如:. sourceRange)先冲出批次并总是返回最终坐标.
蝙蝠巢;当最外层的批出(或第一次冲出读出)时,会适用编辑. 回调值通过.
Html 模块
这个 HtmlModElement 类是用于操纵 HTML 的类。 运行查询时返回的类别.
属性
标签Name: 字符串
元素的标记名称 。 这可以设定.
编号:字符串
元素的 id. 这可以设定.
类列表: 字符串 []
元素上的一组类.
类Name: 字符串
元素的类属性值 .
数据集: DOMSTringMap
包含全部数据*属性的对象。 可以像普通对象一样读取和修改:
const el = h.querySelector('div')!;
el.dataset.userId = '123'; // Sets data-user-id="123"
console.log(el.dataset.userId); // "123"
属性: 属性 []
数组 Attribute 对象.
内置HTML: 字符串
元素的内部 HTML. 这可以设定.
外部 HTML: 字符串
元素的外侧 HTML .
文本串:字符串
元素的文本内容 。 这可以设定.
儿童:源儿童节点
元素的子孙群.
父 : HtmlModElement 无效
母元素.
源程: 对象
来源中元素的位置信息 :
{
startLineNumber: number;
startColumn: number;
endLineNumber: number;
endColumn: number;
}
方法
之前( html: 字符串) qq 此
在元素前插入 HTML.
之后( html: 字符串) @ info
在元素后插入 HTML.
预拨( html: 字符串) @ info
将 HTML 优先用于元素.
附录( html: 字符串) @ info
将 HTML 附加到元素中.
删除( ) 此处
删除元素.
替换为( html: 字符串) QQ 此
用 HTML 替换元素.
有属性( 名称: 字符串) QQ布尔
回返 true 如果元素有属性.
属性( ) *% 1 布尔
回返 true 如果元素具有任何属性.
获得属性( 名称: 字符串) % 1
返回属性的值.
获取属性名称 () @% 1 字符串 []
返回属性名称的数组.
设置属性( 名称: 字符串, 值: 字符串) @% 1
设置属性.
切换属性( 名称: 字符串, 强制? : 布尔) QX
切换属性 .
部队: 如果 true,属性将被添加。 若为 false,属性将被删除。 如果没有指定, 属性将被切换 .
删除属性( 名称: 字符串) % 1
删除属性.
查询选择器( 选择器: 字符串) QQ Html ModElement 无效
返回第一个 HtmlModElement 和选择者匹配.
查询 选择器 全部( 选择器: 字符串) QQ HtmlModElement []
返回数组 HtmlModElement 和选择者匹配.
至 String () QQ 字符串
返回 HTML 字符串。 与 outerHTML。 。 。 .
克隆( ) QQ Html 模块
返回一个新的 HtmlModElement 实例,使用相同的 HTML 字符串.
如果您想要操纵 HTML 而不影响原版, 则有用 HtmlMod 举个例子.
Html 摩德文本
这个 HtmlModText 类代表 HTML 中的文本节点。 它作为元素的一部分还原 children 阵列.
属性
文本串:字符串
节点解码文本内容. 可以设置( HTML 实体会被逃脱) .
内置HTML: 字符串
文本节点的原始 HTML 内容 。 这可以设定.
方法
至 String () QQ 字符串
返回原始文本节点内容.
类型
HtmlMod 选项
type HtmlModOptions = Options & {
HtmlModElement?: typeof HtmlModElement;
};
何处 Options 继承全部 htmlparser2 解析器选项 财务报告和审定财务报表 多姆汉德勒选项。 。 。 .