The Trans Directory
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: header and full-page transcludes (closes #557)

+75 -14
+70 -11
quartz/components/renderPage.tsx
··· 5 5 import { JSResourceToScriptElement, StaticResources } from "../util/resources" 6 6 import { FullSlug, RelativeURL, joinSegments } from "../util/path" 7 7 import { visit } from "unist-util-visit" 8 - import { Root, Element } from "hast" 8 + import { Root, Element, ElementContent } from "hast" 9 9 10 10 interface RenderComponents { 11 11 head: QuartzComponent ··· 61 61 const classNames = (node.properties?.className ?? []) as string[] 62 62 if (classNames.includes("transclude")) { 63 63 const inner = node.children[0] as Element 64 - const blockSlug = inner.properties?.["data-slug"] as FullSlug 65 - const blockRef = node.properties!.dataBlock as string 64 + const transcludeTarget = inner.properties?.["data-slug"] as FullSlug 66 65 67 66 // TODO: avoid this expensive find operation and construct an index ahead of time 68 - let blockNode = componentData.allFiles.find((f) => f.slug === blockSlug)?.blocks?.[blockRef] 69 - if (blockNode) { 70 - if (blockNode.tagName === "li") { 71 - blockNode = { 72 - type: "element", 73 - tagName: "ul", 74 - children: [blockNode], 67 + const page = componentData.allFiles.find((f) => f.slug === transcludeTarget) 68 + if (!page) { 69 + return 70 + } 71 + 72 + let blockRef = node.properties?.dataBlock as string | undefined 73 + if (blockRef?.startsWith("^")) { 74 + // block transclude 75 + blockRef = blockRef.slice(1) 76 + let blockNode = page.blocks?.[blockRef] 77 + if (blockNode) { 78 + if (blockNode.tagName === "li") { 79 + blockNode = { 80 + type: "element", 81 + tagName: "ul", 82 + children: [blockNode], 83 + } 84 + } 85 + 86 + node.children = [ 87 + blockNode, 88 + { 89 + type: "element", 90 + tagName: "a", 91 + properties: { href: inner.properties?.href, class: ["internal"] }, 92 + children: [{ type: "text", value: `Link to original` }], 93 + }, 94 + ] 95 + } 96 + } else if (blockRef?.startsWith("#") && page.htmlAst) { 97 + // header transclude 98 + blockRef = blockRef.slice(1) 99 + let startIdx = undefined 100 + let endIdx = undefined 101 + for (const [i, el] of page.htmlAst.children.entries()) { 102 + if (el.type === "element" && el.tagName.match(/h[1-6]/)) { 103 + if (endIdx) { 104 + break 105 + } 106 + 107 + if (startIdx) { 108 + endIdx = i 109 + } else if (el.properties?.id === blockRef) { 110 + startIdx = i 111 + } 75 112 } 113 + } 114 + 115 + if (!startIdx) { 116 + return 76 117 } 77 118 78 119 node.children = [ 79 - blockNode, 120 + ...(page.htmlAst.children.slice(startIdx, endIdx) as ElementContent[]), 121 + { 122 + type: "element", 123 + tagName: "a", 124 + properties: { href: inner.properties?.href, class: ["internal"] }, 125 + children: [{ type: "text", value: `Link to original` }], 126 + }, 127 + ] 128 + } else if (page.htmlAst) { 129 + // page transclude 130 + node.children = [ 131 + { 132 + type: "element", 133 + tagName: "h1", 134 + children: [ 135 + { type: "text", value: page.frontmatter?.title ?? `Transclude of ${page.slug}` }, 136 + ], 137 + }, 138 + ...(page.htmlAst.children as ElementContent[]), 80 139 { 81 140 type: "element", 82 141 tagName: "a",
+5 -3
quartz/plugins/transformers/ofm.ts
··· 1 1 import { PluggableList } from "unified" 2 2 import { QuartzTransformerPlugin } from "../types" 3 3 import { Root, HTML, BlockContent, DefinitionContent, Code, Paragraph } from "mdast" 4 - import { Element, Literal } from "hast" 4 + import { Element, Literal, Root as HtmlRoot } from "hast" 5 5 import { Replace, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace" 6 6 import { slug as slugAnchor } from "github-slugger" 7 7 import rehypeRaw from "rehype-raw" ··· 236 236 value: `<iframe src="${url}"></iframe>`, 237 237 } 238 238 } else if (ext === "") { 239 - const block = anchor.slice(1) 239 + const block = anchor 240 240 return { 241 241 type: "html", 242 242 data: { hProperties: { transclude: true } }, 243 243 value: `<blockquote class="transclude" data-url="${url}" data-block="${block}"><a href="${ 244 244 url + anchor 245 - }" class="transclude-inner">Transclude of block ${block}</a></blockquote>`, 245 + }" class="transclude-inner">Transclude of ${url}${block}</a></blockquote>`, 246 246 } 247 247 } 248 248 ··· 436 436 const blockTagTypes = new Set(["blockquote"]) 437 437 return (tree, file) => { 438 438 file.data.blocks = {} 439 + file.data.htmlAst = tree 439 440 440 441 visit(tree, "element", (node, index, parent) => { 441 442 if (blockTagTypes.has(node.tagName)) { ··· 524 525 declare module "vfile" { 525 526 interface DataMap { 526 527 blocks: Record<string, Element> 528 + htmlAst: HtmlRoot 527 529 } 528 530 }