mirror of
https://github.com/hzrd149/nostrudel.git
synced 2025-07-06 05:25:48 +02:00
Fix link cards breaking lines
This commit is contained in:
5
.changeset/smooth-chairs-bow.md
Normal file
5
.changeset/smooth-chairs-bow.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"nostrudel": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix link cards breaking lines
|
@ -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} />;
|
||||||
}
|
}
|
||||||
|
12
src/components/open-graph-link.tsx
Normal file
12
src/components/open-graph-link.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
@ -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) {}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user