From ce3dd0923b93e8c1cbe95fe584418d6ee5dcba69 Mon Sep 17 00:00:00 2001
From: kabirgh <15871468+kabirgh@users.noreply.github.com>
Date: Thu, 18 Jan 2024 18:56:14 +0000
Subject: [PATCH] refactor: move emit from callback to helper file function (#704)

---
 quartz/plugins/types.ts                       |   15 ----
 quartz/plugins/emitters/static.ts             |    2 
 quartz/plugins/emitters/404.tsx               |    6 +
 quartz/plugins/emitters/helpers.ts            |   19 ++++++
 quartz/plugins/emitters/componentResources.ts |   16 +++--
 quartz/plugins/emitters/contentIndex.ts       |   12 ++-
 quartz/plugins/emitters/tagPage.tsx           |    6 +
 quartz/processors/emit.ts                     |   13 ----
 quartz/plugins/emitters/assets.ts             |    2 
 quartz/plugins/emitters/folderPage.tsx        |    6 +
 quartz/plugins/emitters/contentPage.tsx       |    6 +
 quartz/plugins/emitters/aliases.ts            |    7 +
 quartz/plugins/emitters/cname.ts              |    2 
 docs/advanced/making plugins.md               |   15 ++---
 14 files changed, 69 insertions(+), 58 deletions(-)

diff --git a/docs/advanced/making plugins.md b/docs/advanced/making plugins.md
index fcc88a7..65209a2 100644
--- a/docs/advanced/making plugins.md
+++ b/docs/advanced/making plugins.md
@@ -216,22 +216,19 @@
 
 export type QuartzEmitterPluginInstance = {
   name: string
-  emit(
-    ctx: BuildCtx,
-    content: ProcessedContent[],
-    resources: StaticResources,
-    emitCallback: EmitCallback,
-  ): Promise<FilePath[]>
+  emit(ctx: BuildCtx, content: ProcessedContent[], resources: StaticResources): Promise<FilePath[]>
   getQuartzComponents(ctx: BuildCtx): QuartzComponent[]
 }
 ```
 
-An emitter plugin must define a `name` field an `emit` function and a `getQuartzComponents` function. `emit` is responsible for looking at all the parsed and filtered content and then appropriately creating files and returning a list of paths to files the plugin created.
+An emitter plugin must define a `name` field, an `emit` function, and a `getQuartzComponents` function. `emit` is responsible for looking at all the parsed and filtered content and then appropriately creating files and returning a list of paths to files the plugin created.
 
-Creating new files can be done via regular Node [fs module](https://nodejs.org/api/fs.html) (i.e. `fs.cp` or `fs.writeFile`) or via the `emitCallback` if you are creating files that contain text. The `emitCallback` function is the 4th argument of the emit function. Its interface looks something like this:
+Creating new files can be done via regular Node [fs module](https://nodejs.org/api/fs.html) (i.e. `fs.cp` or `fs.writeFile`) or via the `write` function in `quartz/plugins/emitters/helpers.ts` if you are creating files that contain text. `write` has the following signature:
 
 ```ts
-export type EmitCallback = (data: {
+export type WriteOptions = (data: {
+  // the build context
+  ctx: BuildCtx
   // the name of the file to emit (not including the file extension)
   slug: ServerSlug
   // the file extension
diff --git a/quartz/plugins/emitters/404.tsx b/quartz/plugins/emitters/404.tsx
index cd079a0..58ae59a 100644
--- a/quartz/plugins/emitters/404.tsx
+++ b/quartz/plugins/emitters/404.tsx
@@ -7,6 +7,7 @@
 import { sharedPageComponents } from "../../../quartz.layout"
 import { NotFound } from "../../components"
 import { defaultProcessedContent } from "../vfile"
+import { write } from "./helpers"
 
 export const NotFoundPage: QuartzEmitterPlugin = () => {
   const opts: FullPageLayout = {
@@ -25,7 +26,7 @@
     getQuartzComponents() {
       return [Head, Body, pageBody, Footer]
     },
-    async emit(ctx, _content, resources, emit): Promise<FilePath[]> {
+    async emit(ctx, _content, resources): Promise<FilePath[]> {
       const cfg = ctx.cfg.configuration
       const slug = "404" as FullSlug
 
@@ -48,7 +49,8 @@
       }
 
       return [
-        await emit({
+        await write({
+          ctx,
           content: renderPage(slug, componentData, opts, externalResources),
           slug,
           ext: ".html",
diff --git a/quartz/plugins/emitters/aliases.ts b/quartz/plugins/emitters/aliases.ts
index 210715e..118c392 100644
--- a/quartz/plugins/emitters/aliases.ts
+++ b/quartz/plugins/emitters/aliases.ts
@@ -1,13 +1,15 @@
 import { FilePath, FullSlug, joinSegments, resolveRelative, simplifySlug } from "../../util/path"
 import { QuartzEmitterPlugin } from "../types"
 import path from "path"
+import { write } from "./helpers"
 
 export const AliasRedirects: QuartzEmitterPlugin = () => ({
   name: "AliasRedirects",
   getQuartzComponents() {
     return []
   },
-  async emit({ argv }, content, _resources, emit): Promise<FilePath[]> {
+  async emit(ctx, content, _resources): Promise<FilePath[]> {
+    const { argv } = ctx
     const fps: FilePath[] = []
 
     for (const [_tree, file] of content) {
@@ -32,7 +34,8 @@
         }
 
         const redirUrl = resolveRelative(slug, file.data.slug!)
-        const fp = await emit({
+        const fp = await write({
+          ctx,
           content: `
             <!DOCTYPE html>
             <html lang="en-us">
diff --git a/quartz/plugins/emitters/assets.ts b/quartz/plugins/emitters/assets.ts
index edc22d9..cc97b2e 100644
--- a/quartz/plugins/emitters/assets.ts
+++ b/quartz/plugins/emitters/assets.ts
@@ -10,7 +10,7 @@
     getQuartzComponents() {
       return []
     },
-    async emit({ argv, cfg }, _content, _resources, _emit): Promise<FilePath[]> {
+    async emit({ argv, cfg }, _content, _resources): Promise<FilePath[]> {
       // glob all non MD/MDX/HTML files in content folder and copy it over
       const assetsPath = argv.output
       const fps = await glob("**", argv.directory, ["**/*.md", ...cfg.configuration.ignorePatterns])
diff --git a/quartz/plugins/emitters/cname.ts b/quartz/plugins/emitters/cname.ts
index ffe2c6d..3e17fea 100644
--- a/quartz/plugins/emitters/cname.ts
+++ b/quartz/plugins/emitters/cname.ts
@@ -13,7 +13,7 @@
   getQuartzComponents() {
     return []
   },
-  async emit({ argv, cfg }, _content, _resources, _emit): Promise<FilePath[]> {
+  async emit({ argv, cfg }, _content, _resources): Promise<FilePath[]> {
     if (!cfg.configuration.baseUrl) {
       console.warn(chalk.yellow("CNAME emitter requires `baseUrl` to be set in your configuration"))
       return []
diff --git a/quartz/plugins/emitters/componentResources.ts b/quartz/plugins/emitters/componentResources.ts
index e8a81bc..f92c0a9 100644
--- a/quartz/plugins/emitters/componentResources.ts
+++ b/quartz/plugins/emitters/componentResources.ts
@@ -13,6 +13,7 @@
 import { googleFontHref, joinStyles } from "../../util/theme"
 import { Features, transform } from "lightningcss"
 import { transform as transpile } from "esbuild"
+import { write } from "./helpers"
 
 type ComponentResources = {
   css: string[]
@@ -93,7 +94,7 @@
       function gtag() { dataLayer.push(arguments); }
       gtag("js", new Date());
       gtag("config", "${tagId}", { send_page_view: false });
-  
+
       document.addEventListener("nav", () => {
         gtag("event", "page_view", {
           page_title: document.title,
@@ -121,7 +122,7 @@
       umamiScript.src = "https://analytics.umami.is/script.js"
       umamiScript.setAttribute("data-website-id", "${cfg.analytics.websiteId}")
       umamiScript.async = true
-  
+
       document.head.appendChild(umamiScript)
     `)
   }
@@ -168,7 +169,7 @@
     getQuartzComponents() {
       return []
     },
-    async emit(ctx, _content, resources, emit): Promise<FilePath[]> {
+    async emit(ctx, _content, resources): Promise<FilePath[]> {
       // component specific scripts and styles
       const componentResources = getComponentResources(ctx)
       // important that this goes *after* component scripts
@@ -190,7 +191,8 @@
       ])
 
       const fps = await Promise.all([
-        emit({
+        write({
+          ctx,
           slug: "index" as FullSlug,
           ext: ".css",
           content: transform({
@@ -207,12 +209,14 @@
             include: Features.MediaQueries,
           }).code.toString(),
         }),
-        emit({
+        write({
+          ctx,
           slug: "prescript" as FullSlug,
           ext: ".js",
           content: prescript,
         }),
-        emit({
+        write({
+          ctx,
           slug: "postscript" as FullSlug,
           ext: ".js",
           content: postscript,
diff --git a/quartz/plugins/emitters/contentIndex.ts b/quartz/plugins/emitters/contentIndex.ts
index fa8c2c9..31e1d3e 100644
--- a/quartz/plugins/emitters/contentIndex.ts
+++ b/quartz/plugins/emitters/contentIndex.ts
@@ -6,6 +6,7 @@
 import { QuartzEmitterPlugin } from "../types"
 import { toHtml } from "hast-util-to-html"
 import path from "path"
+import { write } from "./helpers"
 
 export type ContentIndex = Map<FullSlug, ContentDetails>
 export type ContentDetails = {
@@ -91,7 +92,7 @@
   opts = { ...defaultOptions, ...opts }
   return {
     name: "ContentIndex",
-    async emit(ctx, content, _resources, emit) {
+    async emit(ctx, content, _resources) {
       const cfg = ctx.cfg.configuration
       const emitted: FilePath[] = []
       const linkIndex: ContentIndex = new Map()
@@ -115,7 +116,8 @@
 
       if (opts?.enableSiteMap) {
         emitted.push(
-          await emit({
+          await write({
+            ctx,
             content: generateSiteMap(cfg, linkIndex),
             slug: "sitemap" as FullSlug,
             ext: ".xml",
@@ -125,7 +127,8 @@
 
       if (opts?.enableRSS) {
         emitted.push(
-          await emit({
+          await write({
+            ctx,
             content: generateRSSFeed(cfg, linkIndex, opts.rssLimit),
             slug: "index" as FullSlug,
             ext: ".xml",
@@ -146,7 +149,8 @@
       )
 
       emitted.push(
-        await emit({
+        await write({
+          ctx,
           content: JSON.stringify(simplifiedIndex),
           slug: fp,
           ext: ".json",
diff --git a/quartz/plugins/emitters/contentPage.tsx b/quartz/plugins/emitters/contentPage.tsx
index 338bfae..f8e6404 100644
--- a/quartz/plugins/emitters/contentPage.tsx
+++ b/quartz/plugins/emitters/contentPage.tsx
@@ -8,6 +8,7 @@
 import { defaultContentPageLayout, sharedPageComponents } from "../../../quartz.layout"
 import { Content } from "../../components"
 import chalk from "chalk"
+import { write } from "./helpers"
 
 export const ContentPage: QuartzEmitterPlugin<Partial<FullPageLayout>> = (userOpts) => {
   const opts: FullPageLayout = {
@@ -26,7 +27,7 @@
     getQuartzComponents() {
       return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
     },
-    async emit(ctx, content, resources, emit): Promise<FilePath[]> {
+    async emit(ctx, content, resources): Promise<FilePath[]> {
       const cfg = ctx.cfg.configuration
       const fps: FilePath[] = []
       const allFiles = content.map((c) => c[1].data)
@@ -49,7 +50,8 @@
         }
 
         const content = renderPage(slug, componentData, opts, externalResources)
-        const fp = await emit({
+        const fp = await write({
+          ctx,
           content,
           slug,
           ext: ".html",
diff --git a/quartz/plugins/emitters/folderPage.tsx b/quartz/plugins/emitters/folderPage.tsx
index 8632ece..a4bd1ae 100644
--- a/quartz/plugins/emitters/folderPage.tsx
+++ b/quartz/plugins/emitters/folderPage.tsx
@@ -17,6 +17,7 @@
 } from "../../util/path"
 import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
 import { FolderContent } from "../../components"
+import { write } from "./helpers"
 
 export const FolderPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => {
   const opts: FullPageLayout = {
@@ -35,7 +36,7 @@
     getQuartzComponents() {
       return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
     },
-    async emit(ctx, content, resources, emit): Promise<FilePath[]> {
+    async emit(ctx, content, resources): Promise<FilePath[]> {
       const fps: FilePath[] = []
       const allFiles = content.map((c) => c[1].data)
       const cfg = ctx.cfg.configuration
@@ -82,7 +83,8 @@
         }
 
         const content = renderPage(slug, componentData, opts, externalResources)
-        const fp = await emit({
+        const fp = await write({
+          ctx,
           content,
           slug,
           ext: ".html",
diff --git a/quartz/plugins/emitters/helpers.ts b/quartz/plugins/emitters/helpers.ts
new file mode 100644
index 0000000..ef1d1c3
--- /dev/null
+++ b/quartz/plugins/emitters/helpers.ts
@@ -0,0 +1,19 @@
+import path from "path"
+import fs from "fs"
+import { BuildCtx } from "../../util/ctx"
+import { FilePath, FullSlug, joinSegments } from "../../util/path"
+
+type WriteOptions = {
+  ctx: BuildCtx
+  slug: FullSlug
+  ext: `.${string}` | ""
+  content: string
+}
+
+export const write = async ({ ctx, slug, ext, content }: WriteOptions): Promise<FilePath> => {
+  const pathToPage = joinSegments(ctx.argv.output, slug + ext) as FilePath
+  const dir = path.dirname(pathToPage)
+  await fs.promises.mkdir(dir, { recursive: true })
+  await fs.promises.writeFile(pathToPage, content)
+  return pathToPage
+}
diff --git a/quartz/plugins/emitters/static.ts b/quartz/plugins/emitters/static.ts
index f0118e2..9f93d9b 100644
--- a/quartz/plugins/emitters/static.ts
+++ b/quartz/plugins/emitters/static.ts
@@ -8,7 +8,7 @@
   getQuartzComponents() {
     return []
   },
-  async emit({ argv, cfg }, _content, _resources, _emit): Promise<FilePath[]> {
+  async emit({ argv, cfg }, _content, _resources): Promise<FilePath[]> {
     const staticPath = joinSegments(QUARTZ, "static")
     const fps = await glob("**", staticPath, cfg.configuration.ignorePatterns)
     await fs.promises.cp(staticPath, joinSegments(argv.output, "static"), {
diff --git a/quartz/plugins/emitters/tagPage.tsx b/quartz/plugins/emitters/tagPage.tsx
index 5669119..56a552c 100644
--- a/quartz/plugins/emitters/tagPage.tsx
+++ b/quartz/plugins/emitters/tagPage.tsx
@@ -14,6 +14,7 @@
 } from "../../util/path"
 import { defaultListPageLayout, sharedPageComponents } from "../../../quartz.layout"
 import { TagContent } from "../../components"
+import { write } from "./helpers"
 
 export const TagPage: QuartzEmitterPlugin<FullPageLayout> = (userOpts) => {
   const opts: FullPageLayout = {
@@ -32,7 +33,7 @@
     getQuartzComponents() {
       return [Head, Header, Body, ...header, ...beforeBody, pageBody, ...left, ...right, Footer]
     },
-    async emit(ctx, content, resources, emit): Promise<FilePath[]> {
+    async emit(ctx, content, resources): Promise<FilePath[]> {
       const fps: FilePath[] = []
       const allFiles = content.map((c) => c[1].data)
       const cfg = ctx.cfg.configuration
@@ -81,7 +82,8 @@
         }
 
         const content = renderPage(slug, componentData, opts, externalResources)
-        const fp = await emit({
+        const fp = await write({
+          ctx,
           content,
           slug: file.data.slug!,
           ext: ".html",
diff --git a/quartz/plugins/types.ts b/quartz/plugins/types.ts
index eaeb12a..bf1c0db 100644
--- a/quartz/plugins/types.ts
+++ b/quartz/plugins/types.ts
@@ -36,19 +36,6 @@
 ) => QuartzEmitterPluginInstance
 export type QuartzEmitterPluginInstance = {
   name: string
-  emit(
-    ctx: BuildCtx,
-    content: ProcessedContent[],
-    resources: StaticResources,
-    emitCallback: EmitCallback,
-  ): Promise<FilePath[]>
+  emit(ctx: BuildCtx, content: ProcessedContent[], resources: StaticResources): Promise<FilePath[]>
   getQuartzComponents(ctx: BuildCtx): QuartzComponent[]
 }
-
-export interface EmitOptions {
-  slug: FullSlug
-  ext: `.${string}` | ""
-  content: string
-}
-
-export type EmitCallback = (data: EmitOptions) => Promise<FilePath>
diff --git a/quartz/processors/emit.ts b/quartz/processors/emit.ts
index 3b357aa..c68e0ed 100644
--- a/quartz/processors/emit.ts
+++ b/quartz/processors/emit.ts
@@ -1,10 +1,6 @@
-import path from "path"
-import fs from "fs"
 import { PerfTimer } from "../util/perf"
 import { getStaticResourcesFromPlugins } from "../plugins"
-import { EmitCallback } from "../plugins/types"
 import { ProcessedContent } from "../plugins/vfile"
-import { FilePath, joinSegments } from "../util/path"
 import { QuartzLogger } from "../util/log"
 import { trace } from "../util/trace"
 import { BuildCtx } from "../util/ctx"
@@ -15,19 +11,12 @@
   const log = new QuartzLogger(ctx.argv.verbose)
 
   log.start(`Emitting output files`)
-  const emit: EmitCallback = async ({ slug, ext, content }) => {
-    const pathToPage = joinSegments(argv.output, slug + ext) as FilePath
-    const dir = path.dirname(pathToPage)
-    await fs.promises.mkdir(dir, { recursive: true })
-    await fs.promises.writeFile(pathToPage, content)
-    return pathToPage
-  }
 
   let emittedFiles = 0
   const staticResources = getStaticResourcesFromPlugins(ctx)
   for (const emitter of cfg.plugins.emitters) {
     try {
-      const emitted = await emitter.emit(ctx, content, staticResources, emit)
+      const emitted = await emitter.emit(ctx, content, staticResources)
       emittedFiles += emitted.length
 
       if (ctx.argv.verbose) {

--
Gitblit v1.10.0