diff --git a/quartz/components/pages/404.tsx b/quartz/components/pages/404.tsx index 3583b0399..2076ad7d1 100644 --- a/quartz/components/pages/404.tsx +++ b/quartz/components/pages/404.tsx @@ -1,11 +1,11 @@ -import {i18n} from "../../i18n" -import { - QuartzComponent, - QuartzComponentConstructor, - QuartzComponentProps, -} from "../types" +import { i18n } from "../../i18n" +import { QuartzComponent, QuartzComponentConstructor, QuartzComponentProps } from "../types" + +const NotFound: QuartzComponent = ({ cfg }: QuartzComponentProps) => { + // If baseUrl contains a pathname after the domain, use this as the home link + const url = new URL(`https://${cfg.baseUrl ?? "example.com"}`) + const baseDir = url.pathname -const NotFound: QuartzComponent = ({cfg}: QuartzComponentProps) => { return (

404

@@ -15,4 +15,4 @@ const NotFound: QuartzComponent = ({cfg}: QuartzComponentProps) => { ) } -export default (() => NotFound) satisfies QuartzComponentConstructor +export default (() => NotFound) satisfies QuartzComponentConstructor \ No newline at end of file diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts index 6ef9ea6ee..f4f6066d1 100644 --- a/quartz/plugins/transformers/ofm.ts +++ b/quartz/plugins/transformers/ofm.ts @@ -1,32 +1,22 @@ -import {QuartzTransformerPlugin} from "../types" -import { - Root, - Html, - BlockContent, - DefinitionContent, - Paragraph, - Code, -} from "mdast" -import {Element, Literal, Root as HtmlRoot} from "hast" -import { - ReplaceFunction, - findAndReplace as mdastFindReplace, -} from "mdast-util-find-and-replace" -import {slug as slugAnchor} from "github-slugger" +import { QuartzTransformerPlugin } from "../types" +import { Root, Html, BlockContent, DefinitionContent, Paragraph, Code } from "mdast" +import { Element, Literal, Root as HtmlRoot } from "hast" +import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace" +import { slug as slugAnchor } from "github-slugger" import rehypeRaw from "rehype-raw" -import {SKIP, visit} from "unist-util-visit" +import { SKIP, visit } from "unist-util-visit" import path from "path" -import {JSResource} from "../../util/resources" +import { JSResource } from "../../util/resources" // @ts-ignore import calloutScript from "../../components/scripts/callout.inline.ts" // @ts-ignore import checkboxScript from "../../components/scripts/checkbox.inline.ts" -import {FilePath, pathToRoot, slugTag, slugifyFilePath} from "../../util/path" -import {toHast} from "mdast-util-to-hast" -import {toHtml} from "hast-util-to-html" -import {PhrasingContent} from "mdast-util-find-and-replace/lib" -import {capitalize} from "../../util/lang" -import {PluggableList} from "unified" +import { FilePath, pathToRoot, slugTag, slugifyFilePath } from "../../util/path" +import { toHast } from "mdast-util-to-hast" +import { toHtml } from "hast-util-to-html" +import { PhrasingContent } from "mdast-util-find-and-replace/lib" +import { capitalize } from "../../util/lang" +import { PluggableList } from "unified" export interface Options { comments: boolean @@ -100,8 +90,7 @@ const arrowMapping: Record = { } function canonicalizeCallout(calloutName: string): keyof typeof calloutMapping { - const normalizedCallout = - calloutName.toLowerCase() as keyof typeof calloutMapping + const normalizedCallout = calloutName.toLowerCase() as keyof typeof calloutMapping // if callout is not recognized, make it a custom one return calloutMapping[normalizedCallout] ?? calloutName } @@ -145,24 +134,21 @@ const tagRegex = new RegExp( "gu", ) const blockReferenceRegex = new RegExp(/\^([-_A-Za-z0-9]+)$/, "g") -const ytLinkRegex = - /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/ +const ytLinkRegex = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/ const ytPlaylistLinkRegex = /[?&]list=([^#?&]*)/ -const videoExtensionRegex = new RegExp( - /\.(mp4|webm|ogg|avi|mov|flv|wmv|mkv|mpg|mpeg|3gp|m4v)$/, -) +const videoExtensionRegex = new RegExp(/\.(mp4|webm|ogg|avi|mov|flv|wmv|mkv|mpg|mpeg|3gp|m4v)$/) const wikilinkImageEmbedRegex = new RegExp( /^(?(?!^\d*x?\d*$).*?)?(\|?\s*?(?\d+)(x(?\d+))?)?$/, ) -export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< - Partial | undefined -> = (userOpts) => { - const opts = {...defaultOptions, ...userOpts} +export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin | undefined> = ( + userOpts, +) => { + const opts = { ...defaultOptions, ...userOpts } const mdastToHtml = (ast: PhrasingContent | Paragraph) => { - const hast = toHast(ast, {allowDangerousHtml: true})! - return toHtml(hast, {allowDangerousHtml: true}) + const hast = toHast(ast, { allowDangerousHtml: true })! + return toHtml(hast, { allowDangerousHtml: true }) } return { @@ -216,10 +202,8 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< const fp = rawFp ?? "" const anchor = rawHeader?.trim().replace(/^#+/, "") const blockRef = Boolean(anchor?.startsWith("^")) ? "^" : "" - const displayAnchor = anchor - ? `#${blockRef}${slugAnchor(anchor)}` - : "" - let displayAlias = rawAlias ?? rawHeader?.replace("#", "|") ?? "" + const displayAnchor = anchor ? `#${blockRef}${slugAnchor(anchor)}` : "" + const displayAlias = rawAlias ?? rawHeader?.replace("#", "|") ?? "" const embedDisplay = value.startsWith("!") ? "!" : "" if (rawFp?.match(externalLinkRegex)) { @@ -254,17 +238,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< if (value.startsWith("!")) { const ext: string = path.extname(fp).toLowerCase() 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 alt = match?.groups?.alt ?? "" const width = match?.groups?.width ?? "auto" @@ -280,23 +254,13 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< }, }, } - } else if ( - [".mp4", ".webm", ".ogv", ".mov", ".mkv"].includes(ext) - ) { + } else if ([".mp4", ".webm", ".ogv", ".mov", ".mkv"].includes(ext)) { return { type: "html", value: ``, } } else if ( - [ - ".mp3", - ".webm", - ".wav", - ".m4a", - ".ogg", - ".3gp", - ".flac", - ].includes(ext) + [".mp3", ".webm", ".wav", ".m4a", ".ogg", ".3gp", ".flac"].includes(ext) ) { return { type: "html", @@ -311,7 +275,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< const block = anchor return { type: "html", - data: {hProperties: {transclude: true}}, + data: { hProperties: { transclude: true } }, value: `
Transclude of ${url}${block}
`, @@ -404,24 +368,18 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< if (typeof replace === "string") { node.value = node.value.replace(regex, replace) } else { - node.value = node.value.replace( - regex, - (substring: string, ...args) => { - const replaceValue = replace(substring, ...args) - if (typeof replaceValue === "string") { - return replaceValue - } else if (Array.isArray(replaceValue)) { - return replaceValue.map(mdastToHtml).join("") - } else if ( - typeof replaceValue === "object" && - replaceValue !== null - ) { - return mdastToHtml(replaceValue) - } else { - return substring - } - }, - ) + node.value = node.value.replace(regex, (substring: string, ...args) => { + const replaceValue = replace(substring, ...args) + if (typeof replaceValue === "string") { + return replaceValue + } else if (Array.isArray(replaceValue)) { + return replaceValue.map(mdastToHtml).join("") + } else if (typeof replaceValue === "object" && replaceValue !== null) { + return mdastToHtml(replaceValue) + } else { + return substring + } + }) } } }) @@ -434,11 +392,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< plugins.push(() => { return (tree: Root, _file) => { visit(tree, "image", (node, index, parent) => { - if ( - parent && - index != undefined && - videoExtensionRegex.test(node.url) - ) { + if (parent && index != undefined && videoExtensionRegex.test(node.url)) { const newNode: Html = { type: "html", value: ``, @@ -462,10 +416,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< // find first line const firstChild = node.children[0] - if ( - firstChild.type !== "paragraph" || - firstChild.children[0]?.type !== "text" - ) { + if (firstChild.type !== "paragraph" || firstChild.children[0]?.type !== "text") { return } @@ -476,26 +427,18 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< const match = firstLine.match(calloutRegex) if (match && match.input) { - const [calloutDirective, typeString, collapseChar] = match - const calloutType = canonicalizeCallout( - typeString.toLowerCase(), - ) + const [calloutDirective, typeString, calloutMetaData, collapseChar] = match + const calloutType = canonicalizeCallout(typeString.toLowerCase()) const collapse = collapseChar === "+" || collapseChar === "-" - const defaultState = - collapseChar === "-" ? "collapsed" : "expanded" - const titleContent = match.input - .slice(calloutDirective.length) - .trim() - const useDefaultTitle = - titleContent === "" && restOfTitle.length === 0 + const defaultState = collapseChar === "-" ? "collapsed" : "expanded" + const titleContent = match.input.slice(calloutDirective.length).trim() + const useDefaultTitle = titleContent === "" && restOfTitle.length === 0 const titleNode: Paragraph = { type: "paragraph", children: [ { type: "text", - value: useDefaultTitle - ? capitalize(typeString) - : titleContent + " ", + value: useDefaultTitle ? capitalize(typeString) : titleContent + " ", }, ...restOfTitle, ], @@ -515,8 +458,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< `, } - const blockquoteContent: (BlockContent | DefinitionContent)[] = - [titleHtml] + const blockquoteContent: (BlockContent | DefinitionContent)[] = [titleHtml] if (remainingText.length > 0) { blockquoteContent.push({ type: "paragraph", @@ -544,7 +486,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< node.data = { hProperties: { ...(node.data?.hProperties ?? {}), - "className": classNames.join(" "), + className: classNames.join(" "), "data-callout": calloutType, "data-callout-fold": collapse, "data-callout-metadata": calloutMetaData, @@ -657,14 +599,10 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< plugins.push(() => { return (tree: HtmlRoot) => { visit(tree, "element", (node) => { - if ( - node.tagName === "img" && - typeof node.properties.src === "string" - ) { + if (node.tagName === "img" && typeof node.properties.src === "string") { const match = node.properties.src.match(ytLinkRegex) const videoId = match && match[2].length == 11 ? match[2] : null - const playlistId = - node.properties.src.match(ytPlaylistLinkRegex)?.[1] + const playlistId = node.properties.src.match(ytPlaylistLinkRegex)?.[1] if (videoId) { // YouTube video (with optional playlist) node.tagName = "iframe" @@ -700,10 +638,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< plugins.push(() => { return (tree: HtmlRoot, _file) => { visit(tree, "element", (node) => { - if ( - node.tagName === "input" && - node.properties.type === "checkbox" - ) { + if (node.tagName === "input" && node.properties.type === "checkbox") { const isChecked = node.properties?.checked ?? false node.properties = { type: "checkbox", @@ -765,7 +700,7 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin< }) } - return {js} + return { js } }, } } @@ -775,4 +710,4 @@ declare module "vfile" { blocks: Record htmlAst: HtmlRoot } -} +} \ No newline at end of file