[英]Syntax Highlighting for editable textarea in html
So I have a project that involves creating an html webapp that's similar to pastebin.所以我有一个项目涉及创建一个类似于 pastebin 的 html webapp。 And I have to add syntax highlighting but we're not allowed to used premade syntax highlighter or plugins.
我必须添加语法高亮,但我们不允许使用预制的语法高亮或插件。 We have to do it from scratch.
我们必须从头开始。 I know that I have to do it with javascript.
我知道我必须用 javascript 来做。 Can anyone give me some insight on how I should create this syntax highlighting?
谁能给我一些关于我应该如何创建这种语法突出显示的见解? I've only made some test for syntax highlighting from what I saw on yt, but mostly they are plugins
我只是根据我在 yt 上看到的内容对语法高亮进行了一些测试,但它们大多是插件
Here is the code for the test.html这是测试的代码。html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
code {
display:block;
white-space: pre-wrap;
border: 1px solid #000;
padding: 10px;
line-height: 1.5em;
font-family: "Lucida Console", Monaco, monospace;
}
.code-str { color : #090; }
.code-elem{
color: #F90;
}
</style>
<script>
function syntaxhighlights() {
var ca = document.getElementsByTagName("code");
for(var i = 0; i < ca.length; i++ ){
var data = ca[i].innerHTML;
data = data.replace (/"(.*?)"/g, '<span class="code-str">"$1"</span>');
data = data.replace (/<(.*?)>/g, '<span class="code-elem"><$1></span>');
ca[i].innerHTML = data;
}
}
window.addEventListener("load", syntaxhighlights);
</script>
</head>
<body>
<h2>Code Example:</h2>
<code><h2 id="h21">Welcome Visitors</h2>
<p>When in Rome, do as the Romans do.</p>
</code>
</body>
I have created a project involving syntax highlighting.我创建了一个涉及语法高亮的项目。 The best way is to use regex excessively.
最好的方法是过度使用正则表达式。 You have to create classes for each token.
您必须为每个令牌创建类。 You need a function to take the text and convert it into an html chunk.
您需要 function 来获取文本并将其转换为 html 块。 Using
String.replace
you can format the given text.使用
String.replace
您可以格式化给定的文本。 Just create a render class.只需创建一个渲染 class。 Mine was something like that(It has been so long since I wrote it. Hope this helps):
我的就是这样(我写它已经很久了。希望这会有所帮助):
import ReactHtmlParser from 'react-html-parser'
import StyleSheet from '../styles/native/code.module.css'
import React from 'react'
import { insertArray, replaceString, updateArray } from './utility-functions'
// Add String.matchAll polyfill in case it is not implemented
;(() => {
if (!String.prototype.matchAll) {
String.prototype.matchAll = function (regex) {
let match = regex.exec(this)
const matches = []
while (match !== null) {
matches.push(match)
match = regex.exec(this)
}
return matches
}
}
console.log('matchAll polyfill has been configured.')
})()
const createJSXBuilder = (className) => (v) =>
`<span class="${className}">${v}</span>`
const getMatchArray = (content, pattern, builder) => {
let matchArray = []
const results = Array.from(content.matchAll(pattern))
for (const result of results) {
const index = result.index
const match = result[0]
const length = match.length
matchArray.push([index, length, match, builder])
}
return matchArray
}
const sortMatchArray = (matchArray) => {
let sortedMatchedArray = []
let g
for (const matchItem of matchArray) {
if (sortedMatchedArray.length === 0) {
sortedMatchedArray.push(matchItem)
continue
}
g = true
for (let i = 0; i < sortedMatchedArray.length; i++) {
if (matchItem[0] < sortedMatchedArray[i][0]) {
sortedMatchedArray = insertArray(
sortedMatchedArray,
i,
matchItem
)
g = false
break
}
}
if (g) {
sortedMatchedArray.push(matchItem)
}
}
return sortedMatchedArray
}
const parse = (content, matchArray) => {
let secretIndex = 0
for (const match of matchArray) {
const jsx = match[3](match[2])
const beginIndex = match[0] + secretIndex
content = replaceString(content, beginIndex, beginIndex + match[1], jsx)
secretIndex += jsx.length - match[2].length
}
return content
}
export function parseSourceCodeToJSX(content) {
let matchArray = []
const newLine = /\n/g
const tab = /\t/g
const parserTokenMap = [
[/@\w+\([\w, ]*\)\n/g, createJSXBuilder(StyleSheet.annotation)],
[/(?<!(['"@]\w*\(?))[,():+\-*\[\];{}.!](?!\w*['"])/g, createJSXBuilder(StyleSheet.symbol)],
[/\/\/.*/g, createJSXBuilder(StyleSheet.comment)],
[/['"].*?['"]/g, createJSXBuilder(StyleSheet.string)],
[/\b(?<!(['"]|\/\/ )\w*)\d+\.?\d*(?!\w*['"])\b/g, createJSXBuilder(StyleSheet.number)],
[/(?<=\.)\w+(?=\()/g, createJSXBuilder(StyleSheet.method)],
[/(?<=\.)\w+(?!\()\b/g, createJSXBuilder(StyleSheet.property)],
[/\bthis(?=\.)/g, createJSXBuilder(StyleSheet.number)],
[
/\b(number|string|boolean|object|instanceof|typeof)\b/g,
createJSXBuilder(StyleSheet.method),
],
[/(>|<)/g, createJSXBuilder(StyleSheet.method)],
[
/(?<=<)\/?(?!number|string|boolean|object|instanceof|typeof)\w*(?=>)/g,
createJSXBuilder(StyleSheet.method),
],
[
/\b(((?<! )import)|new|true|extends|super|false|from|function|break|case|return|const|=|let|default|((?<! )export)|class)\b/g,
createJSXBuilder(StyleSheet.keyword),
],
]
for (const parserItem of parserTokenMap) {
matchArray = matchArray.concat(
getMatchArray(content.slice(), parserItem[0], parserItem[1])
)
}
matchArray = sortMatchArray(matchArray)
let result = parse(content, matchArray)
result = result.replace(tab, '<span class="space"></span>')
result = result.replace(newLine, '<br />')
return <div dangerouslySetInnerHTML={{ __html: result }} />
}
export function parseTextToJSX(content) {
const newLine = /\n/g
return <>{ReactHtmlParser(content.replace(newLine, '<br/>'))}</>
}
export function updateArray(arr, index, value) {
return [...arr.slice(0, index), value, ...arr.slice(index + 1)]
}
export function insertArray(arr, index, value) {
return [...arr.slice(0, index), value, ...arr.slice(index)]
}
export function replaceString(str, begin, end, value) {
return str.substring(0, begin) + value + str.substring(end)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.