Skip to content

Commit

Permalink
UBERF-6037 Enhance codeblock extension (#4993)
Browse files Browse the repository at this point in the history
Signed-off-by: Alexander Onnikov <[email protected]>
  • Loading branch information
aonnikov authored Mar 17, 2024
1 parent 81fea92 commit e587118
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 24 deletions.
71 changes: 71 additions & 0 deletions packages/text-editor/src/components/extension/codeblock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// 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.
//

import { isActive } from '@tiptap/core'
import CodeBlock from '@tiptap/extension-code-block'

export const CodeBlockExtension = CodeBlock.extend({
addCommands () {
return {
setCodeBlock:
(attributes) =>
({ commands }) => {
return commands.setNode(this.name, attributes)
},
toggleCodeBlock:
(attributes) =>
({ chain, commands, state }) => {
const { from, to } = state.selection

// merge multiple paragraphs into codeblock
if (!isActive(state, this.name) && !state.selection.empty) {
let hasParagraphsOnlySelected = true
const textArr: string[] = []
state.doc.nodesBetween(from, to, (node, pos) => {
if (node.isInline) {
return false
}
if (node.type.name !== 'paragraph') {
if (pos + 1 <= from && pos + node.nodeSize - 1 >= to) {
// skip nodes outside of the selected range
return false
} else {
// cannot merge non-paragraph nodes inside selection
hasParagraphsOnlySelected = false
return false
}
} else {
const selectedText = (node.textContent ?? '').slice(
pos + 1 > from ? 0 : from - pos - 1,
pos + node.nodeSize - 1 < to ? node.nodeSize - 1 : to - pos - 1
)
textArr.push(selectedText ?? '')
}
})
if (hasParagraphsOnlySelected && textArr.length > 1) {
return chain()
.command(({ state, tr }) => {
tr.replaceRangeWith(from, to, this.type.create(attributes, state.schema.text(textArr.join('\n'))))
return true
})
.setTextSelection({ from: from + 2, to: from + 2 })
.run()
}
}
return commands.toggleNode(this.name, 'paragraph', attributes)
}
}
}
})
34 changes: 20 additions & 14 deletions packages/text-editor/src/kits/default-kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,39 +14,45 @@
//

import { Extension } from '@tiptap/core'

import { type CodeOptions } from '@tiptap/extension-code'
import { type CodeBlockOptions } from '@tiptap/extension-code-block'
import type { Level } from '@tiptap/extension-heading'
import Highlight from '@tiptap/extension-highlight'
import Link from '@tiptap/extension-link'
import Typography from '@tiptap/extension-typography'
import StarterKit from '@tiptap/starter-kit'

export interface DefaultKitOptions {
codeBlock?: false
heading?: {
levels?: Level[]
}
history?: false
}

export const codeOptions: CodeOptions = {
HTMLAttributes: {
class: 'proseCode'
}
}

export const codeBlockOptions: CodeBlockOptions = {
languageClassPrefix: 'language-',
exitOnArrowDown: true,
exitOnTripleEnter: true,
HTMLAttributes: {
class: 'proseCodeBlock'
}
}

export const DefaultKit = Extension.create<DefaultKitOptions>({
name: 'defaultKit',

addExtensions () {
return [
StarterKit.configure({
code: {
HTMLAttributes: {
class: 'proseCode'
}
},
codeBlock: {
languageClassPrefix: 'language-',
exitOnArrowDown: true,
exitOnTripleEnter: true,
HTMLAttributes: {
class: 'proseCodeBlock'
}
},
code: codeOptions,
codeBlock: this.options.codeBlock ?? codeBlockOptions,
heading: this.options.heading,
history: this.options.history
}),
Expand Down
5 changes: 4 additions & 1 deletion packages/text-editor/src/kits/editor-kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ import TaskItem from '@tiptap/extension-task-item'
import TaskList from '@tiptap/extension-task-list'
import Underline from '@tiptap/extension-underline'

import { DefaultKit, type DefaultKitOptions } from './default-kit'
import { DefaultKit, type DefaultKitOptions, codeBlockOptions } from './default-kit'

import { CodeBlockExtension } from '../components/extension/codeblock'
import { CodemarkExtension } from '../components/extension/codemark'
import { NodeUuidExtension } from '../components/extension/nodeUuid'
import { Table, TableCell, TableRow } from '../components/extension/table'
Expand Down Expand Up @@ -62,10 +63,12 @@ export const EditorKit = Extension.create<EditorKitOptions>({
return [
DefaultKit.configure({
...this.options,
codeBlock: false,
heading: {
levels: headingLevels
}
}),
CodeBlockExtension.configure(codeBlockOptions),
CodemarkExtension,
Underline,
ListKeymap.configure({
Expand Down
21 changes: 12 additions & 9 deletions packages/text/src/kits/default-kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ import { Level } from '@tiptap/extension-heading'
import Highlight from '@tiptap/extension-highlight'
import Link from '@tiptap/extension-link'
import Typography from '@tiptap/extension-typography'
import StarterKit from '@tiptap/starter-kit'
import StarterKit, { StarterKitOptions } from '@tiptap/starter-kit'

export interface DefaultKitOptions {
codeBlock?: false
heading?: {
levels?: Level[]
}
Expand All @@ -32,21 +33,23 @@ export const DefaultKit = Extension.create<DefaultKitOptions>({
name: 'defaultKit',

addExtensions () {
const codeBlock: StarterKitOptions['codeBlock'] = this.options.codeBlock ?? {
languageClassPrefix: 'language-',
exitOnArrowDown: true,
exitOnTripleEnter: true,
HTMLAttributes: {
class: 'proseCodeBlock'
}
}

return [
StarterKit.configure({
code: {
HTMLAttributes: {
class: 'proseCode'
}
},
codeBlock: {
languageClassPrefix: 'language-',
exitOnArrowDown: true,
exitOnTripleEnter: true,
HTMLAttributes: {
class: 'proseCodeBlock'
}
},
codeBlock,
heading: this.options.heading,
history: this.options.history
}),
Expand Down

0 comments on commit e587118

Please sign in to comment.