Fix link cards breaking lines

This commit is contained in:
hzrd149
2023-10-29 17:02:48 -05:00
parent e740b6f059
commit d1181ef97c
4 changed files with 26 additions and 7 deletions

View File

@ -0,0 +1,5 @@
---
"nostrudel": patch
---
Fix link cards breaking lines

View File

@ -2,6 +2,7 @@ import { Link } from "@chakra-ui/react";
import OpenGraphCard from "../open-graph-card"; import OpenGraphCard from "../open-graph-card";
import { isVideoURL } from "../../helpers/url"; import { isVideoURL } from "../../helpers/url";
import OpenGraphLink from "../open-graph-link";
export function renderVideoUrl(match: URL) { export function renderVideoUrl(match: URL) {
if (!isVideoURL(match)) return null; if (!isVideoURL(match)) return null;
@ -23,6 +24,6 @@ export function renderGenericUrl(match: URL) {
); );
} }
export function renderOpenGraphUrl(match: URL) { export function renderOpenGraphUrl(match: URL, isEndOfLine: boolean) {
return <OpenGraphCard url={match} />; return isEndOfLine ? <OpenGraphCard url={match} /> : <OpenGraphLink url={match} />;
} }

View File

@ -0,0 +1,12 @@
import { Link, LinkProps } from "@chakra-ui/react";
import useOpenGraphData from "../hooks/use-open-graph-data";
export default function OpenGraphLink({ url, ...props }: { url: URL } & Omit<LinkProps, "children">) {
const { value: data } = useOpenGraphData(url);
return (
<Link href={url.toString()} isExternal color="blue.500" {...props}>
{data?.ogTitle?.trim() ?? data?.dcTitle?.trim() ?? decodeURI(url.toString())}
</Link>
);
}

View File

@ -4,7 +4,7 @@ import { getMatchLink } from "./regexp";
export type EmbedableContent = (string | JSX.Element)[]; export type EmbedableContent = (string | JSX.Element)[];
export type EmbedType = { export type EmbedType = {
regexp: RegExp; regexp: RegExp;
render: (match: RegExpMatchArray) => JSX.Element | string | null; render: (match: RegExpMatchArray, isEndOfLine: boolean) => JSX.Element | string | null;
name: string; name: string;
getLocation?: (match: RegExpMatchArray) => { start: number; end: number }; getLocation?: (match: RegExpMatchArray) => { start: number; end: number };
}; };
@ -35,7 +35,8 @@ export function embedJSX(content: EmbedableContent, embed: EmbedType): Embedable
const before = str.slice(0, start - cursor); const before = str.slice(0, start - cursor);
const after = str.slice(end - cursor, str.length); const after = str.slice(end - cursor, str.length);
let render = embed.render(match); const isEndOfLine = /^\p{Z}*(\n|$)/iu.test(after);
let render = embed.render(match, isEndOfLine);
if (render === null) continue; if (render === null) continue;
if (typeof render !== "string" && !render.props.key) { if (typeof render !== "string" && !render.props.key) {
@ -68,18 +69,18 @@ export function embedJSX(content: EmbedableContent, embed: EmbedType): Embedable
.flat(); .flat();
} }
export type LinkEmbedHandler = (link: URL) => JSX.Element | string | null; export type LinkEmbedHandler = (link: URL, isEndOfLine: boolean) => JSX.Element | string | null;
export function embedUrls(content: EmbedableContent, handlers: LinkEmbedHandler[]) { export function embedUrls(content: EmbedableContent, handlers: LinkEmbedHandler[]) {
return embedJSX(content, { return embedJSX(content, {
name: "embedUrls", name: "embedUrls",
regexp: getMatchLink(), regexp: getMatchLink(),
render: (match) => { render: (match, isEndOfLine) => {
try { try {
const url = new URL(match[0]); const url = new URL(match[0]);
for (const handler of handlers) { for (const handler of handlers) {
try { try {
const content = handler(url); const content = handler(url, isEndOfLine);
if (content) return content; if (content) return content;
} catch (e) {} } catch (e) {}
} }