mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-21 16:09:12 +03:00
fix: codeblock various fixes (#6550)
This commit is contained in:
parent
81fbac2a73
commit
24bd0e9f59
@ -1223,6 +1223,9 @@ dependencies:
|
|||||||
'@types/domhandler':
|
'@types/domhandler':
|
||||||
specifier: ^2.4.5
|
specifier: ^2.4.5
|
||||||
version: 2.4.5
|
version: 2.4.5
|
||||||
|
'@types/dompurify':
|
||||||
|
specifier: ^3.0.5
|
||||||
|
version: 3.0.5
|
||||||
'@types/email-addresses':
|
'@types/email-addresses':
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0
|
version: 3.0.0
|
||||||
@ -1451,6 +1454,9 @@ dependencies:
|
|||||||
domhandler:
|
domhandler:
|
||||||
specifier: ^5.0.3
|
specifier: ^5.0.3
|
||||||
version: 5.0.3
|
version: 5.0.3
|
||||||
|
dompurify:
|
||||||
|
specifier: ^3.1.6
|
||||||
|
version: 3.1.6
|
||||||
domutils:
|
domutils:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
@ -8954,6 +8960,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-lANhC2grmFG1gBac/8sDAKdIXx+TzAdkJIAjEOSMA+qW3297ybACEbacJnG15aNYfrzDO6fdcoouokqAKsy6aQ==}
|
resolution: {integrity: sha512-lANhC2grmFG1gBac/8sDAKdIXx+TzAdkJIAjEOSMA+qW3297ybACEbacJnG15aNYfrzDO6fdcoouokqAKsy6aQ==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/dompurify@3.0.5:
|
||||||
|
resolution: {integrity: sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==}
|
||||||
|
dependencies:
|
||||||
|
'@types/trusted-types': 2.0.7
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/domutils@1.7.8:
|
/@types/domutils@1.7.8:
|
||||||
resolution: {integrity: sha512-iZGboDV79ibrO3D625p9yD+VgmMDnyJocdIRJvu9Xz66R8SHfOY/XNgdjY5SFoFiLgILceVfSLt7IUhlk1Vhhg==}
|
resolution: {integrity: sha512-iZGboDV79ibrO3D625p9yD+VgmMDnyJocdIRJvu9Xz66R8SHfOY/XNgdjY5SFoFiLgILceVfSLt7IUhlk1Vhhg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -9534,6 +9546,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==}
|
resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/@types/trusted-types@2.0.7:
|
||||||
|
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@types/unist@2.0.10:
|
/@types/unist@2.0.10:
|
||||||
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==}
|
||||||
dev: false
|
dev: false
|
||||||
@ -12958,6 +12974,10 @@ packages:
|
|||||||
domelementtype: 2.3.0
|
domelementtype: 2.3.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/dompurify@3.1.6:
|
||||||
|
resolution: {integrity: sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/domutils@1.5.1:
|
/domutils@1.5.1:
|
||||||
resolution: {integrity: sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==}
|
resolution: {integrity: sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -30472,7 +30492,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/presentation.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
|
file:projects/presentation.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
|
||||||
resolution: {integrity: sha512-r+NP0EMgEeKbfaa4v8P1Iho0cfYqe9PhOBfV6SPd/9xnNPt42nK9Gu4r5so1LTolhEUzbFiKh7zSX1ADL5e/3g==, tarball: file:projects/presentation.tgz}
|
resolution: {integrity: sha512-ryBht4b1zE/Ik6KZqDL/joAzt3968bkRbGZOt3x+pE929i7yCtHmlMC7W65Nlr1eglhC2JTSy2NiKTNv9yjcuw==, tarball: file:projects/presentation.tgz}
|
||||||
id: file:projects/presentation.tgz
|
id: file:projects/presentation.tgz
|
||||||
name: '@rush-temp/presentation'
|
name: '@rush-temp/presentation'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -35107,17 +35127,19 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/ui.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
|
file:projects/ui.tgz(@types/node@20.11.19)(esbuild@0.20.1)(postcss-load-config@4.0.2)(postcss@8.4.35)(ts-node@10.9.2):
|
||||||
resolution: {integrity: sha512-WtSFJW84fNe+3lwzv2a8CRmyYIsY8B6HHJwg3YKLd7jWHF4T8hYIf892hAEv7kvh/vrZ7elq8E8b1znmCNd7Sw==, tarball: file:projects/ui.tgz}
|
resolution: {integrity: sha512-umESBjjPj7ES3uF9YcS31H5dwqZtMATByltYeDc+XG+7ovD1SOM11UAjBpHCqj026RvvqcSjE8lAQP1zRXxCoA==, tarball: file:projects/ui.tgz}
|
||||||
id: file:projects/ui.tgz
|
id: file:projects/ui.tgz
|
||||||
name: '@rush-temp/ui'
|
name: '@rush-temp/ui'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@types/dompurify': 3.0.5
|
||||||
'@types/jest': 29.5.12
|
'@types/jest': 29.5.12
|
||||||
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
'@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0)(eslint@8.56.0)(typescript@5.3.3)
|
||||||
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
'@typescript-eslint/parser': 6.21.0(eslint@8.56.0)(typescript@5.3.3)
|
||||||
autolinker: 4.0.0
|
autolinker: 4.0.0
|
||||||
date-fns: 2.30.0
|
date-fns: 2.30.0
|
||||||
date-fns-tz: 2.0.0(date-fns@2.30.0)
|
date-fns-tz: 2.0.0(date-fns@2.30.0)
|
||||||
|
dompurify: 3.1.6
|
||||||
emoji-regex: 10.3.0
|
emoji-regex: 10.3.0
|
||||||
eslint: 8.56.0
|
eslint: 8.56.0
|
||||||
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
eslint-config-standard-with-typescript: 40.0.0(@typescript-eslint/eslint-plugin@6.21.0)(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3)
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
"@hcengineering/ui": "^0.6.15",
|
"@hcengineering/ui": "^0.6.15",
|
||||||
"@hcengineering/view": "^0.6.13",
|
"@hcengineering/view": "^0.6.13",
|
||||||
"@hcengineering/text": "^0.6.5",
|
"@hcengineering/text": "^0.6.5",
|
||||||
|
"@hcengineering/diffview": "^0.6.0",
|
||||||
"@hcengineering/uploader": "^0.6.0",
|
"@hcengineering/uploader": "^0.6.0",
|
||||||
"svelte": "^4.2.12",
|
"svelte": "^4.2.12",
|
||||||
"@hcengineering/client": "^0.6.18",
|
"@hcengineering/client": "^0.6.18",
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2024 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.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import diffview from '@hcengineering/diffview'
|
||||||
|
import { MarkupNode } from '@hcengineering/text'
|
||||||
|
import { Component } from '@hcengineering/ui'
|
||||||
|
|
||||||
|
export let node: MarkupNode
|
||||||
|
export let preview = false
|
||||||
|
|
||||||
|
$: language = node.attrs?.language
|
||||||
|
$: content = node.content ?? []
|
||||||
|
$: value = content.map((node) => node.text).join('/n')
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if node}
|
||||||
|
<pre class="proseCodeBlock" style:margin={preview ? '0' : null}><code
|
||||||
|
><Component is={diffview.component.Highlight} props={{ value, language }} /></code
|
||||||
|
></pre>
|
||||||
|
{/if}
|
@ -17,6 +17,7 @@
|
|||||||
import { AttrValue, MarkupNode, MarkupNodeType } from '@hcengineering/text'
|
import { AttrValue, MarkupNode, MarkupNodeType } from '@hcengineering/text'
|
||||||
|
|
||||||
import MarkupNodes from './Nodes.svelte'
|
import MarkupNodes from './Nodes.svelte'
|
||||||
|
import CodeBlockNode from './CodeBlockNode.svelte'
|
||||||
import ObjectNode from './ObjectNode.svelte'
|
import ObjectNode from './ObjectNode.svelte'
|
||||||
|
|
||||||
export let node: MarkupNode
|
export let node: MarkupNode
|
||||||
@ -71,7 +72,7 @@
|
|||||||
<MarkupNodes {nodes} {preview} />
|
<MarkupNodes {nodes} {preview} />
|
||||||
</svelte:element>
|
</svelte:element>
|
||||||
{:else if node.type === MarkupNodeType.code_block}
|
{:else if node.type === MarkupNodeType.code_block}
|
||||||
<pre class="proseCodeBlock" style:margin={preview ? '0' : null}><code><MarkupNodes {nodes} {preview} /></code></pre>
|
<CodeBlockNode {node} {preview} />
|
||||||
{:else if node.type === MarkupNodeType.image}
|
{:else if node.type === MarkupNodeType.image}
|
||||||
{@const src = toString(attrs.src)}
|
{@const src = toString(attrs.src)}
|
||||||
{@const alt = toString(attrs.alt)}
|
{@const alt = toString(attrs.alt)}
|
||||||
|
@ -77,7 +77,6 @@
|
|||||||
--text-editor-highlighted-node-delete-background-color: #F6DCDA;
|
--text-editor-highlighted-node-delete-background-color: #F6DCDA;
|
||||||
--text-editor-highlighted-node-delete-font-color: #54201C;
|
--text-editor-highlighted-node-delete-font-color: #54201C;
|
||||||
|
|
||||||
--text-editor-inline-code-color: #B02B46;
|
|
||||||
--text-editor-table-marker-color: #bebebf;
|
--text-editor-table-marker-color: #bebebf;
|
||||||
|
|
||||||
--theme-clockface-sec-arrow: conic-gradient(at 50% -10px, rgba(255, 0, 0, 0), rgba(255, 0, 0, 0) 49%, #F47758 50%, rgba(255, 0, 0, 0) 51%, rgba(255, 0, 0, 0) 100%);
|
--theme-clockface-sec-arrow: conic-gradient(at 50% -10px, rgba(255, 0, 0, 0), rgba(255, 0, 0, 0) 49%, #F47758 50%, rgba(255, 0, 0, 0) 51%, rgba(255, 0, 0, 0) 100%);
|
||||||
|
@ -345,7 +345,6 @@ table.proseTable {
|
|||||||
margin: 0 1px;
|
margin: 0 1px;
|
||||||
padding: 0 .25rem;
|
padding: 0 .25rem;
|
||||||
font-family: var(--mono-font);
|
font-family: var(--mono-font);
|
||||||
color: var(--text-editor-inline-code-color);
|
|
||||||
background-color: var(--theme-button-default);
|
background-color: var(--theme-button-default);
|
||||||
border: 1px solid var(--theme-button-border);
|
border: 1px solid var(--theme-button-border);
|
||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
"prettier": "^3.1.0",
|
"prettier": "^3.1.0",
|
||||||
"typescript": "^5.3.3",
|
"typescript": "^5.3.3",
|
||||||
"@types/jest": "^29.5.5",
|
"@types/jest": "^29.5.5",
|
||||||
|
"@types/dompurify": "^3.0.5",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"ts-jest": "^29.1.1",
|
"ts-jest": "^29.1.1",
|
||||||
"svelte-eslint-parser": "^0.33.1"
|
"svelte-eslint-parser": "^0.33.1"
|
||||||
@ -47,6 +48,7 @@
|
|||||||
"emoji-regex": "^10.1.0",
|
"emoji-regex": "^10.1.0",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
"date-fns-tz": "^2.0.0",
|
"date-fns-tz": "^2.0.0",
|
||||||
|
"dompurify": "^3.1.6",
|
||||||
"@hcengineering/analytics": "^0.6.0"
|
"@hcengineering/analytics": "^0.6.0"
|
||||||
},
|
},
|
||||||
"repository": "https://github.com/hcenginneing/anticrm",
|
"repository": "https://github.com/hcenginneing/anticrm",
|
||||||
|
23
packages/ui/src/components/Html.svelte
Normal file
23
packages/ui/src/components/Html.svelte
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2024 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.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import dompurify from 'dompurify'
|
||||||
|
|
||||||
|
export let value: string
|
||||||
|
|
||||||
|
$: sanitized = dompurify.sanitize(value)
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{@html sanitized}
|
@ -96,6 +96,7 @@ export { default as DatePresenter } from './components/calendar/DatePresenter.sv
|
|||||||
export { default as DueDatePresenter } from './components/calendar/DueDatePresenter.svelte'
|
export { default as DueDatePresenter } from './components/calendar/DueDatePresenter.svelte'
|
||||||
export { default as DateTimePresenter } from './components/calendar/DateTimePresenter.svelte'
|
export { default as DateTimePresenter } from './components/calendar/DateTimePresenter.svelte'
|
||||||
export { default as TimeInputBox } from './components/calendar/TimeInputBox.svelte'
|
export { default as TimeInputBox } from './components/calendar/TimeInputBox.svelte'
|
||||||
|
export { default as Html } from './components/Html.svelte'
|
||||||
export { default as StylishEdit } from './components/StylishEdit.svelte'
|
export { default as StylishEdit } from './components/StylishEdit.svelte'
|
||||||
export { default as Grid } from './components/Grid.svelte'
|
export { default as Grid } from './components/Grid.svelte'
|
||||||
export { default as Row } from './components/Row.svelte'
|
export { default as Row } from './components/Row.svelte'
|
||||||
|
26
plugins/diffview-resources/src/components/Highlight.svelte
Normal file
26
plugins/diffview-resources/src/components/Highlight.svelte
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<!--
|
||||||
|
// Copyright © 2024 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.
|
||||||
|
-->
|
||||||
|
<script lang="ts">
|
||||||
|
import { Html } from '@hcengineering/ui'
|
||||||
|
|
||||||
|
import { highlightText } from '../highlight'
|
||||||
|
|
||||||
|
export let value: string
|
||||||
|
export let language: string | undefined = undefined
|
||||||
|
|
||||||
|
$: highlighted = highlightText(value, { language })
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Html value={highlighted} />
|
@ -19,18 +19,18 @@ import { hljsDefineSvelte } from './languages/svelte-hljs'
|
|||||||
hljs.registerLanguage('svelte', hljsDefineSvelte)
|
hljs.registerLanguage('svelte', hljsDefineSvelte)
|
||||||
|
|
||||||
export interface HighlightOptions {
|
export interface HighlightOptions {
|
||||||
language: string
|
language: string | undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
export function highlightText (text: string, options: HighlightOptions): string {
|
export function highlightText (text: string, options: HighlightOptions): string {
|
||||||
// We should always use highlighter because it sanitizes the input
|
// We should always use highlighter because it sanitizes the input
|
||||||
// We have to always use highlighter to ensure that the input is sanitized
|
// We have to always use highlighter to ensure that the input is sanitized
|
||||||
const validLanguage = options.language !== '' && hljs.getLanguage(options.language) !== undefined
|
const { language } = options
|
||||||
const language = validLanguage ? options.language : 'text'
|
const validLanguage = language !== undefined && hljs.getLanguage(language) !== undefined
|
||||||
|
|
||||||
const { value: highlighted } = hljs.highlight(text, { language })
|
const { value: highlighted } = validLanguage ? hljs.highlight(text, { language }) : hljs.highlightAuto(text)
|
||||||
const normalized = normalizeHighlightTags(highlighted)
|
|
||||||
return normalized
|
return normalizeHighlightTags(highlighted)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function highlightLines (lines: string[], options: HighlightOptions): string[] {
|
export function highlightLines (lines: string[], options: HighlightOptions): string[] {
|
||||||
|
@ -15,10 +15,12 @@
|
|||||||
|
|
||||||
import { type Resources } from '@hcengineering/platform'
|
import { type Resources } from '@hcengineering/platform'
|
||||||
import DiffView from './components/DiffView.svelte'
|
import DiffView from './components/DiffView.svelte'
|
||||||
|
import Highlight from './components/Highlight.svelte'
|
||||||
import InlineDiffView from './components/InlineDiffView.svelte'
|
import InlineDiffView from './components/InlineDiffView.svelte'
|
||||||
export default async (): Promise<Resources> => ({
|
export default async (): Promise<Resources> => ({
|
||||||
component: {
|
component: {
|
||||||
DiffView,
|
DiffView,
|
||||||
InlineDiffView
|
InlineDiffView,
|
||||||
|
Highlight
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -48,7 +48,8 @@ export interface DiffFileId {
|
|||||||
export default plugin(diffviewId, {
|
export default plugin(diffviewId, {
|
||||||
component: {
|
component: {
|
||||||
DiffView: '' as AnyComponent,
|
DiffView: '' as AnyComponent,
|
||||||
InlineDiffView: '' as AnyComponent
|
InlineDiffView: '' as AnyComponent,
|
||||||
|
Highlight: '' as AnyComponent
|
||||||
},
|
},
|
||||||
string: {
|
string: {
|
||||||
ViewMode: '' as IntlString,
|
ViewMode: '' as IntlString,
|
||||||
|
@ -13,12 +13,13 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import { codeBlockOptions } from '@hcengineering/text'
|
||||||
import { DropdownLabelsPopup, getEventPositionElement, showPopup } from '@hcengineering/ui'
|
import { DropdownLabelsPopup, getEventPositionElement, showPopup } from '@hcengineering/ui'
|
||||||
import { type CodeBlockLowlightOptions, CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight'
|
import { type CodeBlockLowlightOptions, CodeBlockLowlight } from '@tiptap/extension-code-block-lowlight'
|
||||||
import { type Node as ProseMirrorNode } from '@tiptap/pm/model'
|
import { type Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||||
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
||||||
import { Decoration, DecorationSet, type EditorView } from '@tiptap/pm/view'
|
import { Decoration, DecorationSet, type EditorView } from '@tiptap/pm/view'
|
||||||
import { type createLowlight } from 'lowlight'
|
import { common, createLowlight } from 'lowlight'
|
||||||
|
|
||||||
type Lowlight = ReturnType<typeof createLowlight>
|
type Lowlight = ReturnType<typeof createLowlight>
|
||||||
|
|
||||||
@ -26,14 +27,19 @@ const chevronSvg = `<svg width="16" height="16" viewBox="0 0 32 32" fill="curren
|
|||||||
<path d="M16 22L6 12L7.4 10.6L16 19.2L24.6 10.6L26 12L16 22Z" />
|
<path d="M16 22L6 12L7.4 10.6L16 19.2L24.6 10.6L26 12L16 22Z" />
|
||||||
</svg>`
|
</svg>`
|
||||||
|
|
||||||
export const CodeBlockExtension = CodeBlockLowlight.extend<CodeBlockLowlightOptions>({
|
export const codeBlockHighlightOptions: CodeBlockLowlightOptions = {
|
||||||
|
...codeBlockOptions,
|
||||||
|
lowlight: createLowlight(common)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CodeBlockHighlighExtension = CodeBlockLowlight.extend<CodeBlockLowlightOptions>({
|
||||||
addProseMirrorPlugins () {
|
addProseMirrorPlugins () {
|
||||||
return [...(this.parent?.() ?? []), LanguageSelector(this.options)]
|
return [...(this.parent?.() ?? []), LanguageSelector(this.options)]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
export function LanguageSelector (options: CodeBlockLowlightOptions): Plugin {
|
export function LanguageSelector (options: CodeBlockLowlightOptions): Plugin {
|
||||||
return new Plugin({
|
return new Plugin<DecorationSet>({
|
||||||
key: new PluginKey('codeblock-language-selector'),
|
key: new PluginKey('codeblock-language-selector'),
|
||||||
props: {
|
props: {
|
||||||
decorations (state) {
|
decorations (state) {
|
||||||
@ -41,13 +47,14 @@ export function LanguageSelector (options: CodeBlockLowlightOptions): Plugin {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
state: {
|
state: {
|
||||||
init () {
|
init (config, state) {
|
||||||
return DecorationSet.empty
|
return createDecorations(state.doc, options)
|
||||||
},
|
},
|
||||||
apply (tr, prev) {
|
apply (tr, prev) {
|
||||||
if (tr.docChanged) {
|
if (tr.docChanged) {
|
||||||
return createDecorations(tr.doc, options)
|
return createDecorations(tr.doc, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
return prev
|
return prev
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,7 +91,7 @@ function createDecorations (doc: ProseMirrorNode, options: CodeBlockLowlightOpti
|
|||||||
|
|
||||||
function createLangButton (language: string | null): HTMLButtonElement {
|
function createLangButton (language: string | null): HTMLButtonElement {
|
||||||
const button = document.createElement('button')
|
const button = document.createElement('button')
|
||||||
button.className = 'antiButton ghost small sh-no-shape bs-none gap-medium iconR'
|
button.className = 'antiButton link-bordered small sh-no-shape bs-none gap-medium iconR'
|
||||||
button.style.position = 'absolute'
|
button.style.position = 'absolute'
|
||||||
button.style.top = '0.375rem'
|
button.style.top = '0.375rem'
|
||||||
button.style.right = '0.375rem'
|
button.style.right = '0.375rem'
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { codeBlockOptions, codeOptions } from '@hcengineering/text'
|
import { codeOptions } from '@hcengineering/text'
|
||||||
import { showPopup } from '@hcengineering/ui'
|
import { showPopup } from '@hcengineering/ui'
|
||||||
import { type Editor, Extension } from '@tiptap/core'
|
import { type Editor, Extension } from '@tiptap/core'
|
||||||
import type { CodeOptions } from '@tiptap/extension-code'
|
import type { CodeOptions } from '@tiptap/extension-code'
|
||||||
@ -25,10 +25,9 @@ import Link from '@tiptap/extension-link'
|
|||||||
import Typography from '@tiptap/extension-typography'
|
import Typography from '@tiptap/extension-typography'
|
||||||
import Underline from '@tiptap/extension-underline'
|
import Underline from '@tiptap/extension-underline'
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
import StarterKit from '@tiptap/starter-kit'
|
||||||
import { common, createLowlight } from 'lowlight'
|
|
||||||
|
|
||||||
import LinkPopup from '../components/LinkPopup.svelte'
|
import LinkPopup from '../components/LinkPopup.svelte'
|
||||||
import { CodeBlockExtension } from '../components/extension/codeblock'
|
import { CodeBlockHighlighExtension, codeBlockHighlightOptions } from '../components/extension/codeblock'
|
||||||
|
|
||||||
export interface DefaultKitOptions {
|
export interface DefaultKitOptions {
|
||||||
codeBlock?: Partial<CodeBlockOptions> | false
|
codeBlock?: Partial<CodeBlockOptions> | false
|
||||||
@ -66,10 +65,7 @@ export const DefaultKit = Extension.create<DefaultKitOptions>({
|
|||||||
openOnClick: true,
|
openOnClick: true,
|
||||||
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
|
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
|
||||||
}),
|
}),
|
||||||
CodeBlockExtension.configure({
|
CodeBlockHighlighExtension.configure(codeBlockHighlightOptions)
|
||||||
...codeBlockOptions,
|
|
||||||
lowlight: createLowlight(common)
|
|
||||||
})
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
import { type Class, type Doc, type Ref, type Space } from '@hcengineering/core'
|
import { type Class, type Doc, type Ref, type Space } from '@hcengineering/core'
|
||||||
import { getResource } from '@hcengineering/platform'
|
import { getResource } from '@hcengineering/platform'
|
||||||
import { getBlobRef, getClient } from '@hcengineering/presentation'
|
import { getBlobRef, getClient } from '@hcengineering/presentation'
|
||||||
import { CodeBlockExtension, codeBlockOptions, CodeExtension, codeOptions } from '@hcengineering/text'
|
import { CodeExtension, codeOptions } from '@hcengineering/text'
|
||||||
import textEditor, { type ActionContext, type ExtensionCreator, type TextEditorMode } from '@hcengineering/text-editor'
|
import textEditor, { type ActionContext, type ExtensionCreator, type TextEditorMode } from '@hcengineering/text-editor'
|
||||||
import { type AnyExtension, type Editor, Extension } from '@tiptap/core'
|
import { type AnyExtension, type Editor, Extension } from '@tiptap/core'
|
||||||
import { type Level } from '@tiptap/extension-heading'
|
import { type Level } from '@tiptap/extension-heading'
|
||||||
@ -23,6 +23,7 @@ import ListKeymap from '@tiptap/extension-list-keymap'
|
|||||||
import TableHeader from '@tiptap/extension-table-header'
|
import TableHeader from '@tiptap/extension-table-header'
|
||||||
import 'prosemirror-codemark/dist/codemark.css'
|
import 'prosemirror-codemark/dist/codemark.css'
|
||||||
|
|
||||||
|
import { CodeBlockHighlighExtension, codeBlockHighlightOptions } from '../components/extension/codeblock'
|
||||||
import { NoteExtension, type NoteOptions } from '../components/extension/note'
|
import { NoteExtension, type NoteOptions } from '../components/extension/note'
|
||||||
import { FileExtension, type FileOptions } from '../components/extension/fileExt'
|
import { FileExtension, type FileOptions } from '../components/extension/fileExt'
|
||||||
import { HardBreakExtension } from '../components/extension/hardBreak'
|
import { HardBreakExtension } from '../components/extension/hardBreak'
|
||||||
@ -171,7 +172,7 @@ async function buildEditorKit (): Promise<Extension<EditorKitOptions, any>> {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
],
|
],
|
||||||
[200, CodeBlockExtension.configure(codeBlockOptions)],
|
[200, CodeBlockHighlighExtension.configure(codeBlockHighlightOptions)],
|
||||||
[210, CodeExtension.configure(codeOptions)],
|
[210, CodeExtension.configure(codeOptions)],
|
||||||
[220, HardBreakExtension.configure({ shortcuts: mode })]
|
[220, HardBreakExtension.configure({ shortcuts: mode })]
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user