From a70e846b0a14f3065bbf613221fee0e3b09c12ef Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Tue, 1 Aug 2023 22:47:16 -0700 Subject: [PATCH] flag to allow ofm replace in html embed --- content/advanced/architecture.md | 1 + content/advanced/paths.md | 0 content/configuration.md | 22 +++++++++- content/index.md | 2 +- package-lock.json | 63 ++++++++++++++++++++++++++-- package.json | 2 + quartz/plugins/transformers/links.ts | 1 + quartz/plugins/transformers/ofm.ts | 40 +++++++++++++++++- 8 files changed, 124 insertions(+), 7 deletions(-) create mode 100644 content/advanced/architecture.md create mode 100644 content/advanced/paths.md diff --git a/content/advanced/architecture.md b/content/advanced/architecture.md new file mode 100644 index 000000000..688fd75f8 --- /dev/null +++ b/content/advanced/architecture.md @@ -0,0 +1 @@ +how does quartz work? great question lol diff --git a/content/advanced/paths.md b/content/advanced/paths.md new file mode 100644 index 000000000..e69de29bb diff --git a/content/configuration.md b/content/configuration.md index 1545d66b7..e31dbc2d7 100644 --- a/content/configuration.md +++ b/content/configuration.md @@ -79,6 +79,26 @@ If you'd like to make your own plugins, read the guide on [[making plugins]] for ### Layout -Certain emitters may also output [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML) files. To enable easy customization, these emitters allow you to fully rearrange the layout of the page. +Certain emitters may also output [HTML](https://developer.mozilla.org/en-US/docs/Web/HTML) files. To enable easy customization, these emitters allow you to fully rearrange the layout of the page. The default page layouts can be found in `quartz.layout.ts`. + +Ultimately, each page is composed of multiple different sections which contain `QuartzComponents`. The following code snippet lists all of the valid sections that you can add components to: + +```typescript title="quartz/cfg.ts" +export interface FullPageLayout { + head: QuartzComponent + header: QuartzComponent[] + beforeBody: QuartzComponent[] + pageBody: QuartzComponent + left: QuartzComponent[] + right: QuartzComponent[] + footer: QuartzComponent +} +``` + +These correspond to following parts of the page: ### Components + +See [a list of all the components](./tags/component) for all available components. + +### Style diff --git a/content/index.md b/content/index.md index 5c32c23d9..050ce78ac 100644 --- a/content/index.md +++ b/content/index.md @@ -6,7 +6,7 @@ Quartz is a fast, batteries-included static-site generator that transforms Markd ## 🪴 Get Started -Quartz requires **at least [Node](https://nodejs.org/) v16** to function correctly. In your terminal of choice, enter the following commands line by line: +Quartz requires **at least [Node](https://nodejs.org/) v18.14** to function correctly. In your terminal of choice, enter the following commands line by line: ```shell git clone https://github.com/jackyzha0/quartz.git diff --git a/package-lock.json b/package-lock.json index 7bb72bc25..3e106a656 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,12 +21,14 @@ "github-slugger": "^2.0.0", "globby": "^13.1.4", "gray-matter": "^4.0.3", + "hast-util-to-html": "^8.0.4", "hast-util-to-jsx-runtime": "^1.2.0", "hast-util-to-string": "^2.0.0", "is-absolute-url": "^4.0.1", "js-yaml": "^4.1.0", "lightningcss": "^1.21.5", "mdast-util-find-and-replace": "^2.2.2", + "mdast-util-to-hast": "^12.3.0", "mdast-util-to-string": "^3.2.0", "micromorph": "^0.4.5", "plausible-tracker": "^0.3.8", @@ -1414,11 +1416,11 @@ "dev": true }, "node_modules/@types/hast": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.4.tgz", - "integrity": "sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==", + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@types/hast/-/hast-2.3.5.tgz", + "integrity": "sha512-SvQi0L/lNpThgPoleH53cdjB3y9zpLlVjRbqB3rH8hx1jiRSBGAhyjV3H+URFjNVRqt2EdYNrbZE5IsGlNfpRg==", "dependencies": { - "@types/unist": "*" + "@types/unist": "^2" } }, "node_modules/@types/js-yaml": { @@ -1736,6 +1738,24 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/character-entities-html4": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", + "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/character-entities-legacy": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", + "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -2972,6 +2992,28 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" }, + "node_modules/hast-util-to-html": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-8.0.4.tgz", + "integrity": "sha512-4tpQTUOr9BMjtYyNlt0P50mH7xj0Ks2xpo8M943Vykljf99HW6EzulIoJP1N3eKOSScEHzyzi9dm7/cn0RfGwA==", + "dependencies": { + "@types/hast": "^2.0.0", + "@types/unist": "^2.0.0", + "ccount": "^2.0.0", + "comma-separated-tokens": "^2.0.0", + "hast-util-raw": "^7.0.0", + "hast-util-whitespace": "^2.0.0", + "html-void-elements": "^2.0.0", + "property-information": "^6.0.0", + "space-separated-tokens": "^2.0.0", + "stringify-entities": "^4.0.0", + "zwitch": "^2.0.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/hast-util-to-jsx-runtime": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-1.2.0.tgz", @@ -5404,6 +5446,19 @@ "node": ">=8" } }, + "node_modules/stringify-entities": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.3.tgz", + "integrity": "sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==", + "dependencies": { + "character-entities-html4": "^2.0.0", + "character-entities-legacy": "^3.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/strip-ansi": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", diff --git a/package.json b/package.json index cfd1d1551..8a1d483c7 100644 --- a/package.json +++ b/package.json @@ -40,12 +40,14 @@ "github-slugger": "^2.0.0", "globby": "^13.1.4", "gray-matter": "^4.0.3", + "hast-util-to-html": "^8.0.4", "hast-util-to-jsx-runtime": "^1.2.0", "hast-util-to-string": "^2.0.0", "is-absolute-url": "^4.0.1", "js-yaml": "^4.1.0", "lightningcss": "^1.21.5", "mdast-util-find-and-replace": "^2.2.2", + "mdast-util-to-hast": "^12.3.0", "mdast-util-to-string": "^3.2.0", "micromorph": "^0.4.5", "plausible-tracker": "^0.3.8", diff --git a/quartz/plugins/transformers/links.ts b/quartz/plugins/transformers/links.ts index 7e8a2788b..f5bfdfc62 100644 --- a/quartz/plugins/transformers/links.ts +++ b/quartz/plugins/transformers/links.ts @@ -47,6 +47,7 @@ export const CrawlLinks: QuartzTransformerPlugin | undefined> = return targetCanonical === fileName }) + // only match, just use it if (matchingFileNames.length === 1) { const targetSlug = canonicalizeServer(matchingFileNames[0]) return (resolveRelative(curSlug, targetSlug) + targetAnchor) as RelativeURL diff --git a/quartz/plugins/transformers/ofm.ts b/quartz/plugins/transformers/ofm.ts index 4a45b0214..23b97d6f2 100644 --- a/quartz/plugins/transformers/ofm.ts +++ b/quartz/plugins/transformers/ofm.ts @@ -1,7 +1,7 @@ import { PluggableList } from "unified" import { QuartzTransformerPlugin } from "../types" import { Root, HTML, BlockContent, DefinitionContent, Code } from "mdast" -import { findAndReplace } from "mdast-util-find-and-replace" +import { Replace, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace" import { slug as slugAnchor } from "github-slugger" import rehypeRaw from "rehype-raw" import { visit } from "unist-util-visit" @@ -10,6 +10,9 @@ import { JSResource } from "../../resources" // @ts-ignore import calloutScript from "../../components/scripts/callout.inline.ts" import { FilePath, canonicalizeServer, pathToRoot, slugTag, slugifyFilePath } from "../../path" +import { toHast } from "mdast-util-to-hast" +import { toHtml } from "hast-util-to-html" +import { PhrasingContent } from "mdast-util-find-and-replace/lib" export interface Options { comments: boolean @@ -18,6 +21,7 @@ export interface Options { callouts: boolean mermaid: boolean parseTags: boolean + enableInHtmlEmbed: boolean } const defaultOptions: Options = { @@ -27,6 +31,7 @@ const defaultOptions: Options = { callouts: true, mermaid: true, parseTags: true, + enableInHtmlEmbed: false, } const icons = { @@ -117,6 +122,39 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin userOpts, ) => { const opts = { ...defaultOptions, ...userOpts } + + const findAndReplace = opts.enableInHtmlEmbed + ? (tree: Root, regex: RegExp, replace?: Replace | null | undefined) => { + if (replace) { + const mdastToHtml = (ast: PhrasingContent) => { + const hast = toHast(ast, { allowDangerousHtml: true })! + return toHtml(hast, { allowDangerousHtml: true }) + } + + visit(tree, "html", (node: HTML) => { + if (typeof replace === "string") { + node.value = node.value.replace(regex, replace) + } else { + node.value = node.value.replaceAll(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 + } + }) + } + }) + } + + mdastFindReplace(tree, regex, replace) + } + : mdastFindReplace + return { name: "ObsidianFlavoredMarkdown", textTransform(_ctx, src) {