正则表达式实现关键字高亮

news2024/12/28 3:45:40

使用正则表达式实现一个类似于navicat中sql编辑器功能,大致实现以下目标:

  1. 指定关键字高亮(eg. 红色)
  2. 数字高亮(eg. 蓝色)
  3. 引号内容高亮(eg.浅绿色)

实现效果如下:
在这里插入图片描述

下面直接上代码,具体解释见代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>SQL编辑器</title>
    <style>
		#edit{
			height:100px;
			width:500px;
			border:1px solid red;
			padding: 5px;
			background: black;
			color: white;
			white-space: pre-wrap;
			word-wrap:break-word;
		}
		.hight-light-red{
			color: red
		}
		.hight-light-yellow{
			color: yellow
		}
		.hight-light-lightgreen{
			color: lightgreen
		}
	</style>
</head>
<body>
    <div id="edit" contenteditable>132adasd#csfsfspan</div>
    <script>
		//SQL关键字举例
		const SQL_KEYWORDS = [
			'show', 'case', 'when', 'use', 'alter', 'add', 'change', 'select', 'from', 'as', 'left', 'right', 'inner', 'join', 'using', 'where', 'like', 'between', 'and', 'or', 'in', 'not', 'null', 'exists', 'group', 'order',
			'by', 'asc', 'desc', 'limit', 'having', 'union', 'all', 'distinct', 'create', 'truncate', 'drop', 'insert', 'delete', 'update', 'set', 'table', 'count', 'sum', 'max', 'min', 'hvg'
		];
		//正则替换高亮文本
		function hightLight(el, keywords) {
			const reg = RegExp(`(<)|(>)|(\\b(${keywords.join('|')})\\b)|(\\b(\\d+)\\b)|('[^']*'?|"[^"]*"?)`, 'gi');
			el.innerHTML = el.innerText.replace(reg, (match, k1, k2, k3, k4, k5) => {
			  if (k1) {
				//替换<
				return `&lt;`;
			  } else if (k2) {
				//替换>
				return `&gt;`;
			  } else if (k3) {
				//高亮关键字
				return `<span class='hight-light-red'>${match}</span>`;
			  } else if (k5) {
				//高亮数字(作为变量名时不高亮)
				return `<span class='hight-light-yellow'>${match}</span>`;
			  } else {
				//高亮引号内容
				return `<span class='hight-light-lightgreen'>${match}</span>`;
			  }
			});
		}
		//获取文本长度
		function getNodeTextLength(node) {
		  return node.nodeName === '#text' ? node.length : node.innerText.length;
		}
		//获取光标相对于整个文本的位置
    	function getCursorIndex(el, node, index) {
			if(node.previousSibling===null) {
				return node.parentNode===el ? index : getCursorIndex(el, node.parentNode, index);
			}
			return node===el ? index : getCursorIndex(el, node.previousSibling, index + getNodeTextLength(node.previousSibling));
        }
		//根据光标位置(相对于整个文本的位置)获取具体的位置(光标所在元素的位置)
    	function getPosition(el, index) {
        	if(el.nodeName === '#text') {
                return {el, index};
            }
            let childNodes = el.childNodes;
            for(let i = 0; i<childNodes.length; i++) {
            	let node = childNodes[i];
                let length = getNodeTextLength(node);
                if(index <= length) {
                	return getPosition(node, index);
                }
                index -= length;
            }
			return {el, index};
        }
		//设置光标位置
		function setSelectionPosition(start, end) {
            const selection = window.getSelection();
            const range = document.createRange();
            range.setStart(start.el, start.index);
            range.setEnd(end.el, end.index);
            selection.removeAllRanges();
            selection.addRange(range);
        }
		//监听输入框文本变化
        let edit = document.getElementById('edit');
        edit.oninput=function(e) {
        	let el = e.target;
            let range = window.getSelection().getRangeAt(0);
           	let {startContainer, endContainer, startOffset, endOffset} = range;
            let startIndex = getCursorIndex(el, startContainer, startOffset);
            let endIndex = getCursorIndex(el, endContainer, endOffset);

			hightLight(el, SQL_KEYWORDS);
			
			e.inputType==='insertParagraph' && (startIndex+=1, endIndex+=1);
            let start = getPosition(el, startIndex), end = getPosition(el, endIndex);
            setSelectionPosition(start, end);
        };
    </script>
