fix: catch html to jsx errors (closes #547)
1 files added
6 files modified
| | |
| | | |
| | | - Your component should use `getQuartzComponents` to declare a list of `QuartzComponents` that it uses to construct the page. See the page on [[creating components]] for more information. |
| | | - You can use the `renderPage` function defined in `quartz/components/renderPage.tsx` to render Quartz components into HTML. |
| | | - If you need to render an HTML AST to JSX, you can use the `toJsxRuntime` function from `hast-util-to-jsx-runtime` library. An example of this can be found in `quartz/components/pages/Content.tsx`. |
| | | - If you need to render an HTML AST to JSX, you can use the `htmlToJsx` function from `quartz/util/jsx.ts`. An example of this can be found in `quartz/components/pages/Content.tsx`. |
| | | |
| | | For example, the following is a simplified version of the content page plugin that renders every single page. |
| | | |
| | |
| | | gap: 0.4rem; |
| | | margin: 1rem 0; |
| | | flex-wrap: wrap; |
| | | justify-content: flex-end; |
| | | justify-self: end; |
| | | } |
| | | |
| | | .section-ul .tags { |
| | | justify-content: flex-end; |
| | | } |
| | | |
| | | .tags > li { |
| | | display: inline-block; |
| | | white-space: nowrap; |
| | |
| | | import { htmlToJsx } from "../../util/jsx" |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "../types" |
| | | import { Fragment, jsx, jsxs } from "preact/jsx-runtime" |
| | | import { toJsxRuntime } from "hast-util-to-jsx-runtime" |
| | | |
| | | function Content({ tree }: QuartzComponentProps) { |
| | | // @ts-ignore (preact makes it angry) |
| | | const content = toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" }) |
| | | function Content({ fileData, tree }: QuartzComponentProps) { |
| | | const content = htmlToJsx(fileData.filePath!, tree) |
| | | return <article class="popover-hint">{content}</article> |
| | | } |
| | | |
| | |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "../types" |
| | | import { Fragment, jsx, jsxs } from "preact/jsx-runtime" |
| | | import { toJsxRuntime } from "hast-util-to-jsx-runtime" |
| | | import path from "path" |
| | | |
| | | import style from "../styles/listPage.scss" |
| | |
| | | import { _stripSlashes, simplifySlug } from "../../util/path" |
| | | import { Root } from "hast" |
| | | import { pluralize } from "../../util/lang" |
| | | import { htmlToJsx } from "../../util/jsx" |
| | | |
| | | function FolderContent(props: QuartzComponentProps) { |
| | | const { tree, fileData, allFiles } = props |
| | |
| | | const content = |
| | | (tree as Root).children.length === 0 |
| | | ? fileData.description |
| | | : // @ts-ignore |
| | | toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" }) |
| | | : htmlToJsx(fileData.filePath!, tree) |
| | | |
| | | return ( |
| | | <div class="popover-hint"> |
| | |
| | | import { QuartzComponentConstructor, QuartzComponentProps } from "../types" |
| | | import { Fragment, jsx, jsxs } from "preact/jsx-runtime" |
| | | import { toJsxRuntime } from "hast-util-to-jsx-runtime" |
| | | import style from "../styles/listPage.scss" |
| | | import { PageList } from "../PageList" |
| | | import { FullSlug, getAllSegmentPrefixes, simplifySlug } from "../../util/path" |
| | | import { QuartzPluginData } from "../../plugins/vfile" |
| | | import { Root } from "hast" |
| | | import { pluralize } from "../../util/lang" |
| | | import { htmlToJsx } from "../../util/jsx" |
| | | |
| | | const numPages = 10 |
| | | function TagContent(props: QuartzComponentProps) { |
| | |
| | | const content = |
| | | (tree as Root).children.length === 0 |
| | | ? fileData.description |
| | | : // @ts-ignore |
| | | toJsxRuntime(tree, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" }) |
| | | : htmlToJsx(fileData.filePath!, tree) |
| | | |
| | | if (tag === "") { |
| | | const tags = [...new Set(allFiles.flatMap((data) => data.frontmatter?.tags ?? []))] |
| New file |
| | |
| | | import { toJsxRuntime } from "hast-util-to-jsx-runtime" |
| | | import { QuartzPluginData } from "../plugins/vfile" |
| | | import { Node, Root } from "hast" |
| | | import { Fragment, jsx, jsxs } from "preact/jsx-runtime" |
| | | import { trace } from "./trace" |
| | | import { type FilePath } from "./path" |
| | | |
| | | export function htmlToJsx(fp: FilePath, tree: Node<QuartzPluginData>) { |
| | | try { |
| | | // @ts-ignore (preact makes it angry) |
| | | return toJsxRuntime(tree as Root, { Fragment, jsx, jsxs, elementAttributeNameCase: "html" }) |
| | | } catch (e) { |
| | | trace(`Failed to parse Markdown in \`${fp}\` into JSX`, e as Error) |
| | | } |
| | | } |
| | |
| | | |
| | | const rootFile = /.*at file:/ |
| | | export function trace(msg: string, err: Error) { |
| | | const stack = err.stack |
| | | let stack = err.stack ?? "" |
| | | |
| | | const lines: string[] = [] |
| | | |
| | |
| | | lines.push( |
| | | "\n" + |
| | | chalk.bgRed.black.bold(" ERROR ") + |
| | | "\n" + |
| | | "\n\n" + |
| | | chalk.red(` ${msg}`) + |
| | | (err.message.length > 0 ? `: ${err.message}` : ""), |
| | | ) |
| | | |
| | | if (!stack) { |
| | | return |
| | | } |
| | | |
| | | let reachedEndOfLegibleTrace = false |
| | | for (const line of stack.split("\n").slice(1)) { |
| | | if (reachedEndOfLegibleTrace) { |