mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-29 19:56:18 +00:00
UBERF-8969 Rewrite extractReferences to use JSON only (#7506)
This commit is contained in:
parent
5bd3424c9b
commit
63464cbc54
@ -16,6 +16,7 @@
|
||||
export * from './extensions'
|
||||
export * from './markup/dsl'
|
||||
export * from './markup/model'
|
||||
export * from './markup/reference'
|
||||
export * from './markup/traverse'
|
||||
export * from './markup/utils'
|
||||
export * from './nodes'
|
||||
|
@ -17,8 +17,8 @@ describe('traverseNode', () => {
|
||||
traverseNode(node as MarkupNode, callback)
|
||||
|
||||
expect(callback).toHaveBeenCalledTimes(2)
|
||||
expect(callback).toHaveBeenCalledWith(node)
|
||||
expect(callback).toHaveBeenCalledWith(node.content[0])
|
||||
expect(callback).toHaveBeenCalledWith(node, undefined)
|
||||
expect(callback).toHaveBeenCalledWith(node.content[0], node)
|
||||
})
|
||||
|
||||
it('should stop traversing if the callback returns false', () => {
|
||||
@ -40,7 +40,7 @@ describe('traverseNode', () => {
|
||||
traverseNode(node, callback)
|
||||
|
||||
expect(callback).toHaveBeenCalledTimes(1)
|
||||
expect(callback).toHaveBeenCalledWith(node)
|
||||
expect(callback).toHaveBeenCalledWith(node, undefined)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -84,6 +84,7 @@ export interface LinkMark extends MarkupMark {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface ReferenceMark extends MarkupMark {
|
||||
export interface ReferenceMarkupNode extends MarkupNode {
|
||||
type: MarkupNodeType.reference
|
||||
attrs: { id: string, label: string, objectclass: string }
|
||||
}
|
||||
|
49
packages/text/src/markup/reference.ts
Normal file
49
packages/text/src/markup/reference.ts
Normal file
@ -0,0 +1,49 @@
|
||||
//
|
||||
// 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 { Class, Doc, Ref } from '@hcengineering/core'
|
||||
import { MarkupNode, MarkupNodeType, ReferenceMarkupNode } from '../markup/model'
|
||||
import { traverseNode } from '../markup/traverse'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Reference {
|
||||
objectId: Ref<Doc>
|
||||
objectClass: Ref<Class<Doc>>
|
||||
parentNode: MarkupNode | null
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function extractReferences (content: MarkupNode): Array<Reference> {
|
||||
const result: Array<Reference> = []
|
||||
|
||||
traverseNode(content, (node, parent) => {
|
||||
if (node.type === MarkupNodeType.reference) {
|
||||
const reference = node as ReferenceMarkupNode
|
||||
const objectId = reference.attrs.id as Ref<Doc>
|
||||
const objectClass = reference.attrs.objectclass as Ref<Class<Doc>>
|
||||
const e = result.find((e) => e.objectId === objectId && e.objectClass === objectClass)
|
||||
if (e === undefined) {
|
||||
result.push({ objectId, objectClass, parentNode: parent ?? node })
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
@ -15,11 +15,22 @@
|
||||
|
||||
import { MarkupMark, MarkupNode } from './model'
|
||||
|
||||
export function traverseNode (node: MarkupNode, f: (el: MarkupNode) => boolean | undefined): void {
|
||||
const result = f(node)
|
||||
export function traverseNode (
|
||||
node: MarkupNode,
|
||||
fn: (el: MarkupNode, parent: MarkupNode | undefined) => boolean | undefined
|
||||
): void {
|
||||
_traverseNode(node, undefined, fn)
|
||||
}
|
||||
|
||||
function _traverseNode (
|
||||
node: MarkupNode,
|
||||
parent: MarkupNode | undefined,
|
||||
fn: (el: MarkupNode, parent: MarkupNode | undefined) => boolean | undefined
|
||||
): void {
|
||||
const result = fn(node, parent)
|
||||
if (result !== false) {
|
||||
node.content?.forEach((p) => {
|
||||
traverseNode(p, f)
|
||||
_traverseNode(p, node, fn)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,6 @@
|
||||
//
|
||||
|
||||
import { Node } from '@tiptap/core'
|
||||
import { Node as ProseMirrorNode } from '@tiptap/pm/model'
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export interface Comment {
|
||||
parentNode: ProseMirrorNode | null
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
|
@ -13,42 +13,9 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
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
|
||||
*/
|
||||
export interface Reference {
|
||||
objectId: Ref<Doc>
|
||||
objectClass: Ref<Class<Doc>>
|
||||
parentNode: ProseMirrorNode | null
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function extractReferences (content: ProseMirrorNode): Array<Reference> {
|
||||
const result: Array<Reference> = []
|
||||
|
||||
content.descendants((node, _pos, parent): boolean => {
|
||||
if (node.type.name === ReferenceNode.name) {
|
||||
const objectId = node.attrs.id as Ref<Doc>
|
||||
const objectClass = node.attrs.objectclass as Ref<Class<Doc>>
|
||||
const e = result.find((e) => e.objectId === objectId && e.objectClass === objectClass)
|
||||
if (e === undefined) {
|
||||
result.push({ objectId, objectClass, parentNode: parent })
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export interface ReferenceOptions {
|
||||
renderLabel: (props: { options: ReferenceOptions, node: any }) => string
|
||||
suggestion: { char: string }
|
||||
|
@ -73,7 +73,7 @@ describe('extractBacklinks', () => {
|
||||
srcDocId: 'srcDocId',
|
||||
srcDocClass: 'srcDocClass',
|
||||
message:
|
||||
'{"type":"paragraph","content":[{"type":"reference","attrs":{"id":"id","objectclass":"contact:class:Person","label":"Appleseed John","class":null}},{"type":"text","text":" hello"}]}',
|
||||
'{"type":"paragraph","content":[{"type":"reference","attrs":{"id":"id","objectclass":"contact:class:Person","label":"Appleseed John"}},{"type":"text","text":" hello"}]}',
|
||||
attachedDocId: 'attachedDocId',
|
||||
attachedDocClass: 'attachedDocClass'
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import core, {
|
||||
Doc,
|
||||
generateId,
|
||||
Hierarchy,
|
||||
Markup,
|
||||
Ref,
|
||||
Space,
|
||||
Tx,
|
||||
@ -50,12 +51,12 @@ import {
|
||||
toReceiverInfo,
|
||||
type NotificationProviderControl
|
||||
} from '@hcengineering/server-notification-resources'
|
||||
import { areEqualJson, extractReferences, markupToPmNode, pmNodeToMarkup } from '@hcengineering/text'
|
||||
import { areEqualJson, extractReferences, jsonToMarkup, markupToJSON } from '@hcengineering/text'
|
||||
|
||||
export function isDocMentioned (doc: Ref<Doc>, content: string): boolean {
|
||||
const references = []
|
||||
|
||||
const node = markupToPmNode(content)
|
||||
const node = markupToJSON(content)
|
||||
references.push(...extractReferences(node))
|
||||
|
||||
for (const ref of references) {
|
||||
@ -491,13 +492,13 @@ export function getReferencesData (
|
||||
srcDocClass: Ref<Class<Doc>>,
|
||||
attachedDocId: Ref<Doc> | undefined,
|
||||
attachedDocClass: Ref<Class<Doc>> | undefined,
|
||||
content: string
|
||||
content: Markup
|
||||
): Array<Data<ActivityReference>> {
|
||||
const result: Array<Data<ActivityReference>> = []
|
||||
const references = []
|
||||
|
||||
const doc = markupToPmNode(content)
|
||||
references.push(...extractReferences(doc))
|
||||
const node = markupToJSON(content)
|
||||
references.push(...extractReferences(node))
|
||||
|
||||
for (const ref of references) {
|
||||
if (ref.objectId !== attachedDocId && ref.objectId !== srcDocId) {
|
||||
@ -507,7 +508,7 @@ export function getReferencesData (
|
||||
collection: 'references',
|
||||
srcDocId,
|
||||
srcDocClass,
|
||||
message: ref.parentNode !== null ? pmNodeToMarkup(ref.parentNode) : '',
|
||||
message: ref.parentNode !== null ? jsonToMarkup(ref.parentNode) : '',
|
||||
attachedDocId,
|
||||
attachedDocClass
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user