</body>
</html>

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

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

相关文章

C语言参悟-分支和跳转

C语言参悟-分支跳转 一、概述二、判断条件三、if else 条件判断1. 单判断2. 条件“并联”3. 条件“串联” 四、switch case 条件判断1. “单刀” 开关2. “多刀”开关 一、概述 下面只是我的对于C语言的认识拙见&#xff0c;可以多多提出批评建议&#x1f604; 计算机的诞生很…

16JS07——数组

目标&#xff1a; 1、数组的概念 2、创建数组 3、获取数组中的元素 4、遍历数组 5、数组中新增元素 6、数组案例 一、数组的概念 数组是指一组数据的集合&#xff0c;其中的每个数据被称作元素&#xff0c;在数组中可以存放任意类型的元素。数组是一种将一组数据存储在单个变…

Flink从入门到精通之-12Flink CEP

Flink从入门到精通之-12Flink CEP 在 Flink 的学习过程中&#xff0c;从基本原理和核心层 DataStream API 到底层的处理函数、再到应用层的 Table API 和 SQL&#xff0c;我们已经掌握了 Flink 编程的各种手段&#xff0c;可以应对实际应用开发的各种需求了。 在大数据分析领域…

lecory 波形二进制文件头(.trc)定义

1.文件头&#xff0c;从0字节开始 byte[] lecroy_trc_header new byte[]{0x23,0x39,0x30,0x30,0x32,0x30,0x30,0x30,0x31,0x34,0x34,0x57,0x41,0x56,0x45,0x44,0x45,0x53,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0x45,0x43,0x52,0x4F,0x59,0x5F,0x32,0x5F,0x33,0x…

【爬虫第四章】 爬虫工具介绍

预计更新一、 爬虫技术概述 1.1 什么是爬虫技术 1.2 爬虫技术的应用领域 1.3 爬虫技术的工作原理 二、 网络协议和HTTP协议 2.1 网络协议概述 2.2 HTTP协议介绍 2.3 HTTP请求和响应 三、 Python基础 3.1 Python语言概述 3.2 Python的基本数据类型 3.3 Python的流程控制语句 3…

Hack The Box - Crocodile关卡

TASK 1 任务 1 What Nmap scanning switch employs the use of default scripts during a scan? 哪个 Nmap 扫描开关在扫描期间使用默认脚本&#xff1f; -sCTASK 2 任务 2 What service version is found to be running on port 21? 发现端口 21 上运行的服务版本是什么&…

人员定位系统的功能及在不同领域的应用

人员定位系统是实时定位系统&#xff08;RTLS&#xff09;的一种&#xff0c;是用于跟踪人员位置的软硬件一体化系统。它使用无线通信技术和传感器来获取位置数据&#xff0c;并将其发送到监控中心或移动设备。它在多个领域使用&#xff0c;包括工业、医疗保健、军事、物流等。…

【网络】· 路由器中配置单臂路由和DHCP,VTP原理

目录 &#x1f349;单臂路由的工作原理 &#x1f95d;交换机配置 &#x1f95d;路由器配置 &#x1f349;路由器配置DHCP &#x1f95d;配置实例 &#x1f95d;路由器配置 &#x1f95d;验证 &#x1f349;VTP工作原理 &#x1f95d;VTP模式 &#x1f95d;VTP通告 &#x1f95d…

