Leaflet Blog in Deno Fresh
1import { h } from "preact";
2import { PubLeafletBlocksText } from "npm:@atcute/leaflet";
3
4interface TextBlockProps {
5 plaintext: string;
6 facets?: PubLeafletBlocksText.Main["facets"];
7}
8
9export function TextBlock({ plaintext, facets }: TextBlockProps) {
10 // Only process facets if at least one facet has features
11 if (!facets || !facets.some(f => f.features && f.features.length > 0)) {
12 return <>{plaintext}</>;
13 }
14
15 const parts: (string | { text: string; type: string; uri?: string })[] = [];
16 let lastIndex = 0;
17
18 facets.forEach((facet) => {
19 if (facet.index.byteStart > lastIndex) {
20 parts.push(plaintext.slice(lastIndex, facet.index.byteStart));
21 }
22
23 const text = plaintext.slice(facet.index.byteStart, facet.index.byteEnd);
24 const feature = facet.features?.[0];
25
26 if (!feature) {
27 parts.push(text);
28 return;
29 }
30
31 if (feature.$type === "pub.leaflet.richtext.facet#bold") {
32 parts.push({ text, type: feature.$type });
33 } else if (feature.$type === "pub.leaflet.richtext.facet#highlight") {
34 parts.push({ text, type: feature.$type });
35 } else if (feature.$type === "pub.leaflet.richtext.facet#italic") {
36 parts.push({ text, type: feature.$type });
37 } else if (feature.$type === "pub.leaflet.richtext.facet#strikethrough") {
38 parts.push({ text, type: feature.$type });
39 } else if (feature.$type === "pub.leaflet.richtext.facet#underline") {
40 parts.push({ text, type: feature.$type });
41 } else {
42 parts.push({ text, type: feature.$type });
43 }
44
45 lastIndex = facet.index.byteEnd;
46 });
47
48 if (lastIndex < plaintext.length) {
49 parts.push(plaintext.slice(lastIndex));
50 }
51
52 return (
53 <>
54 {parts.map((part, i) => {
55 if (typeof part === "string") {
56 return part;
57 }
58
59 switch (part.type) {
60 case "pub.leaflet.richtext.facet#bold":
61 return <strong key={i}>{part.text}</strong>;
62 case "pub.leaflet.richtext.facet#highlight":
63 return (
64 <mark
65 key={i}
66 className="bg-blue-100 dark:bg-blue-900 text-inherit rounded px-1"
67 style={{ borderRadius: '0.375rem' }}
68 >
69 {part.text}
70 </mark>
71 );
72 case "pub.leaflet.richtext.facet#italic":
73 return <em key={i}>{part.text}</em>;
74 case "pub.leaflet.richtext.facet#strikethrough":
75 return <s key={i}>{part.text}</s>;
76 case "pub.leaflet.richtext.facet#underline":
77 return <u key={i}>{part.text}</u>;
78 default:
79 return part.text;
80 }
81 })}
82 </>
83 );
84}