this repo has no description
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

✨ Add support for title style, fix made with not showing up

+90 -37
+12
src/components/StrongHeader.astro
··· 8 8 } & ( 9 9 | { title: string; wip?: undefined } 10 10 | { title: { fr: string; en: string }; wip?: boolean } 11 + | { title: { img: { src: string; alt: string; srcset: string, height: string; width: string } }; wip?: boolean } 11 12 ); 12 13 13 14 const { title, wip, back, editButton } = Astro.props; ··· 49 50 { 50 51 typeof title === "string" ? ( 51 52 <h1 i18n>{title}</h1> 53 + ) : "img" in title ? ( 54 + <h1 class="image"> 55 + <img {...title.img} /> 56 + </h1> 52 57 ) : ( 53 58 <h1> 54 59 <Translated {...title} /> ··· 69 74 } 70 75 h1 { 71 76 font-size: 2.8em; 77 + } 78 + 79 + img { 80 + max-width: 100%; 81 + max-height: 10rem; 82 + object-fit: contain; 83 + object-position: 0 0; 72 84 } 73 85 74 86 a.back,
+9 -5
src/content.config.ts
··· 72 72 ) 73 73 .optional(), 74 74 created: nullableDate, 75 + title_style: z.string().optional(), 76 + made_with: z.array(z.string()).optional(), 75 77 }) 76 78 .nullable(), 77 79 databaseMetadata: z.object({ ··· 258 260 259 261 return [ 260 262 { ...out, isAliasOf: null }, 261 - ...aliasIds.map((slug) => ({ 262 - ...out, 263 - slug, 264 - isAliasOf: out.slug, 265 - })), 263 + ...aliasIds 264 + .filter((slug) => slug !== out.slug) 265 + .map((slug) => ({ 266 + ...out, 267 + slug, 268 + isAliasOf: out.slug, 269 + })), 266 270 ]; 267 271 }); 268 272
+11 -13
src/pages/works/BlockMedia.astro
··· 1 1 --- 2 2 import type { InferEntrySchema } from "astro:content"; 3 + import { imageAttrs } from "./media"; 3 4 4 5 type Block = 5 6 InferEntrySchema<"works">["content"][keyof InferEntrySchema<"works">["content"]]["blocks"][number]; 6 7 7 8 interface Props extends Block {} 8 9 9 - const { alt, caption, attributes, contentType, thumbnails, dimensions } = 10 - Astro.props; 10 + const { alt, caption, attributes, contentType, dimensions } = Astro.props; 11 11 const generalContentType = contentType?.split("/")[0] ?? ""; 12 - const distSource = `https://media.gwen.works/${Astro.props.distSource}`; 13 - const thumbnailsSrcSet = Object.entries(thumbnails ?? {}) 14 - .map(([size, path]) => `https://media.gwen.works/${path} ${size}w`) 15 - .join(", "); 12 + 13 + const attrs = imageAttrs(Astro.props); 16 14 --- 17 15 18 16 <figure> 19 17 { 20 18 generalContentType === "image" && ( 21 - <a href={distSource}> 19 + <a href={attrs.src}> 22 20 <img 23 - src={distSource} 24 - srcset={thumbnailsSrcSet} 21 + src={attrs.src} 22 + srcset={attrs.srcset} 25 23 alt={alt} 26 24 height={dimensions.height} 27 25 width={dimensions.width} ··· 36 34 height={dimensions.height} 37 35 width={dimensions.width} 38 36 > 39 - <source src={distSource} type={contentType} /> 37 + <source src={attrs.src} type={contentType} /> 40 38 </video> 41 39 ) 42 40 } 43 41 { 44 42 generalContentType === "audio" && ( 45 43 <audio {...attributes}> 46 - <source src={distSource} type={contentType} /> 44 + <source src={attrs.src} type={contentType} /> 47 45 </audio> 48 46 ) 49 47 } 50 48 { 51 49 contentType === "application/pdf" && ( 52 - <a href={distSource}> 53 - <img srcset={thumbnailsSrcSet} alt={alt} /> 50 + <a href={attrs.src}> 51 + <img srcset={attrs.srcset} alt={alt} /> 54 52 </a> 55 53 ) 56 54 }
+35 -19
src/pages/works/[work].astro
··· 8 8 import BlockLink from "./BlockLink.astro"; 9 9 import BlockMedia from "./BlockMedia.astro"; 10 10 import BlockParagraph from "./BlockParagraph.astro"; 11 + import { imageAttrs } from "./media"; 11 12 12 13 export const getStaticPaths = (async () => { 13 14 return await getCollection("works").then((works) => ··· 46 47 47 48 const { 48 49 metadata, 49 - metadata: { tags, wip, colors }, 50 + metadata: { tags, wip, colors, additionalMetadata: misc }, 50 51 } = entry.data; 52 + 53 + const titleStyle = misc?.title_style ?? ""; 51 54 52 55 const content = Object.keys(entry.data.content).includes("default") 53 56 ? { fr: entry.data.content.default, en: entry.data.content.default } 54 57 : entry.data.content; 55 58 56 - const madeWith = await Promise.all( 57 - metadata.madeWith?.map((tech) => getEntry("technologies", tech.id)) ?? [], 59 + let madeWith = await Promise.all( 60 + metadata.madeWith?.map((tech) => getEntry("technologies", tech.id)) ?? 61 + metadata.additionalMetadata?.made_with?.map((tech) => 62 + getEntry("technologies", tech), 63 + ) ?? 64 + [], 58 65 ).then((techs) => techs.filter((x) => !!x)); 59 66 60 67 const { blocks, layout, footnotes } = ··· 75 82 const cssGridAreas = layout 76 83 .map((row) => '"' + row.map((cell) => `_${cell}`).join(" ") + '"') 77 84 .join(" "); 85 + 86 + const firstMediaBlock = blocks.find((b) => b.type === "media"); 78 87 --- 79 88 80 89 <Layout colors={colors}> 81 90 <StrongHeader 82 91 back="/" 83 92 editButton={entry.data.source} 84 - title={{ fr: content.fr?.title, en: content.en?.title }} 93 + title={titleStyle === "image" && firstMediaBlock 94 + ? { img: imageAttrs(firstMediaBlock) } 95 + : { fr: content.fr?.title, en: content.en?.title }} 85 96 wip={wip} 86 97 > 87 98 <section class="tags"> ··· 95 106 { 96 107 ( 97 108 <section style={`grid-template-areas: ${cssGridAreas}; `}> 98 - {blocks.map((block) => ( 99 - <div 100 - id={block.anchor || undefined} 101 - class={`block ${isLoneRow(block.id, layout) && hasMediaRowBefore(block.id, layout, blocks) ? "indent" : ""}`} 102 - data-type={block.type} 103 - data-block-id={block.id} 104 - style={`grid-area: _${block.id}`} 105 - > 106 - {block.type === "paragraph" && <BlockParagraph {...block} />} 107 - {block.type === "link" && <BlockLink {...block} />} 108 - {block.type === "media" && <BlockMedia {...block} />} 109 - </div> 110 - ))} 109 + {blocks 110 + .filter((b) => 111 + titleStyle === "image" ? b.id !== firstMediaBlock?.id : true, 112 + ) 113 + .map((block) => ( 114 + <div 115 + id={block.anchor || undefined} 116 + class={`block ${isLoneRow(block.id, layout) && hasMediaRowBefore(block.id, layout, blocks) ? "indent" : ""}`} 117 + data-type={block.type} 118 + data-block-id={block.id} 119 + style={`grid-area: _${block.id}`} 120 + > 121 + {block.type === "paragraph" && <BlockParagraph {...block} />} 122 + {block.type === "link" && <BlockLink {...block} />} 123 + {block.type === "media" && <BlockMedia {...block} />} 124 + </div> 125 + ))} 111 126 </section> 112 127 ) 113 128 } ··· 120 135 <ul class="technologies"> 121 136 {madeWith.map(({ id, data: { name } }) => ( 122 137 <li> 123 - <a href={`/using/${id}`}>{name}</a> 138 + <a href={`/using/${id}`}>{name === "C Sharp" ? "C#" : name}</a> 124 139 </li> 125 140 ))} 126 141 </ul> ··· 153 168 <code 154 169 class="swatch" 155 170 style={`background-color: ${color}; color: var(--${name === "primary" ? "secondary" : "primary"}, black)`} 171 + onclick={`navigator.clipboard.writeText(JSON.stringify('${color}'))`} 156 172 > 157 - C{i + 1} 173 + {["⊓", "⊔", "⊐"][i]} 158 174 </code> 159 175 )) 160 176 }
+22
src/pages/works/media.ts
··· 1 + import type { InferEntrySchema } from "astro:content"; 2 + 3 + type Block = 4 + InferEntrySchema<"works">["content"][keyof InferEntrySchema<"works">["content"]]["blocks"][number]; 5 + 6 + export function imageAttrs({ distSource, thumbnails, alt, dimensions }: Block): { 7 + src: string; 8 + srcset: string; 9 + alt: string; 10 + height: string; 11 + width: string; 12 + } { 13 + return { 14 + height: dimensions.height.toString(), 15 + width: dimensions.width.toString(), 16 + alt: alt, 17 + src: `https://media.gwen.works/${distSource}`, 18 + srcset: Object.entries(thumbnails ?? {}) 19 + .map(([size, path]) => `https://media.gwen.works/${path} ${size}w`) 20 + .join(", "), 21 + }; 22 + }
+1
src/pages/works/types.ts
··· 1 + import type { InferEntrySchema } from "astro:content";