Fix config editor syntax highlighting with character parser
All checks were successful
Deploy GSM / deploy (push) Successful in 25s
All checks were successful
Deploy GSM / deploy (push) Successful in 25s
Replace regex-based tokenization with character-by-character parsing to completely avoid issues with numbers in CSS class names. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -84,41 +84,81 @@ export default function HytaleConfigEditor({ token }) {
|
|||||||
if (!text) return ''
|
if (!text) return ''
|
||||||
|
|
||||||
// Escape HTML first
|
// Escape HTML first
|
||||||
let result = text
|
let escaped = text
|
||||||
.replace(/&/g, '&')
|
.replace(/&/g, '&')
|
||||||
.replace(/</g, '<')
|
.replace(/</g, '<')
|
||||||
.replace(/>/g, '>')
|
.replace(/>/g, '>')
|
||||||
|
|
||||||
// Use placeholder tokens to avoid regex conflicts
|
// Process character by character to build highlighted output
|
||||||
const tokens = []
|
let result = ''
|
||||||
let tokenIndex = 0
|
let i = 0
|
||||||
|
|
||||||
// Replace strings with placeholders
|
while (i < escaped.length) {
|
||||||
result = result.replace(/"([^"\\]|\\.)*"/g, (match) => {
|
// Check for string start
|
||||||
const isKey = result.indexOf(match + ':') !== -1
|
if (escaped[i] === '"') {
|
||||||
const className = isKey ? 'text-blue-400' : 'text-amber-300'
|
let str = '"'
|
||||||
tokens.push(`<span class="${className}">${match}</span>`)
|
i++
|
||||||
return `\x00${tokenIndex++}\x00`
|
while (i < escaped.length && escaped[i] !== '"') {
|
||||||
})
|
if (escaped[i] === '\\' && i + 1 < escaped.length) {
|
||||||
|
str += escaped[i] + escaped[i + 1]
|
||||||
// Replace booleans and null
|
i += 2
|
||||||
result = result.replace(/\b(true|false|null)\b/g, (match) => {
|
} else {
|
||||||
tokens.push(`<span class="text-purple-400">${match}</span>`)
|
str += escaped[i]
|
||||||
return `\x00${tokenIndex++}\x00`
|
i++
|
||||||
})
|
}
|
||||||
|
}
|
||||||
// Replace numbers (only standalone, not inside placeholders)
|
if (i < escaped.length) {
|
||||||
result = result.replace(/(?<!\x00)(-?\d+\.?\d*)(?!\x00)/g, (match) => {
|
str += '"'
|
||||||
if (match === '' || match === '-') return match
|
i++
|
||||||
tokens.push(`<span class="text-cyan-400">${match}</span>`)
|
}
|
||||||
return `\x00${tokenIndex++}\x00`
|
// Check if it's a key (followed by colon)
|
||||||
})
|
let j = i
|
||||||
|
while (j < escaped.length && /\s/.test(escaped[j])) j++
|
||||||
// Replace brackets
|
const isKey = escaped[j] === ':'
|
||||||
result = result.replace(/([{}\[\]])/g, '<span class="text-gray-500">$1</span>')
|
const className = isKey ? 'text-blue-400' : 'text-amber-300'
|
||||||
|
result += `<span class="${className}">${str}</span>`
|
||||||
// Restore tokens
|
}
|
||||||
result = result.replace(/\x00(\d+)\x00/g, (_, idx) => tokens[parseInt(idx)])
|
// Check for brackets
|
||||||
|
else if (/[{}\[\]]/.test(escaped[i])) {
|
||||||
|
result += `<span class="text-gray-400">${escaped[i]}</span>`
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
// Check for numbers
|
||||||
|
else if (/[-\d]/.test(escaped[i]) && (i === 0 || /[\s,:\[\{]/.test(escaped[i-1]))) {
|
||||||
|
let num = ''
|
||||||
|
if (escaped[i] === '-') {
|
||||||
|
num += '-'
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
while (i < escaped.length && /[\d.]/.test(escaped[i])) {
|
||||||
|
num += escaped[i]
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
if (num && num !== '-') {
|
||||||
|
result += `<span class="text-cyan-400">${num}</span>`
|
||||||
|
} else {
|
||||||
|
result += num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for booleans and null
|
||||||
|
else if (escaped.slice(i, i + 4) === 'true') {
|
||||||
|
result += '<span class="text-purple-400">true</span>'
|
||||||
|
i += 4
|
||||||
|
}
|
||||||
|
else if (escaped.slice(i, i + 5) === 'false') {
|
||||||
|
result += '<span class="text-purple-400">false</span>'
|
||||||
|
i += 5
|
||||||
|
}
|
||||||
|
else if (escaped.slice(i, i + 4) === 'null') {
|
||||||
|
result += '<span class="text-purple-400">null</span>'
|
||||||
|
i += 4
|
||||||
|
}
|
||||||
|
// Regular character
|
||||||
|
else {
|
||||||
|
result += escaped[i]
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user