mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-26 04:23:58 +03:00
UBER-1120 Fix backlinks creation for wiki documents (#3896)
Signed-off-by: Alexander Onnikov <alexander.onnikov@xored.com>
This commit is contained in:
parent
16d3ef147a
commit
d7c1790d8c
@ -475,6 +475,5 @@
|
||||
|
||||
.text-input {
|
||||
font-size: 0.9375rem;
|
||||
padding-bottom: 30vh;
|
||||
}
|
||||
</style>
|
||||
|
@ -14,12 +14,12 @@
|
||||
//
|
||||
import { getMetadata } from '@hcengineering/platform'
|
||||
import presentation, { PDFViewer, getFileUrl } from '@hcengineering/presentation'
|
||||
import { ImageNode, ImageOptions as ImageNodeOptions } from '@hcengineering/text'
|
||||
import { IconSize, getIconSize2x, showPopup } from '@hcengineering/ui'
|
||||
import { Node, mergeAttributes, nodeInputRule } from '@tiptap/core'
|
||||
import { mergeAttributes, nodeInputRule } from '@tiptap/core'
|
||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
import { Plugin, PluginKey } from '@tiptap/pm/state'
|
||||
import { EditorView } from '@tiptap/pm/view'
|
||||
import { getDataAttribute } from '../../utils'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -34,12 +34,8 @@ export type ImageAlignment = 'center' | 'left' | 'right'
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ImageOptions {
|
||||
inline: boolean
|
||||
HTMLAttributes: Record<string, any>
|
||||
|
||||
export interface ImageOptions extends ImageNodeOptions {
|
||||
attachFile?: FileAttachFunction
|
||||
|
||||
reportNode?: (id: string, node: ProseMirrorNode) => void
|
||||
}
|
||||
|
||||
@ -87,9 +83,7 @@ function getType (type: string): 'image' | 'other' {
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const ImageExtension = Node.create<ImageOptions>({
|
||||
name: 'image',
|
||||
|
||||
export const ImageExtension = ImageNode.extend<ImageOptions>({
|
||||
addOptions () {
|
||||
return {
|
||||
inline: true,
|
||||
@ -97,42 +91,6 @@ export const ImageExtension = Node.create<ImageOptions>({
|
||||
}
|
||||
},
|
||||
|
||||
inline () {
|
||||
return this.options.inline
|
||||
},
|
||||
|
||||
group () {
|
||||
return this.options.inline ? 'inline' : 'block'
|
||||
},
|
||||
|
||||
draggable: true,
|
||||
|
||||
selectable: true,
|
||||
|
||||
addAttributes () {
|
||||
return {
|
||||
'file-id': {
|
||||
default: null
|
||||
},
|
||||
width: {
|
||||
default: null
|
||||
},
|
||||
height: {
|
||||
default: null
|
||||
},
|
||||
src: {
|
||||
default: null
|
||||
},
|
||||
alt: {
|
||||
default: null
|
||||
},
|
||||
title: {
|
||||
default: null
|
||||
},
|
||||
align: getDataAttribute('align')
|
||||
}
|
||||
},
|
||||
|
||||
parseHTML () {
|
||||
return [
|
||||
{
|
||||
|
@ -25,6 +25,7 @@ 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 } from './nodes'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -92,3 +93,8 @@ export const defaultExtensions: AnyExtension[] = [
|
||||
...tableExtensions,
|
||||
...taskListExtensions
|
||||
]
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const serverExtensions: AnyExtension[] = [...defaultExtensions, ImageNode, ReferenceNode]
|
||||
|
103
packages/text/src/nodes/image.ts
Normal file
103
packages/text/src/nodes/image.ts
Normal file
@ -0,0 +1,103 @@
|
||||
//
|
||||
// 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 { Node, mergeAttributes } from '@tiptap/core'
|
||||
import { getDataAttribute } from './utils'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface ImageOptions {
|
||||
inline: boolean
|
||||
HTMLAttributes: Record<string, any>
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export const ImageNode = Node.create<ImageOptions>({
|
||||
name: 'image',
|
||||
|
||||
addOptions () {
|
||||
return {
|
||||
inline: true,
|
||||
HTMLAttributes: {}
|
||||
}
|
||||
},
|
||||
|
||||
inline () {
|
||||
return this.options.inline
|
||||
},
|
||||
|
||||
group () {
|
||||
return this.options.inline ? 'inline' : 'block'
|
||||
},
|
||||
|
||||
draggable: true,
|
||||
|
||||
selectable: true,
|
||||
|
||||
addAttributes () {
|
||||
return {
|
||||
'file-id': {
|
||||
default: null
|
||||
},
|
||||
width: {
|
||||
default: null
|
||||
},
|
||||
height: {
|
||||
default: null
|
||||
},
|
||||
src: {
|
||||
default: null
|
||||
},
|
||||
alt: {
|
||||
default: null
|
||||
},
|
||||
title: {
|
||||
default: null
|
||||
},
|
||||
align: getDataAttribute('align')
|
||||
}
|
||||
},
|
||||
|
||||
parseHTML () {
|
||||
return [
|
||||
{
|
||||
tag: `img[data-type="${this.name}"]`
|
||||
},
|
||||
{
|
||||
tag: 'img[src]'
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
renderHTML ({ node, HTMLAttributes }) {
|
||||
const divAttributes = {
|
||||
class: 'text-editor-image-container',
|
||||
'data-type': this.name,
|
||||
'data-align': node.attrs.align
|
||||
}
|
||||
|
||||
const imgAttributes = mergeAttributes(
|
||||
{
|
||||
'data-type': this.name
|
||||
},
|
||||
this.options.HTMLAttributes,
|
||||
HTMLAttributes
|
||||
)
|
||||
|
||||
return ['div', divAttributes, ['img', imgAttributes]]
|
||||
}
|
||||
})
|
@ -13,4 +13,6 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
export * from './image'
|
||||
export * from './reference'
|
||||
export { getDataAttribute } from './utils'
|
||||
|
@ -16,6 +16,7 @@
|
||||
import { Class, Doc, Ref } from '@hcengineering/core'
|
||||
import { Node, mergeAttributes } from '@tiptap/core'
|
||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
import { getDataAttribute } from './utils'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@ -59,47 +60,11 @@ export const ReferenceNode = Node.create({
|
||||
|
||||
addAttributes () {
|
||||
return {
|
||||
id: {
|
||||
default: null,
|
||||
parseHTML: (element) => element.getAttribute('data-id'),
|
||||
renderHTML: (attributes) => {
|
||||
if (attributes.id === null) {
|
||||
return {}
|
||||
}
|
||||
id: getDataAttribute('id'),
|
||||
|
||||
return {
|
||||
'data-id': attributes.id
|
||||
}
|
||||
}
|
||||
},
|
||||
objectclass: getDataAttribute('objectclass'),
|
||||
|
||||
objectclass: {
|
||||
default: null,
|
||||
parseHTML: (element) => element.getAttribute('data-objectclass'),
|
||||
renderHTML: (attributes) => {
|
||||
if (attributes.objectclass === null) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
'data-objectclass': attributes.objectclass
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
label: {
|
||||
default: null,
|
||||
parseHTML: (element) => element.getAttribute('data-label'),
|
||||
renderHTML: (attributes) => {
|
||||
if (attributes.label === null) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
'data-label': attributes.label
|
||||
}
|
||||
}
|
||||
},
|
||||
label: getDataAttribute('label'),
|
||||
|
||||
class: {
|
||||
default: null
|
||||
|
38
packages/text/src/nodes/utils.ts
Normal file
38
packages/text/src/nodes/utils.ts
Normal file
@ -0,0 +1,38 @@
|
||||
//
|
||||
// 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 { Attribute } from '@tiptap/core'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function getDataAttribute (name: string, def?: unknown | null): Partial<Attribute> {
|
||||
const dataName = `data-${name}`
|
||||
|
||||
return {
|
||||
default: def,
|
||||
parseHTML: (element) => element.getAttribute(dataName),
|
||||
renderHTML: (attributes) => {
|
||||
// eslint-disable-next-line
|
||||
if (!attributes[name]) {
|
||||
return {}
|
||||
}
|
||||
|
||||
return {
|
||||
[dataName]: attributes[name]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -54,13 +54,13 @@ export function openPanel (
|
||||
}
|
||||
|
||||
export function closePanel (shoulRedirect: boolean = true): void {
|
||||
currentLocation = undefined
|
||||
panelstore.update(() => {
|
||||
return { panel: undefined }
|
||||
})
|
||||
if (shoulRedirect) {
|
||||
const loc = getLocation()
|
||||
loc.fragment = undefined
|
||||
currentLocation = undefined
|
||||
navigate(loc)
|
||||
}
|
||||
}
|
||||
|
@ -15,9 +15,9 @@
|
||||
|
||||
import chunter, { Backlink } from '@hcengineering/chunter'
|
||||
import { Class, Data, Doc, Ref, Tx, TxFactory } from '@hcengineering/core'
|
||||
import { defaultExtensions, extractReferences, getHTML, parseHTML, ReferenceNode } from '@hcengineering/text'
|
||||
import { extractReferences, getHTML, parseHTML, serverExtensions } from '@hcengineering/text'
|
||||
|
||||
const extensions = [...defaultExtensions, ReferenceNode]
|
||||
const extensions = serverExtensions
|
||||
|
||||
export function getBacklinks (
|
||||
backlinkId: Ref<Doc>,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { MeasureContext, WorkspaceId } from '@hcengineering/core'
|
||||
import { ContentTextAdapter } from '@hcengineering/server-core'
|
||||
import { ReferenceNode, defaultExtensions, getText, yDocContentToNodes } from '@hcengineering/text'
|
||||
import { getText, serverExtensions, yDocContentToNodes } from '@hcengineering/text'
|
||||
import { Readable } from 'stream'
|
||||
|
||||
const extensions = [...defaultExtensions, ReferenceNode]
|
||||
const extensions = serverExtensions
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
Loading…
Reference in New Issue
Block a user