summaryrefslogtreecommitdiff
path: root/src/plugins/rehype-image-captions.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/rehype-image-captions.ts')
-rw-r--r--src/plugins/rehype-image-captions.ts78
1 files changed, 78 insertions, 0 deletions
diff --git a/src/plugins/rehype-image-captions.ts b/src/plugins/rehype-image-captions.ts
new file mode 100644
index 0000000..61bdd84
--- /dev/null
+++ b/src/plugins/rehype-image-captions.ts
@@ -0,0 +1,78 @@
+import type { Element, Root } from "hast";
+import { h } from "hastscript";
+import type { Plugin } from "unified";
+import { visit } from "unist-util-visit";
+
+/**
+ * Rehype plugin that wraps images with figure/figcaption to display alt text on hover.
+ * Skips images without alt text or with generic alt text like "Image".
+ */
+export const rehypeImageCaptions: Plugin<[], Root> = () => {
+ return (tree: Root) => {
+ visit(tree, "element", (node: Element, index, parent) => {
+ // Only process img elements that have a parent and an index
+ if (node.tagName !== "img" || !parent || index === undefined) {
+ return;
+ }
+
+ // Get the alt text
+ const alt = node.properties?.alt;
+ if (!alt || typeof alt !== "string") {
+ return;
+ }
+
+ // Skip generic or empty alt text
+ const trimmedAlt = alt.trim();
+ if (!trimmedAlt || trimmedAlt.toLowerCase() === "image") {
+ return;
+ }
+
+ // Preserve all existing properties including data-zoomable for medium-zoom
+ const imgProperties = { ...node.properties };
+
+ // Create the figcaption element with tailwind classes for hover overlay
+ const figcaption = h(
+ "figcaption",
+ {
+ class: [
+ "pointer-events-none",
+ "absolute",
+ "bottom-0",
+ "left-0",
+ "right-0",
+ "rounded-b-lg",
+ "bg-black/70",
+ "px-3",
+ "py-2",
+ "text-sm",
+ "text-white",
+ "opacity-0",
+ "transition-opacity",
+ "group-hover:opacity-100",
+ ].join(" "),
+ },
+ [{ type: "text", value: trimmedAlt }],
+ );
+
+ // Create the figure wrapper with group class for hover trigger
+ const figure = h(
+ "figure",
+ {
+ class: "image-with-alt group relative",
+ },
+ [
+ {
+ type: "element",
+ tagName: "img",
+ properties: imgProperties,
+ children: [],
+ },
+ figcaption,
+ ],
+ );
+
+ // Replace the img with the figure in the parent
+ parent.children[index] = figure;
+ });
+ };
+};