diff --git a/package-lock.json b/package-lock.json index 1898a462a..fb0dca1ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -41,6 +41,7 @@ "reading-time": "^1.5.0", "rehype-autolink-headings": "^7.1.0", "rehype-citation": "^2.1.2", + "rehype-image-caption": "^2.0.10", "rehype-katex": "^7.0.1", "rehype-mathjax": "^6.0.0", "rehype-pretty-code": "^0.14.0", @@ -3863,9 +3864,10 @@ } }, "node_modules/mdast-util-mdx-jsx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.0.0.tgz", - "integrity": "sha512-XZuPPzQNBPAlaqsTTgRrcJnyFbSOBovSadFgbFu8SnuNgm+6Bdx1K+IWoitsmj6Lq6MNtI+ytOqwN70n//NaBA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.1.3.tgz", + "integrity": "sha512-bfOjvNt+1AcbPLTFMFWY149nJz0OjmewJs3LQQ5pIyVGxP4CdOqNVJL6kTaM5c68p8q82Xv3nCyFfUnuEcH3UQ==", + "license": "MIT", "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", @@ -3877,7 +3879,6 @@ "mdast-util-to-markdown": "^2.0.0", "parse-entities": "^4.0.0", "stringify-entities": "^4.0.0", - "unist-util-remove-position": "^5.0.0", "unist-util-stringify-position": "^4.0.0", "vfile-message": "^4.0.0" }, @@ -5025,6 +5026,22 @@ "resolved": "https://registry.npmjs.org/regex/-/regex-4.3.3.tgz", "integrity": "sha512-r/AadFO7owAq1QJVeZ/nq9jNS1vyZt+6t1p/E59B56Rn2GCya+gr1KSyOzNL/er+r+B7phv5jG2xU2Nz1YkmJg==" }, + "node_modules/rehype": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", + "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "rehype-parse": "^9.0.0", + "rehype-stringify": "^10.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/rehype-autolink-headings": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-7.1.0.tgz", @@ -5063,6 +5080,19 @@ "unist-util-visit": "^5.0.0" } }, + "node_modules/rehype-image-caption": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/rehype-image-caption/-/rehype-image-caption-2.0.10.tgz", + "integrity": "sha512-iwm0gnR6Z3svaM8i34mS8GCHFCNnV9Ot3RCv1zteAPb8m3s0oqcwcZYdyZPLXrfQ3PdMH7eo6k7RJyuPIQrgHA==", + "license": "MIT", + "dependencies": { + "hast-util-is-element": "^3.0.0", + "mdast-util-mdx-jsx": "^3.1.2", + "rehype": "^13.0.1", + "unified": "^11.0.4", + "unist-util-visit": "^5.0.0" + } + }, "node_modules/rehype-katex": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/rehype-katex/-/rehype-katex-7.0.1.tgz", @@ -5223,6 +5253,21 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/rehype-stringify": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", + "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", + "license": "MIT", + "dependencies": { + "@types/hast": "^3.0.0", + "hast-util-to-html": "^9.0.0", + "unified": "^11.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/remark": { "version": "15.0.1", "resolved": "https://registry.npmjs.org/remark/-/remark-15.0.1.tgz", diff --git a/package.json b/package.json index 415fc68b6..d2f1a71ce 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "reading-time": "^1.5.0", "rehype-autolink-headings": "^7.1.0", "rehype-citation": "^2.1.2", + "rehype-image-caption": "^2.0.10", "rehype-katex": "^7.0.1", "rehype-mathjax": "^6.0.0", "rehype-pretty-code": "^0.14.0", diff --git a/quartz.config.ts b/quartz.config.ts index e96ee4843..ae5d9893c 100644 --- a/quartz.config.ts +++ b/quartz.config.ts @@ -72,6 +72,12 @@ const config: QuartzConfig = { Plugin.CrawlLinks({ markdownLinkResolution: "shortest" }), Plugin.Description(), Plugin.Latex({ renderEngine: "katex" }), + // Adds image caption support. Syntax: + // ```md + // ![alt text](image.jpg) + // *caption text* + // ``` + Plugin.FigureCaptions() ], filters: [Plugin.RemoveDrafts()], emitters: [ diff --git a/quartz/plugins/transformers/figcaptions.ts b/quartz/plugins/transformers/figcaptions.ts new file mode 100644 index 000000000..6d10e8e41 --- /dev/null +++ b/quartz/plugins/transformers/figcaptions.ts @@ -0,0 +1,11 @@ +import rehypeImageCaption from "rehype-image-caption"; +import { QuartzTransformerPlugin } from "../types"; + +export const FigureCaptions: QuartzTransformerPlugin = () => { + return { + name: "FigureCaptions", + htmlPlugins() { + return [[rehypeImageCaption]] + }, + } +} \ No newline at end of file diff --git a/quartz/plugins/transformers/index.ts b/quartz/plugins/transformers/index.ts index 8e2cd844f..b06f9df97 100644 --- a/quartz/plugins/transformers/index.ts +++ b/quartz/plugins/transformers/index.ts @@ -11,3 +11,4 @@ export { SyntaxHighlighting } from "./syntax" export { TableOfContents } from "./toc" export { HardLineBreaks } from "./linebreaks" export { RoamFlavoredMarkdown } from "./roam" +export { FigureCaptions } from "./figcaptions" \ No newline at end of file diff --git a/quartz/styles/base.scss b/quartz/styles/base.scss index 61c918f42..12abf37c4 100644 --- a/quartz/styles/base.scss +++ b/quartz/styles/base.scss @@ -586,3 +586,24 @@ iframe.pdf { width: 100%; border-radius: 5px; } + +// ========== Image captions ========== + +figure { + margin: 0; + + > img { + display: block; + margin: 0 auto; + } +} + +figcaption { + text-align: center; + margin-top: .25rem; + font-size: .85rem; + line-height: 1.3rem; + opacity: .8; +} + +// ==================================== \ No newline at end of file