JS脚本 - 批量给所有指定标签追加Class属性

JS脚本 - 批量给所有指定标签追加Class属性

  • 前言
  • 一. 脚本
  • 二. 测试运行

前言

公司里我们有个应用引入了UBT埋点,记录了页面上所有的点击操作以及对应的点击按钮。但是我们看下来发现,我们需要给每个按钮加一个唯一标识做区分,并且这个ID是给UBT埋点专用的。那怎么办呢?

  • Id: 不合理,因为如果某个标签已经自带Id了,我们不太可能去覆盖它。
  • Class:合理,class属性可以加多个,也可以过滤。

一. 脚本

const fs = require('fs');
const path = require('path');
// 读取文件内容
const stack = [];
const classRegExp = /class="([^"]*)"/;
const idRegExp = /id="([^"]*)"/;
const args = process.argv.slice(2)
if (!args || args.length < 4) {console.log('参数不合法')
}const TagMapping = [{Tag: 'a',ATagPre: '<a',ATagSuffix: '</a>'
}, {Tag: 'el-button',ATagPre: '<el-button',ATagSuffix: '</el-button>'
}, {Tag: 'el-dialog',ATagPre: '<el-dialog',ATagSuffix: '</el-dialog>'
}, {Tag: 'button',ATagPre: '<button',ATagSuffix: '</button>'
}]
const currentTagRegExp = new RegExp(`(<${'a'}\\s)([^>]*)(>)`, 'i');function contentAddUbtClass(filePath, tag, classPre) {const tagInfo = TagMapping.filter(item => item.Tag === tag)[0];if (!tagInfo) {return;}const content = fs.readFileSync(filePath, 'utf8');let resultContent = ''const preLen = tagInfo.ATagPre.length;const stuffixLen = tagInfo.ATagSuffix.length;for (let i = 0; i < content.length; i++) {// a标签开始if (i + preLen < content.length && content.substring(i, i + preLen) === tagInfo.ATagPre) {stack.push(i);} else if (i + stuffixLen < content.length && content.substring(i, i + stuffixLen) === tagInfo.ATagSuffix) {if (stack.length > 0) {// 出栈,找到起始索引位置const start = stack.pop();// 栈为空的时候,才开始截取并替换,这决定了代码取的标签内容都是最外层的结构if (stack.length === 0) {// a 标签const aTagHtml = content.substring(start, i + stuffixLen);const newHtml = addClass(aTagHtml, i, tag, classPre);resultContent += newHtml;i = i + stuffixLen - 1;}}} else {// 栈为空的时候,说明这个时候还没有识别到对应标签,可以添加其他内容。若识别到了对应标签,那么对应标签包裹的内容在这里不会添加if (stack.length === 0) {resultContent += content.charAt(i);}}}fs.writeFileSync(filePath, resultContent, 'utf8');
}function addClass(content, index, tag, classPre) {// 匹配结果const classMatch = content.match(classRegExp);const idMatch = content.match(idRegExp);// class属性值let className;if (content.includes(classPre)) {return content;}if (idMatch) {// 如果匹配到了id属性,则在原有的class属性值上添加新的样式名称className = `${classPre}${tag}_` + idMatch[1];// 如果没有匹配到class属性,则在原有的文本中添加新的class属性if (classMatch) {// 追加classclassName = classMatch[1] + ` ${className}`;}} else if (classMatch) {// 如果没有匹配到id属性,但匹配到了class属性,则在原有的class属性值上添加新的样式名称className = classMatch[1] + ` ${classPre}${tag}_${index}`;} else {// 如果没有匹配到id属性和class属性,则生成一个新的class属性值className = `${classPre}${tag}_${index}`;// 在原有的文本中添加新的class属性// content = content.replace(currentClassRegExp, `<$1 class="${className}"`);}// 替换原有的class属性值return content.replace(currentTagRegExp, (match, p1, p2, p3) => {// 判断标签原本是否包含了class属性if (p2.includes('class=')) {return `${p1}${p2.replace(classRegExp, `class="${className}"`)}${p3}`;} else {return `${p1}${p2} class="${className}"${p3}`;}});
}// 遍历指定目录下的所有文件
function traverseDirectory(dirPath, extension, tag, classPre) {// 读取目录下的所有文件和子目录const files = fs.readdirSync(dirPath);// 遍历每个文件和子目录files.forEach((file) => {// 获取文件的完整路径const filePath = path.join(dirPath, file);// 判断文件是否是目录if (fs.statSync(filePath).isDirectory()) {// 如果是目录,则递归traverseDirectory(filePath, extension, tag, classPre);} else {// 如果是文件,则判断文件后缀名是否匹配指定的后缀名if (extension.includes(path.extname(filePath))) {// 如果匹配,则输出文件路径contentAddUbtClass(filePath, tag, classPre)}}});
}
traverseDirectory(args[0], args[1], args[2], args[3])

二. 测试运行

假设,我要给页面所有的a标签,添加一个class属性,固定的前缀是UBT_,准备一个html文件:
在这里插入图片描述
执行脚本:

node .\test.js './' '.html' 'a' 'UBT_' 
  1. node 脚本名称 [路径] [匹配的文件后缀(支持多个)] [匹配的标签名称] [增加的class前缀名]

结果如下:
在这里插入图片描述

大家也可以在这个脚本的基础上自行二创。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/688.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶遥控泊车RPA系统功能规范

目 录 1. 版本履历... 4 2. 文档使用范围... 4 3. 术语缩写... 4 4. 系统概述... 5 4.1 系统功能说明... 5 4.2 泊车状态说明... 6 5. 产品基本参数... 6 5.1控制器基本参数... 6 5.2全景摄像头基本参数... 7 5.3 超声波传感器基本参数... 7 …

Flask 使用Flask的session来保存用户登录状态例子

使用Python的Flask库实现的登录接口、查询金额接口和注销接口的示例。 当用户发送POST请求到/login接口时&#xff0c;代码会获取请求中的用户名和密码。如果用户名和密码匹配&#xff08;在示例中是admin和admin123&#xff09;&#xff0c;则会将用户名保存在session中&…

docker命令

查看运行的容器&#xff1a;Docker ps 查看镜像&#xff1a;Docker images 停止容器运行&#xff1a;Docker stop 容器id 删除容器&#xff1a;docker rm 容器id 删除镜像&#xff1a;docker rmi 镜像id 镜像保存下来&#xff1a;docker save -o filename.tar 镜像仓库名称…

php判断是ios手机还是安卓手机

可以使用PHP中的$_SERVER[HTTP_USER_AGENT]全局变量来判断用户的设备类型。根据不同的设备类型&#xff0c;可以判断是iOS手机还是安卓手机。 下面是一个示例代码&#xff1a; <?phpfunction getUserAgent(){$user_agent $_SERVER[HTTP_USER_AGENT]; // 判断是否为iOS设备…

吴恩达机器学习2022-Jupyter特征缩放

1可选实验室: 特征缩放和学习率(多变量) 1.1 目标 在这个实验室里: 利用前一实验室开发的多变量线性回归模型程序在具有多种功能的数据集上运行梯度下降法探讨学习速度 alpha 对梯度下降法的影响通过使用 z 分数标准化的特征缩放来提高梯度下降法的性能 1.2 工具 您将使用…

Python爬虫学习笔记(三)————urllib

目录 1.使用urllib来获取百度首页的源码 2.下载网页图片视频 3.总结-1 4.请求对象的定制&#xff08;解决第一种反爬&#xff09; 5.编解码 &#xff08;1&#xff09;get请求方式&#xff1a;urllib.parse.quote&#xff08;&#xff09; &#xff08;2&#xff09;get请求…

RPC分布式网络通信框架(三)—— 服务配置中心Zookeeper模块

文章目录 一、使用Zookeeper的意义二、Zookeeper基础1 文件系统2 通知机制3 原生zkclient API存在的问题4 服务配置中心Zookeeper模块 三、Zk类实现Start方法创建节点、get节点值方法 四、框架应用rpc提供端框架rpc调用端&#xff08;客户端&#xff09;框架 总结 一、使用Zook…

flutter开发实战-生日等日期选择器DatePicker

flutter开发实战-生日等日期选择器DatePicker 在开发遇到设置生日等信息需要选择日期&#xff0c;这里用到的是CupertinoDatePicker iOS效果的日期、时间选择器 一、效果图 运行后效果图如下 二、代码实现 我们需要调用底部弹窗显示 //显示底部弹窗static void bottomShe…

kubernetes安全机制

//机制说明 Kubernetes 作为一个分布式集群的管理工具&#xff0c;保证集群的安全性是其一个重要的任务。API Server 是集群内部各个组件通信的中介&#xff0c; 也是外部控制的入口。所以 Kubernetes 的安全机制基本就是围绕保护 API Server 来设计的。 比如 kubectl 如果想向…

Python实现PSO粒子群优化算法优化BP神经网络回归模型(BP神经网络回归算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 PSO是粒子群优化算法&#xff08;Particle Swarm Optimization&#xff09;的英文缩写&#xff0c;是一…

Flutter ValueNotifier 监听数据变化

系统提供了 ValueNotifier 组件的实现数据监听&#xff0c;局部刷新&#xff1a; /// 声明可能变化的数据 ValueNotifier<int> valueNotifier ValueNotifier(0);监听数据&#xff1a; ValueListenableBuilder<int>(/// 建立与 _statusNotifier 的绑定关系valueL…

H3C-Cloud Lab实验-三层交换机实验

实验拓扑图&#xff1a; 实验需求&#xff1a; 1. 按照图示为 PC2 和 PC3 配置 IP 地址和网关 2. PC2 属于 Vlan10&#xff0c;PC3 属于 Vlan20&#xff0c;在三层交换机上配置 Vlanif 三层接口实现 Vlan10 和 Vlan20 三层互通 3. PC2 和 PC3 可以互通 实验步骤&#xff1a…

WEB:Web_php_include(多解)

背景知识 文件包含 file://协议 php://协议 data://协议 了解strstr函数 题目 <?php show_source(__FILE__); echo $_GET[hello]; /*可以构造payload*/ $page$_GET[page]; while (strstr($page, "php://")) { /*strstr()函数*/$pagestr_replace("php://&q…

Django实现接口自动化平台(十一)项目模块Projects序列化器及视图【持续更新中】

相关文章&#xff1a; Django实现接口自动化平台&#xff08;十&#xff09;自定义action names【持续更新中】_做测试的喵酱的博客-CSDN博客 本章是项目的一个分解&#xff0c;查看本章内容时&#xff0c;要结合整体项目代码来看&#xff1a; python django vue httprunner …

ICU 排序规则设置概述(Ⅰ)

ICU 排序规则设置概述&#xff08;1&#xff09; 2023年5月16日 原文链接&#xff1a;http://peter.eisentraut.org/blog/2023/05/16/overview-of-icu-collation-settings 作者&#xff1a;Peter Eisentraut&#xff08;彼得艾森特劳特&#xff09; 在 PostgreSQL 中&#…

携6亿用户进场,钉钉上线借款服务

来源 | 镭射财经&#xff08;leishecaijing&#xff09; 「镭射财经」注意到&#xff0c;用户数超6亿的云办公巨头钉钉已入局助贷业务&#xff0c;上线借款服务。据了解&#xff0c;钉钉的助贷业务已上线一段时间&#xff0c;目前仅有四家资金方。 产品信息显示&#xff0c;钉…

在外Windows远程连接MongoDB数据库【无公网IP】

文章目录 前言1. 安装数据库2. 内网穿透2.1 安装cpolar内网穿透2.2 创建隧道映射2.3 测试随机公网地址远程连接 3. 配置固定TCP端口地址3.1 保留一个固定的公网TCP端口地址3.2 配置固定公网TCP端口地址3.3 测试固定地址公网远程访问 转载自cpolar极点云文章&#xff1a;公网远程…

论文阅读-2:基于深度学习的大尺度遥感图像建筑物分割研究

一、该网络中采用了上下文信息捕获模块。通过扩大感受野&#xff0c;在保留细节信息的同时&#xff0c;在中心部分进行多尺度特征的融合&#xff0c;缓解了传统算法中细节信息丢失的问题&#xff1b;通过自适应地融合局部语义特征&#xff0c;该网络在空间特征和通道特征之间建…

docker服务启动过程分析

How docker.service start&#xff1f; just by ref 我们先了解docker的各个核心组件的介绍 runc&#xff1a;runc实现了容器的底层功能&#xff0c;例如创建、运行等。runc通过调用内核接口为容器创建和管理cgroup、namespace等Linux内核功能&#xff0c;来实现容器的核心特…

CXXABI_1.3.8 not found

文章首发于 CXXABI_1.3.8 not found 。 当在 CentOS 7 安装 sqlite3 时会遇到 /lib64/libstdc.so.6: version CXXABI_1.3.8 not found 报错的问题&#xff0c;下面罗列出我的解决流程&#xff1a; 查看 libstdc.so.6 包含的 CXXABI 版本 # 查看本地 CXXABI 所有可用版本 str…