9c334b5f03
This PR fixes an issue where links added inside a note were not
appearing in the preview shown under Company -> Notes. The link would
only appear after opening the note, which led to inconsistent behavior.
Issue:
Blocknote represents text and links using different node types:
1. { "type": "text", "text": "Welcome to this demo!" }
2. {
"type": "link",
"content": { "type": "text", "text": "Example" },
"href": "https://example.com"
}
The existing preview function only handled plain text nodes and
completely ignored link nodes.
As a result:
- Links did not appear in the preview
- Links appeared only inside the full note view
Steps to Reproduce:
- Add a link inside a note
- Go to Company / People and view the note preview -> the link is
missing
- Open the note -> the link appears correctly
How I fixed it:
- A new recursive text extraction function (extractText) was added to
correctly read.
- Text nodes
- Link nodes (including inner content and the href)
- Nested child content
- Link previews now appear in the following format:
DisplayText (https://example.com)
Edit : closes https://github.com/twentyhq/twenty/issues/16043
---------
Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
58 lines
1.3 KiB
TypeScript
58 lines
1.3 KiB
TypeScript
// TODO: merge with getFirstNonEmptyLineOfRichText (and one duplicate I saw and also added a note on)
|
|
|
|
import { isArray, isNonEmptyString } from '@sniptt/guards';
|
|
|
|
interface BaseNode {
|
|
type: string;
|
|
content?: RichTextNode[];
|
|
[key: string]: unknown;
|
|
}
|
|
|
|
interface TextNode extends BaseNode {
|
|
type: 'text';
|
|
text: string;
|
|
}
|
|
|
|
interface LinkNode extends BaseNode {
|
|
type: 'link';
|
|
href?: string;
|
|
content?: RichTextNode[];
|
|
}
|
|
|
|
type RichTextNode = TextNode | LinkNode | BaseNode;
|
|
|
|
const isTextNode = (node: RichTextNode): node is TextNode =>
|
|
node.type === 'text';
|
|
|
|
const isLinkNode = (node: RichTextNode): node is LinkNode =>
|
|
node.type === 'link';
|
|
|
|
export const getActivityPreview = (activityBody: string | null): string => {
|
|
const noteBody: RichTextNode[] = activityBody ? JSON.parse(activityBody) : [];
|
|
|
|
const extractText = (node: RichTextNode | undefined | null): string => {
|
|
if (!node) return '';
|
|
|
|
if (isTextNode(node)) {
|
|
return node.text ?? '';
|
|
}
|
|
|
|
if (isLinkNode(node)) {
|
|
return node.content?.map(extractText).join(' ') ?? '';
|
|
}
|
|
|
|
if (isArray(node.content)) {
|
|
return node.content.map(extractText).join(' ');
|
|
}
|
|
|
|
return '';
|
|
};
|
|
|
|
return noteBody.length
|
|
? noteBody
|
|
.map((node) => extractText(node))
|
|
.filter(isNonEmptyString)
|
|
.join('\n')
|
|
: '';
|
|
};
|