mirror of
https://github.com/jackyzha0/quartz.git
synced 2025-12-31 00:34:05 -06:00
Obsidian Parser (BlockReference)
This commit is contained in:
parent
cd527754a8
commit
7ed79cd27f
@ -0,0 +1,118 @@
|
|||||||
|
import { QuartzParser } from "../../types"
|
||||||
|
import { ReplaceFunction, findAndReplace as mdastFindReplace } from "mdast-util-find-and-replace"
|
||||||
|
import { JSResource } from "../../../util/resources"
|
||||||
|
import { visit } from "unist-util-visit"
|
||||||
|
import { Root } from "mdast"
|
||||||
|
import { Pluggable } from "unified"
|
||||||
|
import { Element, Literal, Root as HtmlRoot } from "hast"
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
enabled: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
const defaultOptions: Options = {
|
||||||
|
enabled: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
const blockReferenceRegex = new RegExp(/\^([-_A-Za-z0-9]+)$/g)
|
||||||
|
|
||||||
|
export const ObsidianBlockReference: QuartzParser<Partial<Options>> = (userOpts) => {
|
||||||
|
const opts: Options = { ...defaultOptions, ...userOpts }
|
||||||
|
return {
|
||||||
|
name: "ObsidianBlockReference",
|
||||||
|
textTransform(_ctx, src: string | Buffer) {
|
||||||
|
if (src instanceof Buffer) {
|
||||||
|
src = src.toString()
|
||||||
|
}
|
||||||
|
return src
|
||||||
|
},
|
||||||
|
markdownPlugins(_ctx) {
|
||||||
|
const plug: Pluggable = (tree: Root, _file) => {
|
||||||
|
const replacements: [RegExp, string | ReplaceFunction][] = []
|
||||||
|
mdastFindReplace(tree, replacements)
|
||||||
|
}
|
||||||
|
return plug
|
||||||
|
},
|
||||||
|
htmlPlugins() {
|
||||||
|
const inlineTagTypes = new Set(["p", "li"])
|
||||||
|
const blockTagTypes = new Set(["blockquote"])
|
||||||
|
if (opts.enabled) {
|
||||||
|
const plug: Pluggable = (tree: HtmlRoot, file) => {
|
||||||
|
file.data.blocks = {}
|
||||||
|
|
||||||
|
visit(tree, "element", (node, index, parent) => {
|
||||||
|
if (blockTagTypes.has(node.tagName)) {
|
||||||
|
const nextChild = parent?.children.at(index! + 2) as Element
|
||||||
|
if (nextChild && nextChild.tagName === "p") {
|
||||||
|
const text = nextChild.children.at(0) as Literal
|
||||||
|
if (text && text.value && text.type === "text") {
|
||||||
|
const matches = text.value.match(blockReferenceRegex)
|
||||||
|
if (matches && matches.length >= 1) {
|
||||||
|
parent!.children.splice(index! + 2, 1)
|
||||||
|
const block = matches[0].slice(1)
|
||||||
|
|
||||||
|
if (!Object.keys(file.data.blocks!).includes(block)) {
|
||||||
|
node.properties = {
|
||||||
|
...node.properties,
|
||||||
|
id: block,
|
||||||
|
}
|
||||||
|
file.data.blocks![block] = node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (inlineTagTypes.has(node.tagName)) {
|
||||||
|
const last = node.children.at(-1) as Literal
|
||||||
|
if (last && last.value && typeof last.value === "string") {
|
||||||
|
const matches = last.value.match(blockReferenceRegex)
|
||||||
|
if (matches && matches.length >= 1) {
|
||||||
|
last.value = last.value.slice(0, -matches[0].length)
|
||||||
|
const block = matches[0].slice(1)
|
||||||
|
|
||||||
|
if (last.value === "") {
|
||||||
|
// this is an inline block ref but the actual block
|
||||||
|
// is the previous element above it
|
||||||
|
let idx = (index ?? 1) - 1
|
||||||
|
while (idx >= 0) {
|
||||||
|
const element = parent?.children.at(idx)
|
||||||
|
if (!element) break
|
||||||
|
if (element.type !== "element") {
|
||||||
|
idx -= 1
|
||||||
|
} else {
|
||||||
|
if (!Object.keys(file.data.blocks!).includes(block)) {
|
||||||
|
element.properties = {
|
||||||
|
...element.properties,
|
||||||
|
id: block,
|
||||||
|
}
|
||||||
|
file.data.blocks![block] = element
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// normal paragraph transclude
|
||||||
|
if (!Object.keys(file.data.blocks!).includes(block)) {
|
||||||
|
node.properties = {
|
||||||
|
...node.properties,
|
||||||
|
id: block,
|
||||||
|
}
|
||||||
|
file.data.blocks![block] = node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
file.data.htmlAst = tree
|
||||||
|
}
|
||||||
|
return plug
|
||||||
|
}
|
||||||
|
return {} as Pluggable
|
||||||
|
},
|
||||||
|
externalResources() {
|
||||||
|
const js = {} as JSResource
|
||||||
|
return js
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,5 @@
|
|||||||
export { ObsidianArrow } from "./arrows"
|
export { ObsidianArrow } from "./arrows"
|
||||||
|
export { ObsidianBlockReference } from "./blockreference"
|
||||||
export { ObsidianCallouts } from "./callouts"
|
export { ObsidianCallouts } from "./callouts"
|
||||||
export { ObsidianCheckboxes } from "./checkboxes"
|
export { ObsidianCheckboxes } from "./checkboxes"
|
||||||
export { ObsidianComments } from "./comments"
|
export { ObsidianComments } from "./comments"
|
||||||
|
|||||||
@ -39,6 +39,7 @@ import { GitHubLinkheadings, GitHubSmartypants } from "../parsers/github"
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ObsidianArrow,
|
ObsidianArrow,
|
||||||
|
ObsidianBlockReference,
|
||||||
ObsidianCallouts,
|
ObsidianCallouts,
|
||||||
ObsidianCheckboxes,
|
ObsidianCheckboxes,
|
||||||
ObsidianComments,
|
ObsidianComments,
|
||||||
@ -323,6 +324,9 @@ export const ObsidianFlavoredMarkdown: QuartzTransformerPlugin<Partial<ObsidianO
|
|||||||
htmlPlugins() {
|
htmlPlugins() {
|
||||||
const plugins: PluggableList = [rehypeRaw]
|
const plugins: PluggableList = [rehypeRaw]
|
||||||
|
|
||||||
|
plugins.push(
|
||||||
|
ObsidianBlockReference({ enabled: opts.parseBlockReferences }).htmlPlugins() as Pluggable,
|
||||||
|
)
|
||||||
plugins.push(ObsidianYouTube({ enabled: opts.enableYouTubeEmbed }).htmlPlugins() as Pluggable)
|
plugins.push(ObsidianYouTube({ enabled: opts.enableYouTubeEmbed }).htmlPlugins() as Pluggable)
|
||||||
plugins.push.apply(
|
plugins.push.apply(
|
||||||
ObsidianCheckboxes({ enabled: opts.enableCheckbox }).htmlPlugins() as Pluggable[],
|
ObsidianCheckboxes({ enabled: opts.enableCheckbox }).htmlPlugins() as Pluggable[],
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user