From 7ece9da7fc6d84e4a0ce2894e9da2dcd676ff9e9 Mon Sep 17 00:00:00 2001 From: manunamz Date: Tue, 3 Sep 2024 14:47:14 -0400 Subject: [PATCH] fix: embed setup -- now embedded content should render properly based on the remark setup in the astro config. --- astro.config.mjs | 36 +++++++++-------- src/wikibonsai/wikirefs.ts | 81 ++++++++++++++++++++++++++------------ 2 files changed, 75 insertions(+), 42 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 5e14e55..e9f5d46 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,18 +1,33 @@ import { base, defineConfig } from 'astro/config'; - import sitemap from '@astrojs/sitemap'; - import { remarkWikiRefs } from 'remark-wikirefs'; import { remarkCaml } from 'remark-caml'; import { resolveHtmlHref, resolveHtmlText, - resolveEmbedContent, + createResolveEmbedContent, generateForeRefsRemarkPlugin, } from './src/wikibonsai/wikirefs'; +const remarkPlugins = [ + remarkCaml, + [ + remarkWikiRefs, + { + resolveHtmlHref: resolveHtmlHref, + resolveHtmlText: resolveHtmlText, + resolveEmbedContent: null, // we'll set this later -- see below + }, + ], + generateForeRefsRemarkPlugin, +]; + +// embed content needs access to a unified processor +const resolveEmbedContent = createResolveEmbedContent(remarkPlugins); +remarkPlugins[1][1].resolveEmbedContent = resolveEmbedContent; + // https://astro.build/config export default defineConfig({ site: 'https://astro-wikibonsai.netlify.app', @@ -24,19 +39,6 @@ export default defineConfig({ // Preserve Astro's default plugins: GitHub-flavored Markdown and Smartypants extendDefaultPlugins: true, // Applied to .md and .mdx files - remarkPlugins: [ - remarkCaml, - [ - remarkWikiRefs, - { - baseUrl: base, - resolveHtmlHref: resolveHtmlHref, - resolveHtmlText: resolveHtmlText, - resolveEmbedContent: resolveEmbedContent, - }, - ], - // this plugin is necessary for backrefs to work - generateForeRefsRemarkPlugin, - ], + remarkPlugins: remarkPlugins, }, }); diff --git a/src/wikibonsai/wikirefs.ts b/src/wikibonsai/wikirefs.ts index b164faa..00501fd 100644 --- a/src/wikibonsai/wikirefs.ts +++ b/src/wikibonsai/wikirefs.ts @@ -1,13 +1,69 @@ +import type { Processor } from 'unified'; import path from 'path'; import fs from 'fs'; import fg from 'fast-glob'; import matter from 'gray-matter'; import { selectAll } from 'unist-util-select'; import * as wikirefs from 'wikirefs'; +import { unified } from 'unified'; +import remarkParse from 'remark-parse'; const CONTENT_GLOB: string = './src/content/**/*.md'; +let globalProcessor: Processor; +let cycleStack: string[] = []; + +export function createResolveEmbedContent(remarkPlugins: any[]) { + console.log("createResolveEmbedContent", remarkPlugins); + if (!globalProcessor) { + globalProcessor = unified().use(remarkParse); + // apply same remark plugins as in astro config + remarkPlugins.forEach(plugin => { + if (Array.isArray(plugin)) { + globalProcessor.use(plugin[0], plugin[1]); + } else { + globalProcessor.use(plugin); + } + }); + // note: we're not using remarkRehype or rehypeStringify here + } + + return function resolveEmbedContentInternal(filename: string): any { + // markdown-only + if (wikirefs.isMedia(filename)) { return; } + // cycle detection + if (cycleStack.length === 0) { + cycleStack = []; + } else if (cycleStack.includes(filename)) { + // reset stack before leaving + cycleStack = []; + return 'cycle detected'; + } + cycleStack.push(filename); + const docPaths: string[] = fg.sync(CONTENT_GLOB); + const docPath: string | undefined = docPaths.find((p) => { + return path.basename(p, '.md') === filename; + }); + let content: string = ''; + if (docPath === undefined) { + content = 'Error: Content not found for ' + "'" + filename + "'"; + } else { + const text: string | undefined = fs.readFileSync(docPath, { encoding: 'utf8', flag: 'r' }); + content = matter(text).content; + } + let mdastContent: any; + if (content.length === 0) { + mdastContent = ''; + } else { + mdastContent = globalProcessor.parse(content); + } + // reset stack before leaving + cycleStack = []; + return mdastContent; + }; +} + export function resolveHtmlHref(fname: string): string | undefined { // #todo revisit: https://docs.astro.build/en/reference/api-reference/#importmeta // 'import.meta.glob' docs: @@ -66,31 +122,6 @@ export function resolveHtmlText(fname: string): string | undefined { } } -export function resolveEmbedContent(filename: string): any { - // markdown-only - if (wikirefs.isMedia(filename)) { return; } - const docPaths: string[] = fg.sync(CONTENT_GLOB); - const docPath: string | undefined = docPaths.find((p) => { - return path.basename(p, '.md') === filename; - }); - let content: string = ''; - if (docPath === undefined) { - content = 'Error: Content not found for ' + "'" + filename + "'"; - } else { - const text: string | undefined = fs.readFileSync(docPath, { encoding: 'utf8', flag: 'r' }); - content = matter(text).content; - } - // return mdast node - return { - type: 'text', - // todo: render - value: content, - }; -} - -// forerfs - -// todo: don't include index documents when calculating metadata -- and skip index docs too export function generateForeRefsRemarkPlugin() { return function (tree: any, file: any) { // from: https://observablehq.com/@tmcw/extracting-links-from-markdown-using-remark-and-unist-util