feat: dont show image duplicate in beginnign of markdown

This commit is contained in:
max_richter 2025-01-26 02:00:59 +01:00
parent 6a54bdeec6
commit d450f4ed42
8 changed files with 99 additions and 42 deletions

View File

@ -27,9 +27,11 @@ export function Link(
clearTimeout(globalThis.loadingTimeout); clearTimeout(globalThis.loadingTimeout);
delete globalThis.loadingTimeout; delete globalThis.loadingTimeout;
setTimeout(() => { setTimeout(() => {
globalThis.dispatchEvent(new CustomEvent("loading-finished"));
document.querySelector("main")?.classList.remove("loading"); document.querySelector("main")?.classList.remove("loading");
}, 100); }, 100);
} else { } else {
globalThis.dispatchEvent(new CustomEvent("loading-finished"));
document.querySelector("main")?.classList.remove("loading"); document.querySelector("main")?.classList.remove("loading");
} }
}); });

View File

@ -132,8 +132,35 @@ export function parseDocument(doc: string) {
.parse(doc); .parse(doc);
} }
function removeFrontmatter(doc: string) {
if (doc.trim().startsWith("---")) {
return doc.trim().split("---").filter((s) => s.length).slice(1).join("---");
}
return doc;
}
export function removeImage(doc: string, imageUrl?: string) {
if (!imageUrl) {
return doc;
}
// Remove image from content
const first = doc.slice(0, 500);
const second = doc.slice(500);
// Regex pattern to match the image Markdown syntax with the specific URL
const pattern = new RegExp(
`!\\[.*?\\]\\(${imageUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\)`,
"g",
);
// Remove the matched image
const updatedMarkdown = first.replace(pattern, "");
return updatedMarkdown + second;
}
export function renderMarkdown(doc: string) { export function renderMarkdown(doc: string) {
return render(doc, { return render(removeFrontmatter(doc), {
baseUrl: SILVERBULLET_SERVER,
allowMath: true, allowMath: true,
}); });
} }
@ -172,4 +199,3 @@ export function getTextOfChild(child: DocumentChild): string | undefined {
} }
return; return;
} }

View File

