mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-23 16:56:07 +00:00
UBERF-4795 Make editor extensions kit configurable (#4329)
Signed-off-by: Alexander Onnikov <alexander.onnikov@xored.com>
This commit is contained in:
parent
e6ae8703b3
commit
b84aa01534
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
@ -90,6 +90,7 @@
|
|||||||
"SECRET": "secret",
|
"SECRET": "secret",
|
||||||
"METRICS_CONSOLE": "true",
|
"METRICS_CONSOLE": "true",
|
||||||
"TRANSACTOR_URL": "ws://localhost:3333",
|
"TRANSACTOR_URL": "ws://localhost:3333",
|
||||||
|
"UPLOAD_URL": "/files",
|
||||||
"MONGO_URL": "mongodb://localhost:27017",
|
"MONGO_URL": "mongodb://localhost:27017",
|
||||||
"MINIO_ACCESS_KEY": "minioadmin",
|
"MINIO_ACCESS_KEY": "minioadmin",
|
||||||
"MINIO_SECRET_KEY": "minioadmin",
|
"MINIO_SECRET_KEY": "minioadmin",
|
||||||
|
@ -707,6 +707,9 @@ dependencies:
|
|||||||
'@tiptap/extension-highlight':
|
'@tiptap/extension-highlight':
|
||||||
specifier: ^2.1.12
|
specifier: ^2.1.12
|
||||||
version: 2.1.12(@tiptap/core@2.1.12)
|
version: 2.1.12(@tiptap/core@2.1.12)
|
||||||
|
'@tiptap/extension-history':
|
||||||
|
specifier: ^2.1.12
|
||||||
|
version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
'@tiptap/extension-link':
|
'@tiptap/extension-link':
|
||||||
specifier: ^2.1.12
|
specifier: ^2.1.12
|
||||||
version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
version: 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
@ -23650,7 +23653,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/text-editor.tgz(@types/node@16.11.68)(bufferutil@4.0.7)(esbuild@0.16.17)(postcss-load-config@4.0.1)(postcss@8.4.31)(prosemirror-model@1.19.3)(ts-node@10.9.1):
|
file:projects/text-editor.tgz(@types/node@16.11.68)(bufferutil@4.0.7)(esbuild@0.16.17)(postcss-load-config@4.0.1)(postcss@8.4.31)(prosemirror-model@1.19.3)(ts-node@10.9.1):
|
||||||
resolution: {integrity: sha512-OTmONKS1vIIvQHrDVFHNsaVZopEiXGbimLMlkHpMj1sznAdusJITPsPbj9Q3YLvIc8VXNSlQeRzN2QlkwW2IYg==, tarball: file:projects/text-editor.tgz}
|
resolution: {integrity: sha512-QgUDUW3v5zIVHETcfC/UsoZ8EPeauNcSyGO+I/J6rXLG2ndtNKIWRdl7Herj480/Q6JjPjWmm5RTIRAnz8lZXQ==, tarball: file:projects/text-editor.tgz}
|
||||||
id: file:projects/text-editor.tgz
|
id: file:projects/text-editor.tgz
|
||||||
name: '@rush-temp/text-editor'
|
name: '@rush-temp/text-editor'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -23665,6 +23668,7 @@ packages:
|
|||||||
'@tiptap/extension-gapcursor': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
'@tiptap/extension-gapcursor': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
'@tiptap/extension-heading': 2.1.12(@tiptap/core@2.1.12)
|
'@tiptap/extension-heading': 2.1.12(@tiptap/core@2.1.12)
|
||||||
'@tiptap/extension-highlight': 2.1.12(@tiptap/core@2.1.12)
|
'@tiptap/extension-highlight': 2.1.12(@tiptap/core@2.1.12)
|
||||||
|
'@tiptap/extension-history': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
'@tiptap/extension-link': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
'@tiptap/extension-link': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
'@tiptap/extension-list-keymap': 2.1.12(@tiptap/core@2.1.12)
|
'@tiptap/extension-list-keymap': 2.1.12(@tiptap/core@2.1.12)
|
||||||
'@tiptap/extension-mention': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)(@tiptap/suggestion@2.1.12)
|
'@tiptap/extension-mention': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)(@tiptap/suggestion@2.1.12)
|
||||||
@ -23735,7 +23739,7 @@ packages:
|
|||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
file:projects/text.tgz(@types/node@16.11.68)(esbuild@0.16.17)(svelte@4.2.5)(ts-node@10.9.1):
|
file:projects/text.tgz(@types/node@16.11.68)(esbuild@0.16.17)(svelte@4.2.5)(ts-node@10.9.1):
|
||||||
resolution: {integrity: sha512-mAnt4uQfrjjGcqAXJI8y+sOq5joLxJAU4l8shfLkgdv0FJY+JcR7/lnT0cg79pAEySJ3WWb3RnXlyH+TtGejJQ==, tarball: file:projects/text.tgz}
|
resolution: {integrity: sha512-yBBmdVZ6t7OiE7WauaYvqDsgVsOUzS8W4sKslQ6EXa/gvDvnV3F/cjAMIvbH6B4w1bFOWoqgC25sqxO8HUaEOQ==, tarball: file:projects/text.tgz}
|
||||||
id: file:projects/text.tgz
|
id: file:projects/text.tgz
|
||||||
name: '@rush-temp/text'
|
name: '@rush-temp/text'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@ -23744,6 +23748,7 @@ packages:
|
|||||||
'@tiptap/extension-gapcursor': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
'@tiptap/extension-gapcursor': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
'@tiptap/extension-heading': 2.1.12(@tiptap/core@2.1.12)
|
'@tiptap/extension-heading': 2.1.12(@tiptap/core@2.1.12)
|
||||||
'@tiptap/extension-highlight': 2.1.12(@tiptap/core@2.1.12)
|
'@tiptap/extension-highlight': 2.1.12(@tiptap/core@2.1.12)
|
||||||
|
'@tiptap/extension-history': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
'@tiptap/extension-link': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
'@tiptap/extension-link': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
'@tiptap/extension-mention': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)(@tiptap/suggestion@2.1.12)
|
'@tiptap/extension-mention': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)(@tiptap/suggestion@2.1.12)
|
||||||
'@tiptap/extension-table': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
'@tiptap/extension-table': 2.1.12(@tiptap/core@2.1.12)(@tiptap/pm@2.1.12)
|
||||||
|
@ -103,6 +103,7 @@ services:
|
|||||||
- COLLABORATOR_PORT=3078
|
- COLLABORATOR_PORT=3078
|
||||||
- SECRET=secret
|
- SECRET=secret
|
||||||
- TRANSACTOR_URL=ws://localhost:3333
|
- TRANSACTOR_URL=ws://localhost:3333
|
||||||
|
- UPLOAD_URL=/files
|
||||||
- MONGO_URL=mongodb://mongodb:27017
|
- MONGO_URL=mongodb://mongodb:27017
|
||||||
- MINIO_ENDPOINT=minio
|
- MINIO_ENDPOINT=minio
|
||||||
- MINIO_ACCESS_KEY=minioadmin
|
- MINIO_ACCESS_KEY=minioadmin
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
"@tiptap/extension-code-block": "^2.1.12",
|
"@tiptap/extension-code-block": "^2.1.12",
|
||||||
"@tiptap/extension-gapcursor": "^2.1.12",
|
"@tiptap/extension-gapcursor": "^2.1.12",
|
||||||
"@tiptap/extension-heading": "^2.1.12",
|
"@tiptap/extension-heading": "^2.1.12",
|
||||||
|
"@tiptap/extension-history": "^2.1.12",
|
||||||
"@tiptap/extension-table": "^2.1.12",
|
"@tiptap/extension-table": "^2.1.12",
|
||||||
"@tiptap/extension-table-cell": "^2.1.12",
|
"@tiptap/extension-table-cell": "^2.1.12",
|
||||||
"@tiptap/extension-table-header": "^2.1.12",
|
"@tiptap/extension-table-header": "^2.1.12",
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
import { calculateDecorations, createYdocDocument } from './diff/decorations'
|
import { calculateDecorations, createYdocDocument } from './diff/decorations'
|
||||||
import { defaultEditorAttributes } from './editor/editorProps'
|
import { defaultEditorAttributes } from './editor/editorProps'
|
||||||
import { defaultExtensions } from './extensions'
|
import { EditorKit } from '../kits/editor-kit'
|
||||||
|
|
||||||
export let ydoc: Ydoc
|
export let ydoc: Ydoc
|
||||||
export let field: string | undefined = undefined
|
export let field: string | undefined = undefined
|
||||||
@ -79,7 +79,7 @@
|
|||||||
editorProps: { attributes: mergeAttributes(defaultEditorAttributes, { class: 'flex-grow' }) },
|
editorProps: { attributes: mergeAttributes(defaultEditorAttributes, { class: 'flex-grow' }) },
|
||||||
element,
|
element,
|
||||||
editable: false,
|
editable: false,
|
||||||
extensions: [...defaultExtensions, DecorationExtension, Collaboration.configure({ document: ydoc, field })]
|
extensions: [EditorKit, DecorationExtension, Collaboration.configure({ document: ydoc, field })]
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -100,4 +100,5 @@
|
|||||||
on:focus
|
on:focus
|
||||||
on:blur
|
on:blur
|
||||||
on:update
|
on:update
|
||||||
|
on:open-document
|
||||||
/>
|
/>
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
import { Completion } from '../Completion'
|
import { Completion } from '../Completion'
|
||||||
import { textEditorCommandHandler } from '../commands'
|
import { textEditorCommandHandler } from '../commands'
|
||||||
|
import { EditorKit } from '../kits/editor-kit'
|
||||||
import textEditorPlugin from '../plugin'
|
import textEditorPlugin from '../plugin'
|
||||||
import { DocumentId, TiptapCollabProvider } from '../provider'
|
import { DocumentId, TiptapCollabProvider } from '../provider'
|
||||||
import {
|
import {
|
||||||
@ -47,7 +48,7 @@
|
|||||||
import { FileAttachFunction, ImageExtension } from './extension/imageExt'
|
import { FileAttachFunction, ImageExtension } from './extension/imageExt'
|
||||||
import { InlinePopupExtension } from './extension/inlinePopup'
|
import { InlinePopupExtension } from './extension/inlinePopup'
|
||||||
import { InlineStyleToolbarExtension } from './extension/inlineStyleToolbar'
|
import { InlineStyleToolbarExtension } from './extension/inlineStyleToolbar'
|
||||||
import { completionConfig, defaultExtensions } from './extensions'
|
import { completionConfig } from './extensions'
|
||||||
|
|
||||||
export let documentId: DocumentId
|
export let documentId: DocumentId
|
||||||
export let field: string | undefined = undefined
|
export let field: string | undefined = undefined
|
||||||
@ -207,7 +208,8 @@
|
|||||||
optionalExtensions.push(
|
optionalExtensions.push(
|
||||||
ImageExtension.configure({
|
ImageExtension.configure({
|
||||||
inline: true,
|
inline: true,
|
||||||
attachFile
|
attachFile,
|
||||||
|
uploadUrl: getMetadata(presentation.metadata.UploadURL)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -220,7 +222,7 @@
|
|||||||
element,
|
element,
|
||||||
editorProps: { attributes: mergeAttributes(defaultEditorAttributes, editorAttributes, { class: 'flex-grow' }) },
|
editorProps: { attributes: mergeAttributes(defaultEditorAttributes, editorAttributes, { class: 'flex-grow' }) },
|
||||||
extensions: [
|
extensions: [
|
||||||
...defaultExtensions,
|
EditorKit.configure({ history: false }),
|
||||||
...optionalExtensions,
|
...optionalExtensions,
|
||||||
Placeholder.configure({ placeholder: placeHolderStr }),
|
Placeholder.configure({ placeholder: placeHolderStr }),
|
||||||
InlineStyleToolbarExtension.configure({
|
InlineStyleToolbarExtension.configure({
|
||||||
@ -259,7 +261,7 @@
|
|||||||
dispatch('open-document', { event, _id, _class })
|
dispatch('open-document', { event, _id, _class })
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
EmojiExtension.configure(),
|
EmojiExtension,
|
||||||
...extensions
|
...extensions
|
||||||
],
|
],
|
||||||
parseOptions: {
|
parseOptions: {
|
||||||
|
@ -20,10 +20,13 @@
|
|||||||
import { DecorationSet } from '@tiptap/pm/view'
|
import { DecorationSet } from '@tiptap/pm/view'
|
||||||
import { onDestroy, onMount } from 'svelte'
|
import { onDestroy, onMount } from 'svelte'
|
||||||
import { Markup } from '@hcengineering/core'
|
import { Markup } from '@hcengineering/core'
|
||||||
|
import { getMetadata } from '@hcengineering/platform'
|
||||||
|
import presentation from '@hcengineering/presentation'
|
||||||
|
|
||||||
import { calculateDecorations, createMarkupDocument } from './diff/decorations'
|
import { calculateDecorations, createMarkupDocument } from './diff/decorations'
|
||||||
import { defaultEditorAttributes } from './editor/editorProps'
|
import { defaultEditorAttributes } from './editor/editorProps'
|
||||||
import { defaultExtensions } from './extensions'
|
import { ImageExtension } from './extension/imageExt'
|
||||||
|
import { EditorKit } from '../kits/editor-kit'
|
||||||
|
|
||||||
export let content: Markup
|
export let content: Markup
|
||||||
export let comparedVersion: Markup | undefined = undefined
|
export let comparedVersion: Markup | undefined = undefined
|
||||||
@ -78,7 +81,13 @@
|
|||||||
element,
|
element,
|
||||||
content,
|
content,
|
||||||
editable: false,
|
editable: false,
|
||||||
extensions: [...defaultExtensions, DecorationExtension],
|
extensions: [
|
||||||
|
EditorKit,
|
||||||
|
ImageExtension.configure({
|
||||||
|
uploadUrl: getMetadata(presentation.metadata.UploadURL)
|
||||||
|
}),
|
||||||
|
DecorationExtension
|
||||||
|
],
|
||||||
onTransaction: () => {
|
onTransaction: () => {
|
||||||
// force re-render so `editor.isActive` works as expected
|
// force re-render so `editor.isActive` works as expected
|
||||||
editor = editor
|
editor = editor
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { IntlString } from '@hcengineering/platform'
|
import { IntlString, getMetadata } from '@hcengineering/platform'
|
||||||
import presentation, { MessageViewer } from '@hcengineering/presentation'
|
import presentation, { MessageViewer } from '@hcengineering/presentation'
|
||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
@ -175,7 +175,8 @@
|
|||||||
attachFile,
|
attachFile,
|
||||||
reportNode: (id, node) => {
|
reportNode: (id, node) => {
|
||||||
attachments.set(id, node)
|
attachments.set(id, node)
|
||||||
}
|
},
|
||||||
|
uploadUrl: getMetadata(presentation.metadata.UploadURL)
|
||||||
})
|
})
|
||||||
|
|
||||||
const completionPlugin = Completion.configure({
|
const completionPlugin = Completion.configure({
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
import { InlinePopupExtension } from './extension/inlinePopup'
|
import { InlinePopupExtension } from './extension/inlinePopup'
|
||||||
import { InlineStyleToolbarExtension } from './extension/inlineStyleToolbar'
|
import { InlineStyleToolbarExtension } from './extension/inlineStyleToolbar'
|
||||||
import { SubmitExtension } from './extension/submit'
|
import { SubmitExtension } from './extension/submit'
|
||||||
import { defaultExtensions } from './extensions'
|
import { EditorKit } from '../kits/editor-kit'
|
||||||
|
|
||||||
export let content: string = ''
|
export let content: string = ''
|
||||||
export let placeholder: IntlString = textEditorPlugin.string.EditorPlaceholder
|
export let placeholder: IntlString = textEditorPlugin.string.EditorPlaceholder
|
||||||
@ -124,7 +124,7 @@
|
|||||||
editorProps: { attributes: mergeAttributes(defaultEditorAttributes, editorAttributes) },
|
editorProps: { attributes: mergeAttributes(defaultEditorAttributes, editorAttributes) },
|
||||||
content,
|
content,
|
||||||
extensions: [
|
extensions: [
|
||||||
...defaultExtensions,
|
EditorKit,
|
||||||
...(supportSubmit ? [Handle] : []), // order important
|
...(supportSubmit ? [Handle] : []), // order important
|
||||||
Placeholder.configure({ placeholder: placeHolderStr }),
|
Placeholder.configure({ placeholder: placeHolderStr }),
|
||||||
...extensions,
|
...extensions,
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
import { getMetadata } from '@hcengineering/platform'
|
import { PDFViewer } from '@hcengineering/presentation'
|
||||||
import presentation, { PDFViewer, getFileUrl } from '@hcengineering/presentation'
|
|
||||||
import { ImageNode, type ImageOptions as ImageNodeOptions } from '@hcengineering/text'
|
import { ImageNode, type ImageOptions as ImageNodeOptions } from '@hcengineering/text'
|
||||||
import { type IconSize, getIconSize2x, showPopup } from '@hcengineering/ui'
|
import { type IconSize, getIconSize2x, showPopup } from '@hcengineering/ui'
|
||||||
import { mergeAttributes, nodeInputRule } from '@tiptap/core'
|
import { mergeAttributes, nodeInputRule } from '@tiptap/core'
|
||||||
@ -37,6 +36,7 @@ export type ImageAlignment = 'center' | 'left' | 'right'
|
|||||||
export interface ImageOptions extends ImageNodeOptions {
|
export interface ImageOptions extends ImageNodeOptions {
|
||||||
attachFile?: FileAttachFunction
|
attachFile?: FileAttachFunction
|
||||||
reportNode?: (id: string, node: ProseMirrorNode) => void
|
reportNode?: (id: string, node: ProseMirrorNode) => void
|
||||||
|
uploadUrl: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ImageAlignmentOptions {
|
export interface ImageAlignmentOptions {
|
||||||
@ -80,6 +80,11 @@ function getType (type: string): 'image' | 'other' {
|
|||||||
return 'other'
|
return 'other'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is a simplified version of getFileUrl from presentation plugin, which we cannot use
|
||||||
|
function getFileUrl (fileId: string, size: IconSize = 'full', uploadUrl: string): string {
|
||||||
|
return `${uploadUrl}?file=${fileId}&size=${size as string}`
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
@ -87,7 +92,8 @@ export const ImageExtension = ImageNode.extend<ImageOptions>({
|
|||||||
addOptions () {
|
addOptions () {
|
||||||
return {
|
return {
|
||||||
inline: true,
|
inline: true,
|
||||||
HTMLAttributes: {}
|
HTMLAttributes: {},
|
||||||
|
uploadUrl: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -117,9 +123,11 @@ export const ImageExtension = ImageNode.extend<ImageOptions>({
|
|||||||
HTMLAttributes
|
HTMLAttributes
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const uploadUrl = this.options.uploadUrl ?? ''
|
||||||
|
|
||||||
const id = imgAttributes['file-id']
|
const id = imgAttributes['file-id']
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
imgAttributes.src = getFileUrl(id, 'full')
|
imgAttributes.src = getFileUrl(id, 'full', uploadUrl)
|
||||||
let width: IconSize | undefined
|
let width: IconSize | undefined
|
||||||
switch (imgAttributes.width) {
|
switch (imgAttributes.width) {
|
||||||
case '32px':
|
case '32px':
|
||||||
@ -137,8 +145,9 @@ export const ImageExtension = ImageNode.extend<ImageOptions>({
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (width !== undefined) {
|
if (width !== undefined) {
|
||||||
imgAttributes.src = getFileUrl(id, width)
|
imgAttributes.src = getFileUrl(id, width, uploadUrl)
|
||||||
imgAttributes.srcset = getFileUrl(id, width) + ' 1x,' + getFileUrl(id, getIconSize2x(width)) + ' 2x'
|
imgAttributes.srcset =
|
||||||
|
getFileUrl(id, width, uploadUrl) + ' 1x,' + getFileUrl(id, getIconSize2x(width), uploadUrl) + ' 2x'
|
||||||
}
|
}
|
||||||
imgAttributes.class = 'text-editor-image'
|
imgAttributes.class = 'text-editor-image'
|
||||||
imgAttributes.contentEditable = false
|
imgAttributes.contentEditable = false
|
||||||
@ -207,8 +216,7 @@ export const ImageExtension = ImageNode.extend<ImageOptions>({
|
|||||||
for (const uri of uris) {
|
for (const uri of uris) {
|
||||||
if (uri !== '') {
|
if (uri !== '') {
|
||||||
const url = new URL(uri)
|
const url = new URL(uri)
|
||||||
const uploadUrl = getMetadata(presentation.metadata.UploadURL)
|
if (opt.uploadUrl === undefined || !url.href.includes(opt.uploadUrl)) {
|
||||||
if (uploadUrl === undefined || !url.href.includes(uploadUrl)) {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,91 +1,23 @@
|
|||||||
import TableHeader from '@tiptap/extension-table-header'
|
//
|
||||||
|
// 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 TaskItem from '@tiptap/extension-task-item'
|
|
||||||
import TaskList from '@tiptap/extension-task-list'
|
|
||||||
|
|
||||||
import { type Level } from '@tiptap/extension-heading'
|
|
||||||
import Highlight from '@tiptap/extension-highlight'
|
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
|
||||||
import Underline from '@tiptap/extension-underline'
|
|
||||||
|
|
||||||
import Gapcursor from '@tiptap/extension-gapcursor'
|
|
||||||
import ListKeymap from '@tiptap/extension-list-keymap'
|
|
||||||
|
|
||||||
import { type AnyExtension } from '@tiptap/core'
|
|
||||||
import Link from '@tiptap/extension-link'
|
|
||||||
import Typography from '@tiptap/extension-typography'
|
|
||||||
import { type CompletionOptions } from '../Completion'
|
import { type CompletionOptions } from '../Completion'
|
||||||
import MentionList from './MentionList.svelte'
|
import MentionList from './MentionList.svelte'
|
||||||
import { NodeUuidExtension } from './extension/nodeUuid'
|
|
||||||
import { SvelteRenderer } from './node-view'
|
import { SvelteRenderer } from './node-view'
|
||||||
import { CodemarkExtension } from './extension/codemark'
|
|
||||||
import type { SuggestionKeyDownProps, SuggestionProps } from './extension/suggestion'
|
import type { SuggestionKeyDownProps, SuggestionProps } from './extension/suggestion'
|
||||||
|
|
||||||
import { Table, TableCell, TableRow } from './extension/table'
|
|
||||||
|
|
||||||
export const tableExtensions = [
|
|
||||||
Table.configure({
|
|
||||||
resizable: false,
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'proseTable'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
TableRow.configure({}),
|
|
||||||
TableHeader.configure({}),
|
|
||||||
TableCell.configure({})
|
|
||||||
]
|
|
||||||
|
|
||||||
export const taskListExtensions = [
|
|
||||||
TaskList,
|
|
||||||
TaskItem.configure({
|
|
||||||
nested: true,
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'flex flex-grow gap-1 checkbox_style'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
|
|
||||||
export const supportedHeadingLevels: Level[] = [1, 2, 3]
|
|
||||||
|
|
||||||
export const defaultExtensions: AnyExtension[] = [
|
|
||||||
StarterKit.configure({
|
|
||||||
code: {
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'proseCode'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
codeBlock: {
|
|
||||||
languageClassPrefix: 'language-',
|
|
||||||
exitOnArrowDown: true,
|
|
||||||
exitOnTripleEnter: true,
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'proseCodeBlock'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
heading: {
|
|
||||||
levels: supportedHeadingLevels,
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'proseHeading'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
CodemarkExtension,
|
|
||||||
Highlight.configure({
|
|
||||||
multicolor: false
|
|
||||||
}),
|
|
||||||
Underline.configure({}),
|
|
||||||
Typography.configure({}),
|
|
||||||
Gapcursor,
|
|
||||||
Link.configure({
|
|
||||||
openOnClick: true,
|
|
||||||
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
|
|
||||||
}),
|
|
||||||
ListKeymap.configure({}),
|
|
||||||
NodeUuidExtension,
|
|
||||||
...tableExtensions
|
|
||||||
// ...taskListExtensions // Disable since tasks are not working properly now.
|
|
||||||
]
|
|
||||||
|
|
||||||
export const mInsertTable = [
|
export const mInsertTable = [
|
||||||
{
|
{
|
||||||
label: '2x2',
|
label: '2x2',
|
||||||
|
63
packages/text-editor/src/kits/default-kit.ts
Normal file
63
packages/text-editor/src/kits/default-kit.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// 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 { Extension } from '@tiptap/core'
|
||||||
|
|
||||||
|
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 {
|
||||||
|
heading?: {
|
||||||
|
levels?: Level[]
|
||||||
|
}
|
||||||
|
history?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
heading: this.options.heading,
|
||||||
|
history: this.options.history
|
||||||
|
}),
|
||||||
|
Highlight.configure({
|
||||||
|
multicolor: false
|
||||||
|
}),
|
||||||
|
Typography.configure({}),
|
||||||
|
Link.configure({
|
||||||
|
openOnClick: true,
|
||||||
|
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
77
packages/text-editor/src/kits/editor-kit.ts
Normal file
77
packages/text-editor/src/kits/editor-kit.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// 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 { Extension } from '@tiptap/core'
|
||||||
|
import { type Level } from '@tiptap/extension-heading'
|
||||||
|
import ListKeymap from '@tiptap/extension-list-keymap'
|
||||||
|
import TableHeader from '@tiptap/extension-table-header'
|
||||||
|
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 { CodemarkExtension } from '../components/extension/codemark'
|
||||||
|
import { NodeUuidExtension } from '../components/extension/nodeUuid'
|
||||||
|
import { Table, TableCell, TableRow } from '../components/extension/table'
|
||||||
|
|
||||||
|
const headingLevels: Level[] = [1, 2, 3]
|
||||||
|
|
||||||
|
export const tableExtensions = [
|
||||||
|
Table.configure({
|
||||||
|
resizable: false,
|
||||||
|
HTMLAttributes: {
|
||||||
|
class: 'proseTable'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
TableRow.configure({}),
|
||||||
|
TableHeader.configure({}),
|
||||||
|
TableCell.configure({})
|
||||||
|
]
|
||||||
|
|
||||||
|
export const taskListExtensions = [
|
||||||
|
TaskList,
|
||||||
|
TaskItem.configure({
|
||||||
|
nested: true,
|
||||||
|
HTMLAttributes: {
|
||||||
|
class: 'flex flex-grow gap-1 checkbox_style'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
export interface EditorKitOptions extends DefaultKitOptions {
|
||||||
|
history?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EditorKit = Extension.create<EditorKitOptions>({
|
||||||
|
name: 'defaultKit',
|
||||||
|
|
||||||
|
addExtensions () {
|
||||||
|
return [
|
||||||
|
DefaultKit.configure({
|
||||||
|
...this.options,
|
||||||
|
heading: {
|
||||||
|
levels: headingLevels
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
CodemarkExtension,
|
||||||
|
Underline,
|
||||||
|
ListKeymap,
|
||||||
|
NodeUuidExtension,
|
||||||
|
...tableExtensions
|
||||||
|
// ...taskListExtensions // Disable since tasks are not working properly now.
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
@ -37,6 +37,7 @@
|
|||||||
"@tiptap/extension-gapcursor": "^2.1.12",
|
"@tiptap/extension-gapcursor": "^2.1.12",
|
||||||
"@tiptap/extension-heading": "^2.1.12",
|
"@tiptap/extension-heading": "^2.1.12",
|
||||||
"@tiptap/extension-highlight": "^2.1.12",
|
"@tiptap/extension-highlight": "^2.1.12",
|
||||||
|
"@tiptap/extension-history": "^2.1.12",
|
||||||
"@tiptap/extension-link": "^2.1.12",
|
"@tiptap/extension-link": "^2.1.12",
|
||||||
"@tiptap/extension-mention": "^2.1.12",
|
"@tiptap/extension-mention": "^2.1.12",
|
||||||
"@tiptap/extension-table": "^2.1.12",
|
"@tiptap/extension-table": "^2.1.12",
|
||||||
|
@ -1,106 +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 { AnyExtension } from '@tiptap/core'
|
|
||||||
import { Level } from '@tiptap/extension-heading'
|
|
||||||
import Highlight from '@tiptap/extension-highlight'
|
|
||||||
import Link from '@tiptap/extension-link'
|
|
||||||
import Table from '@tiptap/extension-table'
|
|
||||||
import TableCell from '@tiptap/extension-table-cell'
|
|
||||||
import TableHeader from '@tiptap/extension-table-header'
|
|
||||||
import TableRow from '@tiptap/extension-table-row'
|
|
||||||
import TaskItem from '@tiptap/extension-task-item'
|
|
||||||
import TaskList from '@tiptap/extension-task-list'
|
|
||||||
import Typography from '@tiptap/extension-typography'
|
|
||||||
import StarterKit from '@tiptap/starter-kit'
|
|
||||||
import { ImageNode, ReferenceNode, TodoItemNode, TodoListNode } from './nodes'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export const headingLevels: Level[] = [1, 2, 3, 4, 5, 6]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export const tableExtensions = [
|
|
||||||
Table.configure({
|
|
||||||
resizable: false,
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'proseTable'
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
TableRow.configure({}),
|
|
||||||
TableHeader.configure({}),
|
|
||||||
TableCell.configure({})
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export const taskListExtensions = [
|
|
||||||
TaskList,
|
|
||||||
TaskItem.configure({
|
|
||||||
nested: true,
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'flex flex-grow gap-1 checkbox_style'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export const defaultExtensions: AnyExtension[] = [
|
|
||||||
StarterKit.configure({
|
|
||||||
code: {
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'proseCode'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
codeBlock: {
|
|
||||||
languageClassPrefix: 'language-',
|
|
||||||
exitOnArrowDown: true,
|
|
||||||
exitOnTripleEnter: true,
|
|
||||||
HTMLAttributes: {
|
|
||||||
class: 'proseCodeBlock'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
heading: {
|
|
||||||
levels: headingLevels
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
Highlight.configure({
|
|
||||||
multicolor: false
|
|
||||||
}),
|
|
||||||
Typography.configure({}),
|
|
||||||
Link.configure({
|
|
||||||
openOnClick: true,
|
|
||||||
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
|
|
||||||
}),
|
|
||||||
...tableExtensions,
|
|
||||||
...taskListExtensions
|
|
||||||
]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export const serverExtensions: AnyExtension[] = [
|
|
||||||
...defaultExtensions,
|
|
||||||
ImageNode,
|
|
||||||
ReferenceNode,
|
|
||||||
TodoItemNode,
|
|
||||||
TodoListNode
|
|
||||||
]
|
|
@ -17,7 +17,10 @@ import { Extensions, getSchema } from '@tiptap/core'
|
|||||||
import { generateJSON, generateHTML } from '@tiptap/html'
|
import { generateJSON, generateHTML } from '@tiptap/html'
|
||||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||||
|
|
||||||
import { defaultExtensions } from './extensions'
|
import { ServerKit } from './kits/server-kit'
|
||||||
|
|
||||||
|
const defaultExtensions = [ServerKit]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
@ -13,8 +13,10 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
export * from './extensions'
|
|
||||||
export * from './html'
|
export * from './html'
|
||||||
export * from './node'
|
export * from './node'
|
||||||
export * from './nodes'
|
export * from './nodes'
|
||||||
export * from './text'
|
export * from './text'
|
||||||
|
|
||||||
|
export * from './kits/default-kit'
|
||||||
|
export * from './kits/server-kit'
|
||||||
|
63
packages/text/src/kits/default-kit.ts
Normal file
63
packages/text/src/kits/default-kit.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
//
|
||||||
|
// 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 { Extension } from '@tiptap/core'
|
||||||
|
|
||||||
|
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'
|
||||||
|
|
||||||
|
export interface DefaultKitOptions {
|
||||||
|
heading?: {
|
||||||
|
levels?: Level[]
|
||||||
|
}
|
||||||
|
history?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
heading: this.options.heading,
|
||||||
|
history: this.options.history
|
||||||
|
}),
|
||||||
|
Highlight.configure({
|
||||||
|
multicolor: false
|
||||||
|
}),
|
||||||
|
Typography.configure({}),
|
||||||
|
Link.configure({
|
||||||
|
openOnClick: true,
|
||||||
|
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }
|
||||||
|
})
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
78
packages/text/src/kits/server-kit.ts
Normal file
78
packages/text/src/kits/server-kit.ts
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
//
|
||||||
|
// 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 { Extension } from '@tiptap/core'
|
||||||
|
import Table from '@tiptap/extension-table'
|
||||||
|
import TableCell from '@tiptap/extension-table-cell'
|
||||||
|
import TableHeader from '@tiptap/extension-table-header'
|
||||||
|
import TableRow from '@tiptap/extension-table-row'
|
||||||
|
import TaskItem from '@tiptap/extension-task-item'
|
||||||
|
import TaskList from '@tiptap/extension-task-list'
|
||||||
|
|
||||||
|
import { ImageNode, ImageOptions } from '../nodes/image'
|
||||||
|
import { ReferenceNode } from '../nodes/reference'
|
||||||
|
import { TodoItemNode, TodoListNode } from '../nodes/todo'
|
||||||
|
|
||||||
|
import { DefaultKit, DefaultKitOptions } from './default-kit'
|
||||||
|
import { Level } from '@tiptap/extension-heading'
|
||||||
|
|
||||||
|
const headingLevels: Level[] = [1, 2, 3, 4, 5, 6]
|
||||||
|
|
||||||
|
const tableExtensions = [
|
||||||
|
Table.configure({
|
||||||
|
resizable: false,
|
||||||
|
HTMLAttributes: {
|
||||||
|
class: 'proseTable'
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
TableRow.configure({}),
|
||||||
|
TableHeader.configure({}),
|
||||||
|
TableCell.configure({})
|
||||||
|
]
|
||||||
|
|
||||||
|
const taskListExtensions = [
|
||||||
|
TaskList,
|
||||||
|
TaskItem.configure({
|
||||||
|
nested: true,
|
||||||
|
HTMLAttributes: {
|
||||||
|
class: 'flex flex-grow gap-1 checkbox_style'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
|
export interface ServerKitOptions extends DefaultKitOptions {
|
||||||
|
image: Partial<ImageOptions>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ServerKit = Extension.create<ServerKitOptions>({
|
||||||
|
name: 'serverKit',
|
||||||
|
|
||||||
|
addExtensions () {
|
||||||
|
return [
|
||||||
|
DefaultKit.configure({
|
||||||
|
...this.options,
|
||||||
|
heading: {
|
||||||
|
levels: headingLevels
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
...tableExtensions,
|
||||||
|
...taskListExtensions,
|
||||||
|
ImageNode.configure(this.options.image),
|
||||||
|
TodoItemNode,
|
||||||
|
TodoListNode,
|
||||||
|
ReferenceNode
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
@ -21,6 +21,12 @@ import { getDataAttribute } from './utils'
|
|||||||
export interface ImageOptions {
|
export interface ImageOptions {
|
||||||
inline: boolean
|
inline: boolean
|
||||||
HTMLAttributes: Record<string, any>
|
HTMLAttributes: Record<string, any>
|
||||||
|
uploadUrl?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is a simplified version of getFileUrl from presentation plugin, which we cannot use
|
||||||
|
function getFileUrl (uploadUrl: string, fileId: string, size: string = 'full'): string {
|
||||||
|
return `${uploadUrl}?file=${fileId}&size=${size}`
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +38,8 @@ export const ImageNode = Node.create<ImageOptions>({
|
|||||||
addOptions () {
|
addOptions () {
|
||||||
return {
|
return {
|
||||||
inline: true,
|
inline: true,
|
||||||
HTMLAttributes: {}
|
HTMLAttributes: {},
|
||||||
|
uploadUrl: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -98,6 +105,12 @@ export const ImageNode = Node.create<ImageOptions>({
|
|||||||
HTMLAttributes
|
HTMLAttributes
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const fileId = imgAttributes['file-id']
|
||||||
|
if (fileId != null) {
|
||||||
|
const uploadUrl = this.options.uploadUrl ?? ''
|
||||||
|
imgAttributes.src = getFileUrl(uploadUrl, fileId)
|
||||||
|
}
|
||||||
|
|
||||||
return ['div', divAttributes, ['img', imgAttributes]]
|
return ['div', divAttributes, ['img', imgAttributes]]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
|
|
||||||
import chunter, { Backlink } from '@hcengineering/chunter'
|
import chunter, { Backlink } from '@hcengineering/chunter'
|
||||||
import { Class, Data, Doc, Ref, Tx, TxFactory } from '@hcengineering/core'
|
import { Class, Data, Doc, Ref, Tx, TxFactory } from '@hcengineering/core'
|
||||||
import { extractReferences, getHTML, parseHTML, serverExtensions } from '@hcengineering/text'
|
import { ServerKit, extractReferences, getHTML, parseHTML } from '@hcengineering/text'
|
||||||
|
|
||||||
const extensions = serverExtensions
|
const extensions = [ServerKit]
|
||||||
|
|
||||||
export function getBacklinks (
|
export function getBacklinks (
|
||||||
backlinkId: Ref<Doc>,
|
backlinkId: Ref<Doc>,
|
||||||
|
@ -26,6 +26,7 @@ export interface Config {
|
|||||||
|
|
||||||
TransactorUrl: string
|
TransactorUrl: string
|
||||||
MongoUrl: string
|
MongoUrl: string
|
||||||
|
UploadUrl: string
|
||||||
|
|
||||||
MinioEndpoint: string
|
MinioEndpoint: string
|
||||||
MinioAccessKey: string
|
MinioAccessKey: string
|
||||||
@ -39,6 +40,7 @@ const envMap: { [key in keyof Config]: string } = {
|
|||||||
Port: 'COLLABORATOR_PORT',
|
Port: 'COLLABORATOR_PORT',
|
||||||
TransactorUrl: 'TRANSACTOR_URL',
|
TransactorUrl: 'TRANSACTOR_URL',
|
||||||
MongoUrl: 'MONGO_URL',
|
MongoUrl: 'MONGO_URL',
|
||||||
|
UploadUrl: 'UPLOAD_URL',
|
||||||
MinioEndpoint: 'MINIO_ENDPOINT',
|
MinioEndpoint: 'MINIO_ENDPOINT',
|
||||||
MinioAccessKey: 'MINIO_ACCESS_KEY',
|
MinioAccessKey: 'MINIO_ACCESS_KEY',
|
||||||
MinioSecretKey: 'MINIO_SECRET_KEY'
|
MinioSecretKey: 'MINIO_SECRET_KEY'
|
||||||
@ -63,6 +65,7 @@ const config: Config = (() => {
|
|||||||
Port: parseInt(process.env[envMap.Port] ?? '3078'),
|
Port: parseInt(process.env[envMap.Port] ?? '3078'),
|
||||||
TransactorUrl: process.env[envMap.TransactorUrl],
|
TransactorUrl: process.env[envMap.TransactorUrl],
|
||||||
MongoUrl: process.env[envMap.MongoUrl],
|
MongoUrl: process.env[envMap.MongoUrl],
|
||||||
|
UploadUrl: process.env[envMap.UploadUrl] ?? '/files',
|
||||||
MinioEndpoint: process.env[envMap.MinioEndpoint],
|
MinioEndpoint: process.env[envMap.MinioEndpoint],
|
||||||
MinioAccessKey: process.env[envMap.MinioAccessKey],
|
MinioAccessKey: process.env[envMap.MinioAccessKey],
|
||||||
MinioSecretKey: process.env[envMap.MinioSecretKey]
|
MinioSecretKey: process.env[envMap.MinioSecretKey]
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
import { MeasureContext } from '@hcengineering/core'
|
import { MeasureContext } from '@hcengineering/core'
|
||||||
import { MinioService } from '@hcengineering/minio'
|
import { MinioService } from '@hcengineering/minio'
|
||||||
import { serverExtensions } from '@hcengineering/text'
|
import { ServerKit } from '@hcengineering/text'
|
||||||
import { Hocuspocus, onAuthenticatePayload } from '@hocuspocus/server'
|
import { Hocuspocus, onAuthenticatePayload } from '@hocuspocus/server'
|
||||||
import bp from 'body-parser'
|
import bp from 'body-parser'
|
||||||
import compression from 'compression'
|
import compression from 'compression'
|
||||||
@ -72,6 +72,14 @@ export async function start (
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const extensions = [
|
||||||
|
ServerKit.configure({
|
||||||
|
image: {
|
||||||
|
uploadUrl: config.UploadUrl
|
||||||
|
}
|
||||||
|
})
|
||||||
|
]
|
||||||
|
|
||||||
const extensionsCtx = ctx.newChild('extensions', {})
|
const extensionsCtx = ctx.newChild('extensions', {})
|
||||||
const storageCtx = ctx.newChild('storage', {})
|
const storageCtx = ctx.newChild('storage', {})
|
||||||
|
|
||||||
@ -111,7 +119,7 @@ export async function start (
|
|||||||
extensions: [
|
extensions: [
|
||||||
new ActionsExtension({
|
new ActionsExtension({
|
||||||
ctx: extensionsCtx.newChild('actions', {}),
|
ctx: extensionsCtx.newChild('actions', {}),
|
||||||
transformer: new HtmlTransformer(serverExtensions)
|
transformer: new HtmlTransformer(extensions)
|
||||||
}),
|
}),
|
||||||
new StorageExtension({
|
new StorageExtension({
|
||||||
ctx: extensionsCtx.newChild('storage', {}),
|
ctx: extensionsCtx.newChild('storage', {}),
|
||||||
@ -121,12 +129,12 @@ export async function start (
|
|||||||
mongodb: new MongodbStorageAdapter(
|
mongodb: new MongodbStorageAdapter(
|
||||||
storageCtx.newChild('mongodb', {}),
|
storageCtx.newChild('mongodb', {}),
|
||||||
mongo,
|
mongo,
|
||||||
new HtmlTransformer(serverExtensions)
|
new HtmlTransformer(extensions)
|
||||||
),
|
),
|
||||||
platform: new PlatformStorageAdapter(
|
platform: new PlatformStorageAdapter(
|
||||||
storageCtx.newChild('platform', {}),
|
storageCtx.newChild('platform', {}),
|
||||||
config.TransactorUrl,
|
config.TransactorUrl,
|
||||||
new HtmlTransformer(serverExtensions)
|
new HtmlTransformer(extensions)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
'minio'
|
'minio'
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { MeasureContext, WorkspaceId } from '@hcengineering/core'
|
import { MeasureContext, WorkspaceId } from '@hcengineering/core'
|
||||||
import { ContentTextAdapter } from '@hcengineering/server-core'
|
import { ContentTextAdapter } from '@hcengineering/server-core'
|
||||||
import { getText, serverExtensions, yDocContentToNodes } from '@hcengineering/text'
|
import { ServerKit, getText, yDocContentToNodes } from '@hcengineering/text'
|
||||||
import { Readable } from 'stream'
|
import { Readable } from 'stream'
|
||||||
|
|
||||||
const extensions = serverExtensions
|
const extensions = [ServerKit]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
|
@ -111,6 +111,7 @@ services:
|
|||||||
- COLLABORATOR_PORT=3078
|
- COLLABORATOR_PORT=3078
|
||||||
- SECRET=secret
|
- SECRET=secret
|
||||||
- TRANSACTOR_URL=ws://localhost:3334
|
- TRANSACTOR_URL=ws://localhost:3334
|
||||||
|
- UPLOAD_URL=/files
|
||||||
- MONGO_URL=mongodb://mongodb:27018
|
- MONGO_URL=mongodb://mongodb:27018
|
||||||
- MINIO_ENDPOINT=minio
|
- MINIO_ENDPOINT=minio
|
||||||
- MINIO_ACCESS_KEY=minioadmin
|
- MINIO_ACCESS_KEY=minioadmin
|
||||||
|
Loading…
Reference in New Issue
Block a user