diff --git a/apps/client/src/widgets/dialogs/export.ts b/apps/client/src/widgets/dialogs/export.ts index d9b13f4ed..ccc748d01 100644 --- a/apps/client/src/widgets/dialogs/export.ts +++ b/apps/client/src/widgets/dialogs/export.ts @@ -85,6 +85,13 @@ const TPL = /*html*/` + +
This is a clone of a note. Go to its primary location.
`; - content = prepareContent(noteMeta.title, content, noteMeta); + content = prepareContent(noteMeta.title, content, noteMeta, undefined); archive.append(content, { name: filePathPrefix + noteMeta.dataFileName }); @@ -333,7 +340,7 @@ async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "h } if (noteMeta.dataFileName) { - const content = prepareContent(noteMeta.title, note.getContent(), noteMeta); + const content = prepareContent(noteMeta.title, note.getContent(), noteMeta, note); archive.append(content, { name: filePathPrefix + noteMeta.dataFileName, @@ -395,6 +402,9 @@ async function exportToZip(taskContext: TaskContext, branch: BBranch, format: "h case "markdown": provider = new MarkdownExportProvider(providerData); break; + case "share": + provider = new ShareThemeExportProvider(providerData); + break; default: throw new Error(); } diff --git a/apps/server/src/services/export/zip/abstract_provider.ts b/apps/server/src/services/export/zip/abstract_provider.ts index ceadc0ec1..ba57ba69f 100644 --- a/apps/server/src/services/export/zip/abstract_provider.ts +++ b/apps/server/src/services/export/zip/abstract_provider.ts @@ -1,5 +1,7 @@ import { Archiver } from "archiver"; import type { default as NoteMeta, NoteMetaFile } from "../../meta/note_meta.js"; +import type BNote from "../../../becca/entities/bnote.js"; +import type BBranch from "../../../becca/entities/bbranch.js"; type RewriteLinksFn = (content: string, noteMeta: NoteMeta) => string; @@ -44,6 +46,6 @@ export abstract class ZipExportProvider { } abstract prepareMeta(): void; - abstract prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta): string | Buffer; + abstract prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta, note: BNote | undefined, branch: BBranch): string | Buffer; abstract afterDone(): void; } diff --git a/apps/server/src/services/export/zip/share_theme.ts b/apps/server/src/services/export/zip/share_theme.ts new file mode 100644 index 000000000..50339d20a --- /dev/null +++ b/apps/server/src/services/export/zip/share_theme.ts @@ -0,0 +1,86 @@ +import { join } from "path"; +import NoteMeta from "../../meta/note_meta"; +import { ZipExportProvider } from "./abstract_provider"; +import { RESOURCE_DIR } from "../../resource_dir"; +import { getResourceDir, isDev } from "../../utils"; +import fs from "fs"; +import { renderNoteForExport } from "../../../share/content_renderer"; +import type BNote from "../../../becca/entities/bnote.js"; +import type BBranch from "../../../becca/entities/bbranch.js"; + +export default class ShareThemeExportProvider extends ZipExportProvider { + + private assetsMeta: NoteMeta[] = []; + + prepareMeta(): void { + const assets = [ + "style.css", + "script.js", + "boxicons.css", + "boxicons.eot", + "boxicons.woff2", + "boxicons.woff", + "boxicons.ttf", + "boxicons.svg", + "icon-color.svg" + ]; + + for (const asset of assets) { + const assetMeta = { + noImport: true, + dataFileName: asset + }; + this.assetsMeta.push(assetMeta); + this.metaFile.files.push(assetMeta); + } + } + + prepareContent(title: string, content: string | Buffer, noteMeta: NoteMeta, note: BNote, branch: BBranch): string | Buffer { + if (!noteMeta?.notePath?.length) { + throw new Error("Missing note path."); + } + const basePath = "../".repeat(noteMeta.notePath.length - 1); + + content = renderNoteForExport(note, branch, basePath); + + return content; + } + + afterDone(): void { + this.#saveAssets(this.rootMeta, this.assetsMeta); + } + + #saveAssets(rootMeta: NoteMeta, assetsMeta: NoteMeta[]) { + for (const assetMeta of assetsMeta) { + if (!assetMeta.dataFileName) { + continue; + } + + let cssContent = getShareThemeAssets(assetMeta.dataFileName); + this.archive.append(cssContent, { name: assetMeta.dataFileName }); + } + } + +} + +function getShareThemeAssets(nameWithExtension: string) { + // Rename share.css to style.css. + if (nameWithExtension === "style.css") { + nameWithExtension = "share.css"; + } else if (nameWithExtension === "script.js") { + nameWithExtension = "share.js"; + } + + let path: string | undefined; + if (nameWithExtension === "icon-color.svg") { + path = join(RESOURCE_DIR, "images", nameWithExtension); + } else if (isDev) { + path = join(getResourceDir(), "..", "..", "client", "dist", "src", nameWithExtension); + } + + if (!path) { + throw new Error("Not yet defined."); + } + + return fs.readFileSync(path); +}