基于多动作深度强化学习的柔性车间调度研究(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Hive部署远程模式

远程模式 简介 将hive中的相关进程比如hiveserver2或者metastore这样的进程单独开启&#xff0c;使用客户端工具或者命令行进行远程连接这样的服务&#xff0c;即远程模式。客户端可以在任何机器上&#xff0c;只要连接到这个server&#xff0c;就可以进行操作。客户端可以不…

【1130. 叶值的最小代价生成树】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个正整数数组 arr&#xff0c;考虑所有满足以下条件的二叉树&#xff1a; 每个节点都有 0 个或是 2 个子节点。数组 arr 中的值与树的中序遍历中每个叶节点的值一一对应。每个非叶节点的值等于…

用arcgis for javascript 开发一个简单的二维地图(入门案例)

效果如图&#xff1a; 一、引入arcgis <link rel"stylesheet" href"https://js.arcgis.com/4.26/esri/themes/light/main.css" /> <script src"https://js.arcgis.com/4.26/"></script>2.加载模块 使用第二个标记从 API 加…

第四期:栈与队列的交换游戏

目录 1. 用队列实现栈2. 用栈实现队列3. 答案3.1 用队列实现栈3.2 用栈实现队列 PS&#xff1a;每道题解题方法不唯一&#xff0c;欢迎讨论&#xff01;每道题后都有解析帮助你分析做题&#xff0c;答案在最下面&#xff0c;关注博主每天持续更新。 1. 用队列实现栈 题目描述 …

RISC-V IDE MRS使用笔记(八):实现局域网下的远程调试功能

RISC-V IDE MRS使用笔记(八)&#xff1a;实现局域网下的远程调试功能 1.原理介绍 MRS调试时上位机与硬件的通信基于gdb客户端与服务端的连接。调试时&#xff0c;首先启动openocd以挂载gdbserver的服务到指定端口上。通信建立后&#xff0c;监听到界面操作后以gdb指令的形式发…

Mapbox字体切片工具fontnik部署与使用

我们在使用Mapbox的时候,不同的图层可以配置不同的字体。Mapbox主要通过分片加载SDF格式字体的方式,将比较大的字体文件传输到前端渲染使用。fontnik可以将字体文件也制作成pbf切片文件,在访问的时候,图中大括号的位置,style中的glyphs,需要根据实际字体和切片索引进行替…

基于html+css的图展示101

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

硬件速攻-SG90舵机(180和360)

外观 180度和360度的区别 180度的舵机可以控制角度 360度的舵机只能控制正反转和速度 驱动逻辑 180度 t 0.5ms——————转动 0 t 1.0ms——————转动 45 t 1.5ms——————转动 90 t 2.0ms——————转动 135 t 2.5ms——————转动180 360度 t 0.5ms—…

微信小程序授权给第三方平台后,“消息与事件接收URL“接收不到客服消息

记录微信小程序授权第三方平台遇到的问题 问题表现为&#xff1a;微信小程序授权给第三方平台后&#xff0c;在小程序客服发送消息&#xff0c;消息与事件接收URL接收不到客服消息 小程序授权配置如下&#xff1a; 1、小程序已授权第三方平台“小程序客服管理”权限 2、小程…

韧性数据安全体系缘起与三个目标 |CEO专栏

今年4月&#xff0c;美创科技在数据安全领域的新探索——“韧性”数据安全防护体系框架正式发布亮相。 为帮您更深入了解“韧性数据安全”&#xff0c;我们特别推出专栏“构建适应性进化的韧性数据安全体系”&#xff0c;CEO柳遵梁亲自执笔&#xff0c;进行系列解读分享。 首期…

4.4. 对象序列化与反序列化

在本节中&#xff0c;我们将详细讨论Java中的对象序列化与反序列化概念、使用方法以及实例。对象序列化是将对象的状态信息转换为字节流的过程&#xff0c;而反序列化则相反&#xff0c;是将字节流恢复为对象的过程。 4.4.1 为什么需要对象序列化&#xff1f; 对象序列化的主…