@ -5,7 +5,7 @@ import { KMenu } from "@islands/KMenu.tsx";
import { YoutubePlayer } from "@components/Youtube.tsx"; import { YoutubePlayer } from "@components/Youtube.tsx";
import { HashTags } from "@components/HashTags.tsx"; import { HashTags } from "@components/HashTags.tsx";
import { isYoutubeLink } from "@lib/string.ts"; import { isYoutubeLink } from "@lib/string.ts";
import { renderMarkdown } from "@lib/documents.ts"; import { removeImage, renderMarkdown } from "@lib/documents.ts";
import { RedirectSearchHandler } from "@islands/Search.tsx"; import { RedirectSearchHandler } from "@islands/Search.tsx";
import PageHero from "@components/PageHero.tsx"; import PageHero from "@components/PageHero.tsx";
import { Star } from "@components/Stars.tsx"; import { Star } from "@components/Stars.tsx";
@ -14,6 +14,9 @@ import { MetaTags } from "@components/MetaTags.tsx";
export const handler: Handlers<{ article: Article; session: unknown }> = { export const handler: Handlers<{ article: Article; session: unknown }> = {
async GET(_, ctx) { async GET(_, ctx) {
const article = await getArticle(ctx.params.name); const article = await getArticle(ctx.params.name);
if (!article) {
return ctx.renderNotFound();
}
return ctx.render({ article, session: ctx.state.session }); return ctx.render({ article, session: ctx.state.session });
}, },
}; };
@ -25,7 +28,9 @@ export default function Greet(
const { author = "", date = "" } = article.meta; const { author = "", date = "" } = article.meta;
const content = renderMarkdown(article.content); const content = renderMarkdown(
removeImage(article.content, article.meta.image),
);
return ( return (
<MainLayout <MainLayout

View File

@ -2,7 +2,7 @@ import { PageProps, RouteContext } from "$fresh/server.ts";
import { MainLayout } from "@components/layouts/main.tsx"; import { MainLayout } from "@components/layouts/main.tsx";
import { getMovie, Movie } from "@lib/resource/movies.ts"; import { getMovie, Movie } from "@lib/resource/movies.ts";
import { HashTags } from "@components/HashTags.tsx"; import { HashTags } from "@components/HashTags.tsx";
import { renderMarkdown } from "@lib/documents.ts"; import { removeImage, renderMarkdown } from "@lib/documents.ts";
import { KMenu } from "@islands/KMenu.tsx"; import { KMenu } from "@islands/KMenu.tsx";
import { RedirectSearchHandler } from "@islands/Search.tsx"; import { RedirectSearchHandler } from "@islands/Search.tsx";
import { Recommendations } from "@islands/Recommendations.tsx"; import { Recommendations } from "@islands/Recommendations.tsx";
@ -17,9 +17,15 @@ export default async function Greet(
const movie = await getMovie(ctx.params.name); const movie = await getMovie(ctx.params.name);
const session = ctx.state.session; const session = ctx.state.session;
if (!movie) {
return ctx.renderNotFound();
}
const { author = "", date = "" } = movie.meta; const { author = "", date = "" } = movie.meta;
const content = renderMarkdown(movie.description || ""); const content = renderMarkdown(
removeImage(movie.description || "", movie.meta.image),
);
return ( return (
<MainLayout url={props.url} title={`Movie > ${movie.name}`} context={movie}> <MainLayout url={props.url} title={`Movie > ${movie.name}`} context={movie}>

View File

@ -60,14 +60,13 @@ function ValidRecipe({
); );
} }
export default function Greet( export default function Page(
props: PageProps<{ recipe: Recipe; session: Record<string, string> }>, props: PageProps<{ recipe: Recipe; session: Record<string, string> }>,
) { ) {
const { recipe, session } = props.data; const { recipe, session } = props.data;
const portion = recipe.meta?.portion; const portion = recipe.meta?.portion;
const amount = useSignal(portion || 1); const amount = useSignal(portion || 1);
console.log({ recipe });
const subline = [ const subline = [
recipe?.meta?.time && `Duration ${recipe.meta.time}`, recipe?.meta?.time && `Duration ${recipe.meta.time}`,

View File

@ -1,7 +1,7 @@
import { Handlers, PageProps } from "$fresh/server.ts"; import { Handlers, PageProps } from "$fresh/server.ts";
import { MainLayout } from "@components/layouts/main.tsx"; import { MainLayout } from "@components/layouts/main.tsx";
import { HashTags } from "@components/HashTags.tsx"; import { HashTags } from "@components/HashTags.tsx";
import { renderMarkdown } from "@lib/documents.ts"; import { removeImage, renderMarkdown } from "@lib/documents.ts";
import { getSeries, Series } from "@lib/resource/series.ts"; import { getSeries, Series } from "@lib/resource/series.ts";
import { RedirectSearchHandler } from "@islands/Search.tsx"; import { RedirectSearchHandler } from "@islands/Search.tsx";
import { KMenu } from "@islands/KMenu.tsx"; import { KMenu } from "@islands/KMenu.tsx";
@ -12,6 +12,10 @@ import { MetaTags } from "@components/MetaTags.tsx";
export const handler: Handlers<{ serie: Series; session: unknown }> = { export const handler: Handlers<{ serie: Series; session: unknown }> = {
async GET(_, ctx) { async GET(_, ctx) {
const serie = await getSeries(ctx.params.name); const serie = await getSeries(ctx.params.name);
if (!serie) {
return ctx.renderNotFound();
}
return ctx.render({ serie, session: ctx.state.session }); return ctx.render({ serie, session: ctx.state.session });
}, },
}; };
@ -23,7 +27,9 @@ export default function Greet(
const { author = "", date = "" } = serie.meta; const { author = "", date = "" } = serie.meta;
const content = renderMarkdown(serie.description || ""); const content = renderMarkdown(
removeImage(serie.description || "", serie.meta.image),
);
return ( return (
<MainLayout url={props.url} title={`Serie > ${serie.name}`} context={serie}> <MainLayout url={props.url} title={`Serie > ${serie.name}`} context={serie}>

View File

@ -150,4 +150,12 @@ main.loading {
display: inline-flex; display: inline-flex;
margin-left: -26px; margin-left: -26px;
margin-right: 12px; margin-right: 12px;
opacity: 0;
transition: opacity 0.2s;
}
.markdown-body>h1:hover .anchor,
.markdown-body>h2:hover .anchor,
.markdown-body>h3:hover .anchor {
opacity: 1;
} }

View File

@ -226,7 +226,8 @@ function rgbaToDataURL(w, h, rgba) {
return "data:image/png;base64," + btoa(String.fromCharCode(...bytes)); return "data:image/png;base64," + btoa(String.fromCharCode(...bytes));
} }
document.querySelectorAll("[data-thumb]").forEach((entry) => { function updateThumbnailImages() {
document.querySelectorAll("[data-thumb]").forEach((entry) => {
const hash = entry.getAttribute("data-thumb"); const hash = entry.getAttribute("data-thumb");
if (!hash) return; if (!hash) return;
@ -261,4 +262,8 @@ document.querySelectorAll("[data-thumb]").forEach((entry) => {
}); });
} }
}, 50); }, 50);
}); });
}
globalThis.addEventListener("load", updateThumbnailImages);
globalThis.addEventListener("loading-finished", updateThumbnailImages);