Compare commits
3 Commits
246fc3ae44
...
main
Author | SHA1 | Date | |
---|---|---|---|
|
06e5126fe0
|
||
|
61251e2c85
|
||
|
a1b8eb22e5
|
32
package.json
32
package.json
@@ -11,32 +11,32 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/mdx": "^4.3.1",
|
||||
"@astrojs/svelte": "^7.1.0",
|
||||
"@astrojs/mdx": "^4.3.6",
|
||||
"@astrojs/svelte": "^7.2.0",
|
||||
"@astrojs/tailwind": "^6.0.2",
|
||||
"astro": "^5.12.0",
|
||||
"astro": "^5.14.1",
|
||||
"astro-i18n-aut": "^0.7.3",
|
||||
"exifreader": "^4.31.1",
|
||||
"svelte": "^5.36.10",
|
||||
"svelte-gestures": "^5.1.4",
|
||||
"tailwindcss": "^4.1.11",
|
||||
"exifreader": "^4.32.0",
|
||||
"svelte": "^5.39.8",
|
||||
"svelte-gestures": "^5.2.2",
|
||||
"tailwindcss": "^4.1.14",
|
||||
"thumbhash": "^0.1.1",
|
||||
"typescript": "^5.8.3"
|
||||
"typescript": "^5.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/sitemap": "^3.4.1",
|
||||
"@iconify-json/tabler": "^1.2.19",
|
||||
"@astrojs/sitemap": "^3.6.0",
|
||||
"@iconify-json/tabler": "^1.2.23",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@unocss/preset-icons": "^66.3.3",
|
||||
"@unocss/reset": "^66.3.3",
|
||||
"@unocss/preset-icons": "^66.5.2",
|
||||
"@unocss/reset": "^66.5.2",
|
||||
"astro-font": "^1.1.0",
|
||||
"markdown-it": "^14.1.0",
|
||||
"ogl": "^1.0.11",
|
||||
"prettier": "^3.6.2",
|
||||
"prettier-plugin-astro": "^0.14.1",
|
||||
"sharp": "^0.34.3",
|
||||
"unocss": "^66.3.3",
|
||||
"unplugin-icons": "^22.1.0",
|
||||
"vite-plugin-glsl": "^1.5.1"
|
||||
"sharp": "^0.34.4",
|
||||
"unocss": "^66.5.2",
|
||||
"unplugin-icons": "^22.4.2",
|
||||
"vite-plugin-glsl": "^1.5.4"
|
||||
}
|
||||
}
|
||||
|
2476
pnpm-lock.yaml
generated
2476
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -13,16 +13,15 @@ interface Props {
|
||||
maxWidth?: number;
|
||||
}
|
||||
|
||||
async function checkImage(src:string){
|
||||
async function checkImage(src: string) {
|
||||
try {
|
||||
const res = await fetch(src);
|
||||
if (res.ok) {
|
||||
return src
|
||||
return src;
|
||||
}
|
||||
return undefined
|
||||
}catch(err){
|
||||
console.log({src});
|
||||
return undefined
|
||||
return undefined;
|
||||
} catch (err) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +36,7 @@ const {
|
||||
|
||||
let thumbhash = hash && image.fsPath ? await generateThumbHash(image) : "";
|
||||
|
||||
const imageSrc = await checkImage(image);
|
||||
const imageSrc = await checkImage(image.src);
|
||||
|
||||
let exif = await getExifData(image);
|
||||
|
||||
@@ -60,8 +59,9 @@ const sizes = [
|
||||
].filter((size) => !maxWidth || size.width <= maxWidth);
|
||||
---
|
||||
|
||||
{imageSrc?
|
||||
<AstroImage
|
||||
{
|
||||
imageSrc ? (
|
||||
<AstroImage
|
||||
src={imageSrc}
|
||||
alt={alt}
|
||||
data-thumbhash={thumbhash}
|
||||
@@ -76,5 +76,6 @@ const sizes = [
|
||||
.map((size) => `${size.media || "100vw"} ${size.width}px`)
|
||||
.join(", ")}>
|
||||
<slot />
|
||||
</AstroImage>
|
||||
:undefined }
|
||||
</AstroImage>
|
||||
) : undefined
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@
|
||||
let progress: number[] = [];
|
||||
let currentIndex = -1;
|
||||
const maxZoom = 5;
|
||||
import { swipe } from "svelte-gestures";
|
||||
import { useSwipe } from "svelte-gestures";
|
||||
|
||||
const mod = (a: number, b: number) => ((a % b) + b) % b;
|
||||
|
||||
@@ -232,10 +232,9 @@
|
||||
|
||||
{#if currentIndex > -1}
|
||||
<div
|
||||
{...useSwipe(handleSwipe)}
|
||||
class="image"
|
||||
use:swipe
|
||||
role="dialog"
|
||||
on:swipe={handleSwipe}
|
||||
on:wheel|passive={handleScroll}
|
||||
on:mousemove={handleMouseMove}
|
||||
on:pointermove={handlePointerMove}>
|
||||
|
@@ -1,10 +1,47 @@
|
||||
export async function listResource(id: string): Promise<any[]> {
|
||||
export type MemoriumFile = {
|
||||
type: "file";
|
||||
name: string;
|
||||
path: string;
|
||||
modTime: string;
|
||||
mime: string;
|
||||
size: string;
|
||||
content: unknown;
|
||||
};
|
||||
|
||||
export type MemoriumDir = {
|
||||
type: "dir";
|
||||
name: string;
|
||||
path: string;
|
||||
modTime: string;
|
||||
mime: string;
|
||||
size: string;
|
||||
content: MemoriumEntry[];
|
||||
};
|
||||
|
||||
export type MemoriumEntry = MemoriumFile | MemoriumDir;
|
||||
|
||||
export async function listResource(
|
||||
id: string,
|
||||
): Promise<MemoriumEntry | undefined> {
|
||||
const url = `https://marka.max-richter.dev/${id}`;
|
||||
console.log("Fetching: ", url);
|
||||
try {
|
||||
const response = await fetch(
|
||||
`https://marka.max-richter.dev/${id}`,
|
||||
);
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
return [];
|
||||
const response = await fetch(url);
|
||||
if (response.ok) {
|
||||
const json = await response.json();
|
||||
if (json.type == "dir") {
|
||||
return {
|
||||
...json,
|
||||
content: json.content.filter((res) =>
|
||||
res.mime === "application/markdown"
|
||||
),
|
||||
};
|
||||
}
|
||||
return json;
|
||||
}
|
||||
} catch (_e) {
|
||||
console.log("Failed to get: ", url);
|
||||
console.log(_e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@@ -1,38 +0,0 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const movieReviews = await memorium.listResource("Media/movies/*");
|
||||
|
||||
const paths = movieReviews.map((review: any) => {
|
||||
return {
|
||||
params: {
|
||||
movieName: review.identifier
|
||||
.replace("Media/movies/", "")
|
||||
.replace(/\.md$/, ""),
|
||||
},
|
||||
};
|
||||
});
|
||||
return paths;
|
||||
}
|
||||
|
||||
const reviews = await memorium.listResource(
|
||||
//@ts-ignore
|
||||
`Media/movies/${Astro.params.movieName}.md`,
|
||||
);
|
||||
|
||||
if (reviews.length === 0) {
|
||||
return new Response(null, {
|
||||
status: 404,
|
||||
statusText: "Not found",
|
||||
});
|
||||
}
|
||||
const review = reviews[0];
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
<h1>{review.itemReviewed?.name}</h1>
|
||||
<p>{review.reviewBody}</p>
|
||||
<!-- <pre><code>{JSON.stringify(review, null, 2)}</code></pre> -->
|
||||
</Layout>
|
@@ -1,27 +0,0 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import HeroCard from "@components/HeroCard.astro";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
|
||||
const movieReviews = await memorium.listResource("Media/movies/*");
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
{
|
||||
movieReviews.map((review: any) => (
|
||||
<HeroCard
|
||||
post={{
|
||||
collection: "resources/movies",
|
||||
id: review.identifier
|
||||
.replace("Media/movies/", "")
|
||||
.replace(/\.md$/, ""),
|
||||
data: {
|
||||
title: review.itemReviewed.name,
|
||||
description: review.reviewBody,
|
||||
},
|
||||
body: review.reviewBody,
|
||||
}}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Layout>
|
@@ -1,73 +0,0 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import { useTranslatedPath } from "@i18n/utils";
|
||||
import markdownToText from "@helpers/markdownToText";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
|
||||
const path = useTranslatedPath(Astro.url);
|
||||
|
||||
const collection = "resources/Recipes";
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const recipes = await memorium.listResource("Recipes");
|
||||
|
||||
const paths = recipes.content.filter(res =>res.content).map((recipe: any) => {
|
||||
return {
|
||||
params: {
|
||||
recipeName: recipe.name.replace(/\.md$/, ""),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
const recipeResponse = await memorium.listResource(
|
||||
//@ts-ignore
|
||||
`Recipes/${Astro.params.recipeName}.md`,
|
||||
);
|
||||
if (!recipeResponse?.content) {
|
||||
return new Response(null, {
|
||||
status: 404,
|
||||
statusText: "Not found",
|
||||
});
|
||||
}
|
||||
const recipe = recipeResponse.content;
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
<div class="top-info flex items-center place-content-between m-y-2">
|
||||
<a class="flex items-center gap-1 opacity-50" href={path("/" + collection)}>
|
||||
<span class="i-tabler-arrow-left"></span> back
|
||||
</a>
|
||||
<div class="date opacity-50">
|
||||
{
|
||||
recipe.date?.toLocaleString("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>{recipe.name}</h1>
|
||||
|
||||
<h3>Ingredients</h3>
|
||||
<ul>
|
||||
{
|
||||
recipe.recipeIngredient?.map((ingredient: any) => (
|
||||
<li>{markdownToText(ingredient??"")}</li>
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
|
||||
<h3>Instructions</h3>
|
||||
<ol>
|
||||
{
|
||||
recipe.recipeIngredient?.map((ingredient: any) => (
|
||||
<li>{markdownToText(ingredient??"")}</li>
|
||||
))
|
||||
}
|
||||
</ol>
|
||||
</Layout>
|
@@ -1,32 +0,0 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import HeroCard from "@components/HeroCard.astro";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
|
||||
const recipes = await memorium.listResource("Recipes");
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
{
|
||||
recipes.content
|
||||
.filter((res) => res.content)
|
||||
.map((recipe: any) => (
|
||||
<HeroCard
|
||||
post={{
|
||||
collection: "resources/Recipes",
|
||||
id: recipe.name.replace(/\.md$/, ""),
|
||||
data: {
|
||||
cover: recipe.content?.image
|
||||
? `http://localhost:8080/${recipe.content.image}`
|
||||
: undefined,
|
||||
title: recipe.name.replace(/\.md$/, ""),
|
||||
},
|
||||
}}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Layout>
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Layout>
|
@@ -1,58 +0,0 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import { useTranslatedPath } from "@i18n/utils";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
|
||||
const collection = "resources/series";
|
||||
|
||||
const path = useTranslatedPath(Astro.url);
|
||||
|
||||
export async function getStaticPaths() {
|
||||
const seriesReviews = await memorium.listResource("Media/series/*");
|
||||
|
||||
const paths = seriesReviews.map((review: any) => {
|
||||
return {
|
||||
params: {
|
||||
seriesName: review.identifier
|
||||
.replace("Media/series/", "")
|
||||
.replace(/\.md$/, ""),
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
||||
const reviews = await memorium.listResource(
|
||||
//@ts-ignore
|
||||
`Media/series/${Astro.params.seriesName}.md`,
|
||||
);
|
||||
if (reviews.length === 0) {
|
||||
return new Response(null, {
|
||||
status: 404,
|
||||
statusText: "Not found",
|
||||
});
|
||||
}
|
||||
const review = reviews[0];
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
<div class="top-info flex items-center place-content-between m-y-2">
|
||||
<a class="flex items-center gap-1 opacity-50" href={path("/" + collection)}>
|
||||
<span class="i-tabler-arrow-left"></span> back
|
||||
</a>
|
||||
<div class="date opacity-50">
|
||||
{
|
||||
review.date?.toLocaleString("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>{review.itemReviewed?.name}</h1>
|
||||
<p>{review.reviewBody}</p>
|
||||
</Layout>
|
@@ -1,27 +0,0 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import HeroCard from "@components/HeroCard.astro";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
|
||||
const seriesReviewes = await memorium.listResource("Media/series/*");
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
{
|
||||
seriesReviewes.map((review: any) => (
|
||||
<HeroCard
|
||||
post={{
|
||||
collection: "resources/series",
|
||||
id: review.identifier
|
||||
.replace("Media/series/", "")
|
||||
.replace(/\.md$/, ""),
|
||||
data: {
|
||||
title: review.itemReviewed.name,
|
||||
description: review.reviewBody,
|
||||
},
|
||||
body: review.reviewBody,
|
||||
}}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Layout>
|
65
src/pages/resources/[resourceType]/[resourceName].astro
Normal file
65
src/pages/resources/[resourceType]/[resourceName].astro
Normal file
@@ -0,0 +1,65 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import { useTranslatedPath } from "@i18n/utils";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
import { resources as resourceTypes } from "../resources.ts";
|
||||
import markdownToText from "@helpers/markdownToText";
|
||||
|
||||
const { resourceType, resourceName } = Astro.params;
|
||||
|
||||
const path = useTranslatedPath(Astro.url);
|
||||
|
||||
export async function getStaticPaths(props) {
|
||||
const paths = await Promise.all(resourceTypes.map(async (resourceType: string) => {
|
||||
const resources = await memorium.listResource(resourceType.id);
|
||||
return resources.content.map((res: any) => {
|
||||
return {
|
||||
params: {
|
||||
resourceType: resourceType.id,
|
||||
resourceName: res.name.replace(/\.md$/,"")
|
||||
},
|
||||
};
|
||||
});
|
||||
}));
|
||||
|
||||
const flat = paths.flat();
|
||||
|
||||
console.log(flat.map(p => `/resources/${p.params.resourceType}/${p.params.resourceName}`))
|
||||
|
||||
return flat;
|
||||
}
|
||||
|
||||
|
||||
const resource = await memorium.listResource(
|
||||
`/${resourceType}/${resourceName}.md`
|
||||
);
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
<div class="top-info flex items-center place-content-between m-y-2">
|
||||
<a class="flex items-center gap-1 opacity-50" href={path("/resources/"+resourceType)}>
|
||||
<span class="i-tabler-arrow-left"></span> back
|
||||
</a>
|
||||
<div class="date opacity-50">
|
||||
{
|
||||
resource?.content.date?.toLocaleString("en-US", {
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h1>{resource?.content?.name}</h1>
|
||||
<p>{resource?.content?.description}</p>
|
||||
<h2>Ingredients</h2>
|
||||
<ul>
|
||||
{resource.content.recipeIngredient.map(ingredient => <li>{markdownToText(ingredient)}</li>)}
|
||||
</ul>
|
||||
|
||||
<h2>Steps</h2>
|
||||
<ol>
|
||||
{resource.content.recipeInstructions.map(ingredient => <li>{markdownToText(ingredient)}</li>)}
|
||||
</ol>
|
||||
</Layout>
|
37
src/pages/resources/[resourceType]/index.astro
Normal file
37
src/pages/resources/[resourceType]/index.astro
Normal file
@@ -0,0 +1,37 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import HeroCard from "@components/HeroCard.astro";
|
||||
import * as memorium from "@helpers/memorium";
|
||||
import { resources as resourceTypes } from "../resources.ts";
|
||||
|
||||
const { resourceType } = Astro.params;
|
||||
|
||||
const resources = await memorium.listResource(resourceType);
|
||||
|
||||
export async function getStaticPaths(): string[] {
|
||||
return resourceTypes.map((type: any) => {
|
||||
return {
|
||||
params: {
|
||||
resourceType: type.id,
|
||||
resourceName: "Recipe"
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
{ resources.content.filter(res => res && res?.content && res?.content?.name).map((resource: any) => (
|
||||
<HeroCard
|
||||
post={{
|
||||
collection: "resources/"+resourceType,
|
||||
id: resource.name.replace(/\.md$/,""),
|
||||
data: {
|
||||
title: resource.content.name,
|
||||
cover: {src:`https://marka.max-richter.dev/${resource.content.image}`}
|
||||
},
|
||||
}}
|
||||
/>
|
||||
))
|
||||
}
|
||||
</Layout>
|
@@ -1,64 +1,9 @@
|
||||
---
|
||||
import Layout from "@layouts/Layout.astro";
|
||||
import HeroCard from "@components/HeroCard.astro";
|
||||
|
||||
const collection = "resources";
|
||||
|
||||
const wiki = {
|
||||
id: "wiki",
|
||||
collection,
|
||||
body: "My knowledge base",
|
||||
data: {
|
||||
title: "Wiki",
|
||||
icon: "🧠",
|
||||
},
|
||||
};
|
||||
|
||||
const articles = {
|
||||
id: "Articles",
|
||||
collection,
|
||||
body: "Articles saved",
|
||||
data: {
|
||||
title: "Articles",
|
||||
icon: "📰",
|
||||
},
|
||||
};
|
||||
|
||||
const recipes = {
|
||||
id: "Recipes",
|
||||
collection,
|
||||
body: "Recipes",
|
||||
data: {
|
||||
title: "Recipes",
|
||||
icon: "🍲",
|
||||
},
|
||||
};
|
||||
|
||||
const movies = {
|
||||
id: "Movies",
|
||||
collection,
|
||||
body: "Movies",
|
||||
data: {
|
||||
title: "Movies",
|
||||
icon: "🎥",
|
||||
},
|
||||
};
|
||||
|
||||
const series = {
|
||||
id: "Series",
|
||||
collection,
|
||||
body: "Series",
|
||||
data: {
|
||||
title: "Series",
|
||||
icon: "📺",
|
||||
},
|
||||
};
|
||||
import { resources } from "./resources.ts";
|
||||
---
|
||||
|
||||
<Layout title="Max Richter">
|
||||
<HeroCard post={wiki} />
|
||||
<HeroCard post={recipes} />
|
||||
<HeroCard post={articles} />
|
||||
<HeroCard post={movies} />
|
||||
<HeroCard post={series} />
|
||||
{resources.map((resource) => <HeroCard post={resource} />)}
|
||||
</Layout>
|
||||
|
63
src/pages/resources/resources.ts
Normal file
63
src/pages/resources/resources.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
const collection = "resources";
|
||||
|
||||
type Resource = {
|
||||
id: string;
|
||||
collection: string;
|
||||
body: string;
|
||||
data: {
|
||||
title: string;
|
||||
icon: string;
|
||||
};
|
||||
};
|
||||
|
||||
// const wiki = {
|
||||
// id: "wiki",
|
||||
// collection,
|
||||
// body: "My knowledge base",
|
||||
// data: {
|
||||
// title: "Wiki",
|
||||
// icon: "🧠",
|
||||
// },
|
||||
// };
|
||||
|
||||
// const articles = {
|
||||
// id: "Articles",
|
||||
// collection,
|
||||
// body: "Articles saved",
|
||||
// data: {
|
||||
// title: "Articles",
|
||||
// icon: "📰",
|
||||
// },
|
||||
// };
|
||||
|
||||
const recipes = {
|
||||
id: "Recipes",
|
||||
collection,
|
||||
body: "Recipes",
|
||||
data: {
|
||||
title: "Recipes",
|
||||
icon: "🍲",
|
||||
},
|
||||
};
|
||||
|
||||
// const movies = {
|
||||
// id: "Movies",
|
||||
// collection,
|
||||
// body: "Movies",
|
||||
// data: {
|
||||
// title: "Movies",
|
||||
// icon: "🎥",
|
||||
// },
|
||||
// };
|
||||
|
||||
// const series = {
|
||||
// id: "Series",
|
||||
// collection,
|
||||
// body: "Series",
|
||||
// data: {
|
||||
// title: "Series",
|
||||
// icon: "📺",
|
||||
// },
|
||||
// };
|
||||
|
||||
export const resources: Resource[] = [recipes];
|
@@ -1,5 +1,10 @@
|
||||
import { vitePreprocess } from '@astrojs/svelte';
|
||||
import { vitePreprocess } from "@astrojs/svelte";
|
||||
|
||||
export default {
|
||||
preprocess: vitePreprocess(),
|
||||
}
|
||||
compilerOptions: {
|
||||
experimental: {
|
||||
async: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@@ -11,7 +11,8 @@
|
||||
"baseUrl": ".",
|
||||
"types": [
|
||||
"vite-plugin-glsl/ext",
|
||||
"unplugin-icons/types"
|
||||
"unplugin-icons/types",
|
||||
"svelte-gestures/globals"
|
||||
],
|
||||
"paths": {
|
||||
"@components/*": [
|
||||
|
Reference in New Issue
Block a user