diff --git a/packages/core/src/content-types/tiptap.ts b/packages/core/src/content-types/tiptap.ts
index b0edc4a66..d7f83668d 100644
--- a/packages/core/src/content-types/tiptap.ts
+++ b/packages/core/src/content-types/tiptap.ts
@@ -18,7 +18,7 @@ along with this program. If not, see .
*/
import showdown from "@streetwriters/showdown";
-import { findAll, isTag } from "domutils";
+import { findAll, isTag, removeElement, replaceElement } from "domutils";
import {
DomNode,
FormatOptions,
@@ -37,10 +37,15 @@ import { HTMLRewriter } from "../utils/html-rewriter";
import { ContentBlock } from "../types";
import { InternalLink, parseInternalLink } from "../utils/internal-link";
import { Element } from "domhandler";
+import { render } from "dom-serializer";
export type ResolveHashes = (
hashes: string[]
) => Promise>;
+export type ResolveAttachments = (
+ attachments: Record>
+) => Promise>;
+export type ResolveInternalLink = (link: string) => string;
const ExtractableTypes = ["blocks", "internalLinks"] as const;
type ExtractableType = (typeof ExtractableTypes)[number];
@@ -64,7 +69,7 @@ converter.setFlavor("original");
const splitter = /\W+/gm;
export class Tiptap {
- constructor(private readonly data: string) {}
+ constructor(private data: string) {}
toHTML() {
return this.data;
@@ -143,6 +148,47 @@ export class Tiptap {
}).transform(this.data);
}
+ async resolveAttachments(resolve: ResolveAttachments) {
+ const attachments: Record> = {};
+ const document = parseDocument(this.data);
+ const elements = findAll(
+ (e) => !!e.attribs[ATTRIBUTES.hash],
+ document.childNodes
+ );
+ elements.forEach(
+ (element) =>
+ (attachments[element.attribs[ATTRIBUTES.hash]] = element.attribs)
+ );
+
+ const resolved = await resolve(attachments);
+ for (const element of elements) {
+ const hash = element.attribs[ATTRIBUTES.hash];
+ const html = resolved[hash];
+ if (html === undefined) continue;
+ if (html === false) {
+ removeElement(element);
+ continue;
+ }
+ replaceElement(element, parseDocument(html));
+ }
+ this.data = render(document);
+ return this;
+ }
+
+ resolveInternalLinks(resolve: ResolveInternalLink) {
+ this.data = new HTMLRewriter({
+ ontag: (name, attr) => {
+ const href = attr[ATTRIBUTES.href];
+ if (name === "a" && href.startsWith("nn://")) {
+ const link = resolve(href);
+ if (!link) return;
+ attr[ATTRIBUTES.href] = link;
+ }
+ }
+ }).transform(this.data);
+ return this;
+ }
+
extract(...types: ExtractableType[]): ExtractionResult {
const result: ExtractionResult = { blocks: [], internalLinks: [] };
const document = parseDocument(this.data, {