summaryrefslogtreecommitdiff
path: root/apps/web/src/components/ui/prose.tsx
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-03-27 00:55:15 +0100
committerMaze Winther <mazewinther@gmail.com>2026-03-29 15:56:48 +0200
commit4d127a038bf768eded68aae3cfa5c1b12241bdac (patch)
tree16bbb801caf6770546cff4fdb37b6408ec9ead98 /apps/web/src/components/ui/prose.tsx
parent82817cb50cb0487350573d6129130aec705f924b (diff)
downloadopencut-4d127a038bf768eded68aae3cfa5c1b12241bdac.tar.gz
chore: normalize line endings
Diffstat (limited to 'apps/web/src/components/ui/prose.tsx')
-rw-r--r--apps/web/src/components/ui/prose.tsx222
1 files changed, 111 insertions, 111 deletions
diff --git a/apps/web/src/components/ui/prose.tsx b/apps/web/src/components/ui/prose.tsx
index 88d017fe..74bb14fd 100644
--- a/apps/web/src/components/ui/prose.tsx
+++ b/apps/web/src/components/ui/prose.tsx
@@ -1,111 +1,111 @@
-import { cn } from "@/utils/ui";
-import rehypeParse from "rehype-parse";
-import { unified } from "unified";
-import { createElement } from "react";
-import type React from "react";
-
-type ProseProps = React.HTMLAttributes<HTMLElement> & {
- as?: "article";
- html: string;
-};
-
-type HastTextNode = {
- type: "text";
- value: string;
-};
-
-type HastElementNode = {
- type: "element";
- tagName: string;
- properties?: Record<string, unknown>;
- children?: HastNode[];
-};
-
-type HastRootNode = {
- type: "root";
- children?: HastNode[];
-};
-
-type HastNode = HastTextNode | HastElementNode | HastRootNode;
-
-function toReactProps({
- properties,
-}: {
- properties: HastElementNode["properties"];
-}): Record<string, unknown> {
- if (!properties) {
- return {};
- }
-
- const props: Record<string, unknown> = {};
-
- for (const [propertyName, propertyValue] of Object.entries(properties)) {
- if (propertyValue === null || propertyValue === undefined) {
- continue;
- }
-
- if (propertyName.startsWith("on")) {
- continue;
- }
-
- if (propertyName === "class") {
- props.className = Array.isArray(propertyValue)
- ? propertyValue.join(" ")
- : propertyValue;
- continue;
- }
-
- if (propertyName === "for") {
- props.htmlFor = propertyValue;
- continue;
- }
-
- props[propertyName] = propertyValue;
- }
-
- return props;
-}
-
-function renderHastNode({
- node,
- key,
-}: {
- node: HastNode;
- key: string;
-}): React.ReactNode {
- if (node.type === "text") {
- return node.value;
- }
-
- if (node.type !== "element") {
- return null;
- }
-
- const children = (node.children ?? []).map((childNode, index) =>
- renderHastNode({ node: childNode, key: `${key}-${index}` }),
- );
-
- return createElement(node.tagName, { ...toReactProps({ properties: node.properties }), key }, children);
-}
-
-function renderHtmlNodes({ html }: { html: string }): React.ReactNode {
- const rootNode = unified().use(rehypeParse, { fragment: true }).parse(html) as HastRootNode;
- return (rootNode.children ?? []).map((childNode, index) =>
- renderHastNode({ node: childNode, key: `prose-node-${index}` }),
- );
-}
-
-function Prose({ children, html, className }: ProseProps) {
- return (
- <article
- className={cn(
- "prose prose-h2:font-semibold prose-h1:text-xl prose-a:text-blue-600 prose-p:first:mt-0 dark:prose-invert mx-auto max-w-none px-2",
- className,
- )}
- >
- {html ? renderHtmlNodes({ html }) : children}
- </article>
- );
-}
-
-export default Prose;
+import { cn } from "@/utils/ui";
+import rehypeParse from "rehype-parse";
+import { unified } from "unified";
+import { createElement } from "react";
+import type React from "react";
+
+type ProseProps = React.HTMLAttributes<HTMLElement> & {
+ as?: "article";
+ html: string;
+};
+
+type HastTextNode = {
+ type: "text";
+ value: string;
+};
+
+type HastElementNode = {
+ type: "element";
+ tagName: string;
+ properties?: Record<string, unknown>;
+ children?: HastNode[];
+};
+
+type HastRootNode = {
+ type: "root";
+ children?: HastNode[];
+};
+
+type HastNode = HastTextNode | HastElementNode | HastRootNode;
+
+function toReactProps({
+ properties,
+}: {
+ properties: HastElementNode["properties"];
+}): Record<string, unknown> {
+ if (!properties) {
+ return {};
+ }
+
+ const props: Record<string, unknown> = {};
+
+ for (const [propertyName, propertyValue] of Object.entries(properties)) {
+ if (propertyValue === null || propertyValue === undefined) {
+ continue;
+ }
+
+ if (propertyName.startsWith("on")) {
+ continue;
+ }
+
+ if (propertyName === "class") {
+ props.className = Array.isArray(propertyValue)
+ ? propertyValue.join(" ")
+ : propertyValue;
+ continue;
+ }
+
+ if (propertyName === "for") {
+ props.htmlFor = propertyValue;
+ continue;
+ }
+
+ props[propertyName] = propertyValue;
+ }
+
+ return props;
+}
+
+function renderHastNode({
+ node,
+ key,
+}: {
+ node: HastNode;
+ key: string;
+}): React.ReactNode {
+ if (node.type === "text") {
+ return node.value;
+ }
+
+ if (node.type !== "element") {
+ return null;
+ }
+
+ const children = (node.children ?? []).map((childNode, index) =>
+ renderHastNode({ node: childNode, key: `${key}-${index}` }),
+ );
+
+ return createElement(node.tagName, { ...toReactProps({ properties: node.properties }), key }, children);
+}
+
+function renderHtmlNodes({ html }: { html: string }): React.ReactNode {
+ const rootNode = unified().use(rehypeParse, { fragment: true }).parse(html) as HastRootNode;
+ return (rootNode.children ?? []).map((childNode, index) =>
+ renderHastNode({ node: childNode, key: `prose-node-${index}` }),
+ );
+}
+
+function Prose({ children, html, className }: ProseProps) {
+ return (
+ <article
+ className={cn(
+ "prose prose-h2:font-semibold prose-h1:text-xl prose-a:text-blue-600 prose-p:first:mt-0 dark:prose-invert mx-auto max-w-none px-2",
+ className,
+ )}
+ >
+ {html ? renderHtmlNodes({ html }) : children}
+ </article>
+ );
+}
+
+export default Prose;