UBERF-8560 Imrove editor code highlight (#7074)

This commit is contained in:
Alexander Onnikov
2024-10-31 20:39:47 +07:00
committed by GitHub
parent 1b02810fda
commit 6962e80acd
21 changed files with 423 additions and 43 deletions
@@ -16,7 +16,7 @@
import { Html, Loading, themeStore } from '@hcengineering/ui'
import { DiffFile, DiffLine, DiffLineType, DiffViewMode } from '@hcengineering/diffview'
import { DiffLineRenderResult, RenderOptions, renderHunk } from '../highlight'
import { DiffLineRenderResult, RenderOptions, renderHunk } from '../render'
export let file: DiffFile
export let mode: DiffViewMode
@@ -13,10 +13,9 @@
// limitations under the License.
-->
<script lang="ts">
import { highlightText } from '@hcengineering/highlight'
import { Html } from '@hcengineering/ui'
import { highlightText } from '../highlight'
export let value: string
export let language: string | undefined = undefined
@@ -1,64 +0,0 @@
//
// Copyright © 2023 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
import hljs from 'highlight.js'
import { hljsDefineSvelte } from './languages/svelte-hljs'
hljs.registerLanguage('svelte', hljsDefineSvelte)
export interface HighlightOptions {
auto?: boolean
language: string | undefined
}
export function highlightText (text: string, options: HighlightOptions): string {
// We should always use highlighter because it sanitizes the input
// We have to always use highlighter to ensure that the input is sanitized
const { language, auto } = options
const validLanguage = language !== undefined && hljs.getLanguage(language) !== undefined
const { value: highlighted } = validLanguage
? hljs.highlight(text, { language })
: auto === true
? hljs.highlightAuto(text)
: { value: text }
return normalizeHighlightTags(highlighted)
}
export function highlightLines (lines: string[], options: HighlightOptions): string[] {
const highlighted = highlightText(lines.join('\n'), options)
return highlighted.split('\n')
}
function normalizeHighlightTags (highlighted: string): string {
const openTags: string[] = []
const normalized = highlighted.replace(/(<span[^>]*>)|(<\/span>)|(\n)/g, (match) => {
if (match === '\n') {
return '</span>'.repeat(openTags.length) + '\n' + openTags.join('')
}
if (match === '</span>') {
openTags.pop()
} else {
openTags.push(match)
}
return match
})
return normalized
}
@@ -1,17 +0,0 @@
//
// Copyright © 2023 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//
export * from './highlight'
export * from './render'
@@ -1,48 +0,0 @@
export function hljsDefineSvelte (hljs: any): any {
return {
subLanguage: 'xml',
contains: [
hljs.COMMENT('<!--', '-->', {
relevance: 10
}),
{
begin: /^(\s*)(<script(\s*context="module")?>)/gm,
end: /^(\s*)(<\/script>)/gm,
subLanguage: 'javascript',
excludeBegin: true,
excludeEnd: true,
contains: [
{
begin: /^(\s*)(\$:)/gm,
end: /(\s*)/gm,
className: 'keyword'
}
]
},
{
begin: /^(\s*)(<style.*>)/gm,
end: /^(\s*)(<\/style>)/gm,
subLanguage: 'css',
excludeBegin: true,
excludeEnd: true
},
{
begin: /\{/gm,
end: /\}/gm,
subLanguage: 'javascript',
contains: [
{
begin: /[{]/,
end: /[}]/,
skip: true
},
{
begin: /([#:/@])(if|else|each|await|then|catch|debug|html)/gm,
className: 'keyword',
relevance: 10
}
]
}
]
}
}
+2
View File
@@ -14,9 +14,11 @@
//
import { type Resources } from '@hcengineering/platform'
import DiffView from './components/DiffView.svelte'
import Highlight from './components/Highlight.svelte'
import InlineDiffView from './components/InlineDiffView.svelte'
export default async (): Promise<Resources> => ({
component: {
DiffView,
@@ -14,7 +14,7 @@
//
import { type DiffHunk, type DiffLine, DiffLineType, EmptyLine } from '@hcengineering/diffview'
import { type HighlightOptions, highlightLines } from './highlight'
import { type HighlightOptions, highlightLines } from '@hcengineering/highlight'
export interface RenderOptions {
syntaxHighlight: {