Parsers work, tagpage/folderpage broken

This commit is contained in:
Emile Bangma 2024-09-19 18:17:33 +00:00
parent 7ed79cd27f
commit c1c8e26722
14 changed files with 183 additions and 142 deletions

View File

@ -77,8 +77,8 @@ const config: QuartzConfig = {
Plugin.AliasRedirects(), Plugin.AliasRedirects(),
Plugin.ComponentResources(), Plugin.ComponentResources(),
Plugin.ContentPage(), Plugin.ContentPage(),
Plugin.FolderPage(), //Plugin.FolderPage(),
Plugin.TagPage(), //Plugin.TagPage(),
Plugin.ContentIndex({ Plugin.ContentIndex({
enableSiteMap: true, enableSiteMap: true,
enableRSS: true, enableRSS: true,

View File

@ -23,11 +23,11 @@ export const CustomDefault: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _file) => { const plug: Pluggable = (tree: Root, _file) => {
const replacements: [RegExp, string | ReplaceFunction][] = []
mdastFindReplace(tree, replacements) mdastFindReplace(tree, replacements)
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -42,9 +42,9 @@ export const ObsidianArrow: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _path) => { const plug: Pluggable = (tree: Root, _path) => {
if (opts.enabled) { if (opts.enabled) {
const replacements: [RegExp, string | ReplaceFunction][] = []
replacements.push([ replacements.push([
arrowRegex, arrowRegex,
(value: string, ..._capture: string[]) => { (value: string, ..._capture: string[]) => {
@ -56,10 +56,9 @@ export const ObsidianArrow: QuartzParser<Partial<Options>> = (userOpts) => {
} }
}, },
]) ])
mdastFindReplaceInHtml(tree, replacements, opts.inHtml)
} }
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -27,11 +27,11 @@ export const ObsidianBlockReference: QuartzParser<Partial<Options>> = (userOpts)
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _file) => { const plug: Pluggable = (tree: Root, _file) => {
const replacements: [RegExp, string | ReplaceFunction][] = []
mdastFindReplace(tree, replacements) mdastFindReplace(tree, replacements)
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const inlineTagTypes = new Set(["p", "li"]) const inlineTagTypes = new Set(["p", "li"])

View File

@ -1,6 +1,7 @@
import { QuartzParser } from "../../types" import { QuartzParser } from "../../types"
import { JSResource } from "../../../util/resources" import { JSResource } from "../../../util/resources"
import { Root, BlockContent, DefinitionContent, Paragraph, Html } from "mdast" import { Root, BlockContent, DefinitionContent, Paragraph, Html } from "mdast"
import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace"
import { visit } from "unist-util-visit" import { visit } from "unist-util-visit"
import { Pluggable } from "unified" import { Pluggable } from "unified"
// @ts-ignore // @ts-ignore
@ -77,6 +78,7 @@ export const ObsidianCallouts: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _path) => { const plug: Pluggable = (tree: Root, _path) => {
if (opts.enabled) { if (opts.enabled) {
visit(tree, "blockquote", (node) => { visit(tree, "blockquote", (node) => {
@ -181,7 +183,7 @@ export const ObsidianCallouts: QuartzParser<Partial<Options>> = (userOpts) => {
}) })
} }
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -30,11 +30,11 @@ export const ObsidianCheckboxes: QuartzParser<Partial<Options>> = (userOpts) =>
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _file) => { const plug: Pluggable = (tree: Root, _file) => {
const replacements: [RegExp, string | ReplaceFunction][] = []
mdastFindReplaceInHtml(tree, replacements, opts.inHtml) mdastFindReplaceInHtml(tree, replacements, opts.inHtml)
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
if (opts.enabled) { if (opts.enabled) {

View File

@ -33,13 +33,9 @@ export const ObsidianComments: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const plug: Pluggable = (tree: Root, _file) => { const replacements: [RegExp, string | ReplaceFunction][] = []
if (opts.enabled) { const plug: Pluggable = (tree: Root, _file) => {}
const replacements: [RegExp, string | ReplaceFunction][] = [] return replacements
mdastFindReplaceInHtml(tree, replacements, opts.inHtml)
}
}
return plug
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -30,9 +30,9 @@ export const ObsidianHighlights: QuartzParser<Partial<Options>> = (userOpts) =>
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _path) => { const plug: Pluggable = (tree: Root, _path) => {
if (opts.enabled) { if (opts.enabled) {
const replacements: [RegExp, string | ReplaceFunction][] = []
replacements.push([ replacements.push([
highlightRegex, highlightRegex,
(_value: string, ...capture: string[]) => { (_value: string, ...capture: string[]) => {
@ -43,10 +43,9 @@ export const ObsidianHighlights: QuartzParser<Partial<Options>> = (userOpts) =>
} }
}, },
]) ])
mdastFindReplaceInHtml(tree, replacements, opts.inHtml)
} }
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -1,5 +1,6 @@
import { QuartzParser } from "../../types" import { QuartzParser } from "../../types"
import { JSResource } from "../../../util/resources" import { JSResource } from "../../../util/resources"
import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace"
import { visit } from "unist-util-visit" import { visit } from "unist-util-visit"
import { Root, Code } from "mdast" import { Root, Code } from "mdast"
import { Pluggable } from "unified" import { Pluggable } from "unified"
@ -25,6 +26,7 @@ export const ObsidianMermaid: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins() { markdownPlugins() {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _file) => { const plug: Pluggable = (tree: Root, _file) => {
if (opts.enabled) { if (opts.enabled) {
visit(tree, "code", (node: Code) => { visit(tree, "code", (node: Code) => {
@ -38,7 +40,7 @@ export const ObsidianMermaid: QuartzParser<Partial<Options>> = (userOpts) => {
}) })
} }
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -3,6 +3,7 @@ import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-
import { FilePath, pathToRoot, slugTag, slugifyFilePath } from "../../../util/path" import { FilePath, pathToRoot, slugTag, slugifyFilePath } from "../../../util/path"
import { JSResource } from "../../../util/resources" import { JSResource } from "../../../util/resources"
import { Root } from "mdast" import { Root } from "mdast"
import path from "path"
import { Pluggable } from "unified" import { Pluggable } from "unified"
import { mdastFindReplaceInHtml } from "../../transformers/markdown" import { mdastFindReplaceInHtml } from "../../transformers/markdown"
@ -35,43 +36,44 @@ export const ObsidianTags: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, file) => { const plug: Pluggable = (tree: Root, file) => {
const base = pathToRoot(file.data.slug!) if (opts.enabled) {
const replacements: [RegExp, string | ReplaceFunction][] = [] const base = pathToRoot(file.data.slug!)
replacements.push([ replacements.push([
tagRegex, tagRegex,
(_value: string, tag: string) => { (_value: string, tag: string) => {
// Check if the tag only includes numbers and slashes // Check if the tag only includes numbers and slashes
if (/^[\/\d]+$/.test(tag)) { if (/^[\/\d]+$/.test(tag)) {
return false return false
} }
tag = slugTag(tag) tag = slugTag(tag)
if (file.data.frontmatter) { if (file.data.frontmatter) {
const noteTags = file.data.frontmatter.tags ?? [] const noteTags = file.data.frontmatter.tags ?? []
file.data.frontmatter.tags = [...new Set([...noteTags, tag])] file.data.frontmatter.tags = [...new Set([...noteTags, tag])]
} }
return { return {
type: "link", type: "link",
url: base + `/tags/${tag}`, url: base + `/tags/${tag}`,
data: { data: {
hProperties: { hProperties: {
className: ["tag-link"], className: ["tag-link"],
},
}, },
}, children: [
children: [ {
{ type: "text",
type: "text", value: tag,
value: tag, },
}, ],
], }
} },
}, ])
]) }
mdastFindReplaceInHtml(tree, replacements, opts.inHtml)
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -5,6 +5,7 @@ import { JSResource } from "../../../util/resources"
import { Root } from "mdast" import { Root } from "mdast"
import { Pluggable } from "unified" import { Pluggable } from "unified"
import { mdastFindReplaceInHtml } from "../../transformers/markdown" import { mdastFindReplaceInHtml } from "../../transformers/markdown"
import path from "path"
interface Options { interface Options {
enabled: Boolean enabled: Boolean
@ -82,82 +83,85 @@ export const ObsidianWikilinks: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const plug: Pluggable = (tree: Root, path) => { const replacements: [RegExp, string | ReplaceFunction][] = []
const replacements: [RegExp, string | ReplaceFunction][] = [] const plug: Pluggable = (tree: Root, file) => {
replacements.push([ if (opts.enabled) {
wikilinkRegex, replacements.push([
(value: string, ...capture: string[]) => { wikilinkRegex,
let [rawFp, rawHeader, rawAlias] = capture (value: string, ...capture: string[]) => {
const fp = rawFp?.trim() ?? "" let [rawFp, rawHeader, rawAlias] = capture
const anchor = rawHeader?.trim() ?? "" const fp = rawFp?.trim() ?? ""
const alias = rawAlias?.slice(1).trim() const anchor = rawHeader?.trim() ?? ""
const alias = rawAlias?.slice(1).trim()
// embed cases // embed cases
if (value.startsWith("!")) { if (value.startsWith("!")) {
const ext: string = path.extname(fp).toLowerCase() const ext: string = path.extname(fp).toLowerCase()
const url = slugifyFilePath(fp as FilePath) const url = slugifyFilePath(fp as FilePath)
if ([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg", ".webp"].includes(ext)) { if ([".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg", ".webp"].includes(ext)) {
const match = wikilinkImageEmbedRegex.exec(alias ?? "") const match = wikilinkImageEmbedRegex.exec(alias ?? "")
const alt = match?.groups?.alt ?? "" const alt = match?.groups?.alt ?? ""
const width = match?.groups?.width ?? "auto" const width = match?.groups?.width ?? "auto"
const height = match?.groups?.height ?? "auto" const height = match?.groups?.height ?? "auto"
return { return {
type: "image", type: "image",
url, url,
data: { data: {
hProperties: { hProperties: {
width, width,
height, height,
alt, alt,
},
}, },
}, }
} } else if ([".mp4", ".webm", ".ogv", ".mov", ".mkv"].includes(ext)) {
} else if ([".mp4", ".webm", ".ogv", ".mov", ".mkv"].includes(ext)) { return {
return { type: "html",
type: "html", value: `<video src="${url}" controls></video>`,
value: `<video src="${url}" controls></video>`, }
} } else if (
} else if ([".mp3", ".webm", ".wav", ".m4a", ".ogg", ".3gp", ".flac"].includes(ext)) { [".mp3", ".webm", ".wav", ".m4a", ".ogg", ".3gp", ".flac"].includes(ext)
return { ) {
type: "html", return {
value: `<audio src="${url}" controls></audio>`, type: "html",
} value: `<audio src="${url}" controls></audio>`,
} else if ([".pdf"].includes(ext)) { }
return { } else if ([".pdf"].includes(ext)) {
type: "html", return {
value: `<iframe src="${url}" class="pdf"></iframe>`, type: "html",
} value: `<iframe src="${url}" class="pdf"></iframe>`,
} else { }
const block = anchor } else {
return { const block = anchor
type: "html", return {
data: { hProperties: { transclude: true } }, type: "html",
value: `<blockquote class="transclude" data-url="${url}" data-block="${block}" data-embed-alias="${alias}"><a href="${ data: { hProperties: { transclude: true } },
url + anchor value: `<blockquote class="transclude" data-url="${url}" data-block="${block}" data-embed-alias="${alias}"><a href="${
}" class="transclude-inner">Transclude of ${url}${block}</a></blockquote>`, url + anchor
}" class="transclude-inner">Transclude of ${url}${block}</a></blockquote>`,
}
} }
// otherwise, fall through to regular link
} }
// otherwise, fall through to regular link // internal link
} const url = fp + anchor
return {
// internal link type: "link",
const url = fp + anchor url,
return { children: [
type: "link", {
url, type: "text",
children: [ value: alias ?? fp,
{ },
type: "text", ],
value: alias ?? fp, }
}, },
], ])
} }
},
])
mdastFindReplaceInHtml(tree, replacements, opts.inHtml)
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
const plug: Pluggable = () => {} const plug: Pluggable = () => {}

View File

@ -28,11 +28,11 @@ export const ObsidianYouTube: QuartzParser<Partial<Options>> = (userOpts) => {
return src return src
}, },
markdownPlugins(_ctx) { markdownPlugins(_ctx) {
const replacements: [RegExp, string | ReplaceFunction][] = []
const plug: Pluggable = (tree: Root, _file) => { const plug: Pluggable = (tree: Root, _file) => {
const replacements: [RegExp, string | ReplaceFunction][] = []
mdastFindReplace(tree, replacements) mdastFindReplace(tree, replacements)
} }
return plug return replacements
}, },
htmlPlugins() { htmlPlugins() {
if (opts.enabled) { if (opts.enabled) {

View File

@ -184,8 +184,9 @@ export const mdastFindReplaceInHtml = (
} }
} }
}) })
} else {
mdastFindReplace(tree, replacements)
} }
mdastFindReplace(tree, replacements)
} }
export const CommonMarkFlavoredMarkdown: QuartzTransformerPlugin<Partial<CommonMarkOptions>> = ( export const CommonMarkFlavoredMarkdown: QuartzTransformerPlugin<Partial<CommonMarkOptions>> = (
@ -254,7 +255,9 @@ export const GitHubFlavoredMarkdown: QuartzTransformerPlugin<Partial<GitHubOptio
markdownPlugins(ctx) { markdownPlugins(ctx) {
const plugins: PluggableList = [] const plugins: PluggableList = []
plugins.push(GitHubSmartypants({ enabled: opts.enableSmartyPants }).markdownPlugins(ctx)) plugins.push(
GitHubSmartypants({ enabled: opts.enableSmartyPants }).markdownPlugins(ctx) as Pluggable,
)
return plugins return plugins
}, },
@ -291,6 +294,27 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<ObsidianO
const inHtml = opts.enableInHtmlEmbed const inHtml = opts.enableInHtmlEmbed
const replacements: [RegExp, string | ReplaceFunction][] = []
replacements.push.apply(
ObsidianWikilinks({ enabled: opts.wikilinks, inHtml: inHtml }).markdownPlugins(ctx),
)
replacements.push.apply(
ObsidianHighlights({ enabled: opts.highlight, inHtml: inHtml }).markdownPlugins(ctx),
)
replacements.push.apply(
ObsidianArrow({ enabled: opts.parseArrows, inHtml: inHtml }).markdownPlugins(ctx),
)
replacements.push.apply(
ObsidianTags({ enabled: opts.parseTags, inHtml: inHtml }).markdownPlugins(ctx),
)
plugins.push(() => {
return (tree: Root, file) => {
mdastFindReplaceInHtml(tree, replacements, inHtml)
}
})
/*plugins.push(() => { /*plugins.push(() => {
return (tree: Root, file) => { return (tree: Root, file) => {
//const replacements: [RegExp, string | ReplaceFunction][] = [] //const replacements: [RegExp, string | ReplaceFunction][] = []
@ -305,7 +329,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<ObsidianO
//mdastFindReplace(tree, replacements) //mdastFindReplace(tree, replacements)
} }
})*/ })*/
plugins.push( /*plugins.push(
ObsidianWikilinks({ enabled: opts.wikilinks, inHtml: inHtml }).markdownPlugins(ctx), ObsidianWikilinks({ enabled: opts.wikilinks, inHtml: inHtml }).markdownPlugins(ctx),
) )
plugins.push( plugins.push(
@ -314,23 +338,35 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<ObsidianO
plugins.push( plugins.push(
ObsidianArrow({ enabled: opts.parseArrows, inHtml: inHtml }).markdownPlugins(ctx), ObsidianArrow({ enabled: opts.parseArrows, inHtml: inHtml }).markdownPlugins(ctx),
) )
plugins.push(ObsidianTags({ enabled: opts.parseTags, inHtml: inHtml }).markdownPlugins(ctx)) plugins.push(ObsidianTags({ enabled: opts.parseTags, inHtml: inHtml }).markdownPlugins(ctx))*/
plugins.push(ObsidianVideo({ enabled: opts.enableVideoEmbed }).markdownPlugins(ctx)) plugins.push(() => {
plugins.push(ObsidianCallouts({ enabled: opts.callouts }).markdownPlugins(ctx)) return (tree: Root, file) =>
plugins.push(ObsidianMermaid({ enabled: opts.mermaid }).markdownPlugins(ctx)) ObsidianVideo({ enabled: opts.enableVideoEmbed }).markdownPlugins(ctx)
})
plugins.push(() => {
return (tree: Root, file) =>
ObsidianCallouts({ enabled: opts.callouts }).markdownPlugins(ctx)
})
plugins.push(() => {
return (tree: Root, file) => ObsidianMermaid({ enabled: opts.mermaid }).markdownPlugins(ctx)
})
return plugins return plugins
}, },
htmlPlugins() { htmlPlugins() {
const plugins: PluggableList = [rehypeRaw] const plugins: PluggableList = [rehypeRaw]
plugins.push( plugins.push(() => {
ObsidianBlockReference({ enabled: opts.parseBlockReferences }).htmlPlugins() as Pluggable, return (tree: Root, file) =>
) ObsidianBlockReference({ enabled: opts.parseBlockReferences }).htmlPlugins() as Pluggable
plugins.push(ObsidianYouTube({ enabled: opts.enableYouTubeEmbed }).htmlPlugins() as Pluggable) })
plugins.push.apply( plugins.push(() => {
ObsidianCheckboxes({ enabled: opts.enableCheckbox }).htmlPlugins() as Pluggable[], return (tree: Root, file) =>
) ObsidianYouTube({ enabled: opts.enableYouTubeEmbed }).htmlPlugins() as Pluggable
})
/*plugins.push(() => {
return (tree: HtmlRoot, file) => ObsidianCheckboxes({ enabled: opts.enableCheckbox }).htmlPlugins() as Pluggable}
)*/
return plugins return plugins
}, },

View File

@ -1,5 +1,6 @@
import { PluggableList, Pluggable } from "unified" import { PluggableList, Pluggable } from "unified"
import { JSResource, StaticResources } from "../util/resources" import { JSResource, StaticResources } from "../util/resources"
import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace"
import { ProcessedContent } from "./vfile" import { ProcessedContent } from "./vfile"
import { QuartzComponent } from "../components/types" import { QuartzComponent } from "../components/types"
import { FilePath } from "../util/path" import { FilePath } from "../util/path"
@ -56,7 +57,7 @@ export type QuartzParser<Options extends OptionType = undefined> = (
export type QuartzParserInstance = { export type QuartzParserInstance = {
name: string name: string
textTransform: (ctx: BuildCtx, src: string | Buffer) => string | Buffer textTransform: (ctx: BuildCtx, src: string | Buffer) => string | Buffer
markdownPlugins: (ctx: BuildCtx) => Pluggable markdownPlugins: (ctx: BuildCtx) => [RegExp, string | ReplaceFunction][]
htmlPlugins: () => Pluggable | Pluggable[] htmlPlugins: () => Pluggable | Pluggable[]
externalResources: () => JSResource | string externalResources: () => JSResource | string
} }