authorgravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-04-02 23:01:46-07:00
committergravatar for git@paperclover.netclover caruso <git@paperclover.net> 2026-04-06 01:17:01-07:00
loga2edc9aa2044b09fccabfd343759f4f6e151e0a3
tree58243b0f5228c0250aab16ddd2cf9be17deb1573
parent223b5dc94bf1459d8a62aed61e447b8f3abafcd8
signature Signed by SSH key SHA256:xbd+BjjhyBfwk7GVoURf9Yx0gzDerHbvYv7SddNWmAs

fix: file scanning shit

resolves #49. aspect ratio bugs on videos and images are fixed.

5 files changed, 16 insertions(+), 10 deletions(-)

src/tags/clover-media.marko+2-2
...@@ -12,7 +12,7 @@ export interface Input {...@@ -12,7 +12,7 @@ export interface Input {
12 <div style={ color: "red" }>ERROR: No file in database: ${src}</div>12 <div style={ color: "red" }>ERROR: No file in database: ${src}</div>
13</if>13</if>
14<else if=extsVideo.has(file.extension.toLowerCase())>14<else if=extsVideo.has(file.extension.toLowerCase())>
15 <clover-video noFigure ...{ file }/>15 <clover-video minimal noFigure ...{ file }/>
16</else>16</else>
17<else if=file.extension === ".gif">17<else if=file.extension === ".gif">
18 <img src=`/file${escapeUri(file.path)}` ...rest>18 <img src=`/file${escapeUri(file.path)}` ...rest>
...@@ -29,7 +29,7 @@ export interface Input {...@@ -29,7 +29,7 @@ export interface Input {
29 : `100vw`29 : `100vw`
30 )>30 )>
31 <picture>31 <picture>
32 <for|ext| of=["jxl", "avif", "webp"]>32 <for|ext| of=["jxl", "webp"]>
33 <source33 <source
34 type=`image/${ext}`34 type=`image/${ext}`
35 srcset=targetSizes.map((s) => `${base}:/${s}.${ext} ${s}w`)35 srcset=targetSizes.map((s) => `${base}:/${s}.${ext} ${s}w`)
src/tags/clover-video.marko+1-1
...@@ -34,7 +34,7 @@ export interface Input {...@@ -34,7 +34,7 @@ export interface Input {
34<define/Inner>34<define/Inner>
35 <video35 <video
36 ...{ id }36 ...{ id }
37 class={ "clover-video": noFigure }37 class={ "clover-video": noFigure, minimal: noFigure && minimal }
38 data-src=file.path38 data-src=file.path
39 poster=poster ? `/file${poster.path}` : null39 poster=poster ? `/file${poster.path}` : null
40 width=width40 width=width
src/tags/image.tsx+1-1
...@@ -35,7 +35,7 @@ export default function Image(...@@ -35,7 +35,7 @@ export default function Image(
3535
36 return (36 return (
37 <picture>37 <picture>
38 {["jxl", "avif", "webp"].map((ext) => (38 {["jxl", "webp"].map((ext) => (
39 <source39 <source
40 type={`image/${ext}`}40 type={`image/${ext}`}
41 srcset={targetSizes.map((s) => `${base}:/${s}.${ext} ${s}w`)}41 srcset={targetSizes.map((s) => `${base}:/${s}.${ext} ${s}w`)}
src/tags/photo-grid.css+6
...@@ -22,3 +22,9 @@ photo-grid-item {...@@ -22,3 +22,9 @@ photo-grid-item {
22 object-fit: cover;22 object-fit: cover;
23 }23 }
24}24}
25photo-grid + blockquote {
26 margin: 0 -4px;
27 border: none;
28 background-color: var(--primary);
29 color: black;
30}
src/tags/photo-grid.marko+6-6
...@@ -1,19 +1,18 @@...@@ -1,19 +1,18 @@
1import "./photo-grid.css";1import "./photo-grid.css";
22
3static const gap = 11;
4
5export interface Input {3export interface Input {
6 base?: string;4 base?: string;
7 cols: number[]; // weights5 cols: number[]; // weights
8 rows?: number[]; // pixel heights, based on a 768px container6 rows?: number[]; // pixel heights, based on a 768px container
9 style?: Marko.AttrStyle;7 style?: Marko.AttrStyle;
8 gapless?: boolean;
9 gap?: number;
10 // images are placed left to right, top to bottom10 // images are placed left to right, top to bottom
11 img: Marko.AttrTag<{11 img: Marko.AttrTag<{
12 src: string;12 src: string;
13 w?: number; // column span13 w?: number; // column span
14 h?: number; // row span14 h?: number; // row span
15 s?: number; // skipped columns before placement15 s?: number; // skipped columns before placement
16 small?: unknown;
17 mutedLoop?: boolean;16 mutedLoop?: boolean;
18 align?: "top" | "center" | "bottom" | (string & {});17 align?: "top" | "center" | "bottom" | (string & {});
19 }>;18 }>;
...@@ -39,7 +38,7 @@ static const alignments = {...@@ -39,7 +38,7 @@ static const alignments = {
39 "right-end": "100% 50%",38 "right-end": "100% 50%",
40};39};
4140
42<const/{ base, cols, style }=input>41<const/{ base, cols, style, gapless, gap = gapless ? 4 : 11 }=input>
43<const/rows=input.rows ?? [325]>42<const/rows=input.rows ?? [325]>
44<const/colCount=input.cols.length>43<const/colCount=input.cols.length>
45<const/rowSum=rows.reduce((a, b) => a + b, 0) + gap * (rows.length - 1)>44<const/rowSum=rows.reduce((a, b) => a + b, 0) + gap * (rows.length - 1)>
...@@ -55,8 +54,8 @@ static const alignments = {...@@ -55,8 +54,8 @@ static const alignments = {
55 return false;54 return false;
56 };55 };
5756
58 let x = 0,57 let x = 0;
59 y = 0;58 let y = 0;
60 let result: Positioned[] = [];59 let result: Positioned[] = [];
61 for (const img of input.img) {60 for (const img of input.img) {
62 const w = img.w ?? 1;61 const w = img.w ?? 1;
...@@ -97,6 +96,7 @@ static const alignments = {...@@ -97,6 +96,7 @@ static const alignments = {
97 .map((x) => ((100 * x) / rowSum).toFixed(1) + "%")96 .map((x) => ((100 * x) / rowSum).toFixed(1) + "%")
98 .join(" "),97 .join(" "),
99 "aspect-ratio": `768/${rowSum}`,98 "aspect-ratio": `768/${rowSum}`,
99 gap: gap !== 11 ? gap + "px" : undefined,
100 ...style,100 ...style,
101}>101}>
102 <for|{ x, y, w, h, src, align }| of=items>102 <for|{ x, y, w, h, src, align }| of=items>