Add attributes for demonstation purposes

This commit is contained in:
Luca Bosin
2023-08-18 20:47:03 +02:00
parent d12462222f
commit 6ae22b7a9c
14 changed files with 84 additions and 113 deletions

30
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,30 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Build & Deploy",
"type": "shell",
"command": "npm run build && rsync -arzP --progress --delete-after --force --update --inplace --times ./build ./package.json ./package-lock.json root@f.bosin.ch:/home/sveltekit"
},
{
"label": "Restart Server",
"type": "shell",
"command": "ssh f.bosin.ch systemctl restart bosin-files"
},
{
"label": "Full Deploy",
"dependsOn": [
"Build & Deploy"
],
"type": "shell",
"command": "ssh f.bosin.ch systemctl restart bosin-files",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}

View File

@ -1,38 +1,5 @@
# create-svelte
# f.bosin.ch/g
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
Die neue Fotogalerie von Luca Bosin.
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm create svelte@latest
# create a new project in my-app
npm create svelte@latest my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
Jetzt testen, auf [f.bosin.ch/g/test](https://f.bosin.ch/g/test).

View File

@ -1,4 +1,5 @@
<script>
import { getFileName } from '$lib/util/links';
import { strf } from '$lib/data/language.js';
function sortItems() {
@ -22,10 +23,12 @@
<li>
<h3>{item.item}</h3>
<p>
<b>Title:</b> {$strf(item.title)}<br />
<b>Description:</b> {#if item.description}{$strf(item.description)}{:else}<i>no description</i>{/if}
<b>Title:</b> {#if item.title}{$strf(item.title)}{:else}<i>no title</i>{/if}<br />
<b>Description:</b> {#if item.description}{$strf(item.description)}{:else}<i>no description</i>{/if}<br />
<b>Links:</b> <a href={`${base}${item.item}`}>Open</a> &bullet; <a href={`${base}${item.item}/download`}>Download</a><br />
<b>Thumbnails:</b> <a href={`${base}${item.item}/t/s`}>Small</a> &bullet; <a href={`${base}${item.item}/t/m`}>Medium</a> &bullet; <a href={`${base}${item.item}/t/l`}>Large</a> &bullet; <a href={`${base}${item.item}/t/full`}>Full</a>
</p>
<img src={`${base}${item.item}/t`} alt={$strf(item.title) || item.item} />
<img src={`${base}${item.item}/t`} alt={(item.title ? $strf(item.title) : null) || (item.description ? $strf(item.description) : null) || getFileName(item.item)} />
</li>
{/each}
</ul>

3
src/lib/types.d.ts vendored
View File

@ -12,7 +12,6 @@ type License = {
}
type Metadata = {
title: Translation | string;
description?: Translation | string;
authors?: string[] | string;
place?: string;
@ -21,11 +20,13 @@ type Metadata = {
}
type AlbumMetadata = Metadata & {
title: Translation | string;
date: string; // ISO 8601, e.g. 2020-12-24, used for sorting
cover?: string;
};
type ItemMetadata = Metadata & {
title?: Translation | string;
item: string;
timestamp?: string; // ISO 8601, e.g. 2020-12-24T12:00:00Z
};

View File

@ -0,0 +1,9 @@
<slot />
<style>
:global(*) {
box-sizing: border-box;
margin: 0;
padding: 0;
}
</style>

View File

@ -1,14 +1,12 @@
import { getMetadataOpen } from '$lib/util/album';
import { getMetadata } from '$lib/util/album';
import { getAlbumUri, getZipName } from '$lib/util/links';
/** @type {import('./$types').PageLoad} */
export async function load({ params }) {
const {zip, album} = await getMetadataOpen(getZipName(params));
const entries = await zip.entries();
const album = await getMetadata(getZipName(params));
const base = getAlbumUri(params);
await zip.close();
return {
album, entries, base
album, base
};
}

View File

@ -11,4 +11,10 @@
</script>
<Header title={$strf(data.album.title)}/>
<p>
<b>Description:</b> {#if data.album.description}{$strf(data.album.description)}{:else}<i>no description</i>{/if}<br />
<b>Authors: </b> {#if data.album.authors}{Array.isArray(data.album.authors) ? data.album.authors.join(', ') : data.album.authors}{:else}<i>unknown author</i>{/if}<br />
<b>Sorting Date:</b> {data.album.date}<br />
<b>License:</b> {data.album.license}<br />
</p>
<Gallery items={data.album.items} base={`${data.base}/i/`} />

View File

@ -1,29 +0,0 @@
import { error } from '@sveltejs/kit';
import StreamZip from 'node-stream-zip';
/** @type {import('./$types').LayoutLoad} */
export async function load({ params }) {
const { slug, timestamp } = params;
const cslug = slug.replace(/[^\w-]/gi, '');
const ctimestamp = timestamp?.replace(/[^\w-]/gi, '');
const file = `./zip/${cslug}${ctimestamp ? '-' + ctimestamp :''}.zip`;
let entries = null;
try {
const zip = new StreamZip.async({ file });
entries = await zip.entries();
await zip.close();
} catch (err) {
console.error(err);
throw error(404, 'Not found');
}
console.log(`REQ: ${cslug}/${ctimestamp} @ ${file} with ${entries.length} entries:\n ${JSON.stringify(entries)}`);
return {
file,
cslug,
ctimestamp,
entries
};
}

View File

@ -1,8 +1,14 @@
import { getFileName } from '$lib/util/links.js';
import { getMetadata } from '$lib/util/album';
import { getFileName, getFilePath, getZipName } from '$lib/util/links.js';
/** @type {import('./$types').PageLoad} */
export async function load({ params }) {
const album = await getMetadata(getZipName(params));
const filePath = getFilePath(params.item);
const item = album.items.find(item => item.item === filePath);
return {
item,
filename: getFileName(params.item)
}
};

View File

@ -1,6 +1,19 @@
<script>
import { strf } from '$lib/data/language';
/** @type {import('./$types').PageData} */
export let data;
</script>
<img src="./{data.filename}/t/full" />
{#if data.item}
<img class="image" src="{data.filename}/t/full" alt={(data.item.title ? $strf(data.item.title) : null) || (data.item.description ? $strf(data.item.description) : null) || data.filename} />
{:else}
<p>Item not found.</p>
{/if}
<style>
.image {
max-width: 100%;
max-height: 100%;
}
</style>

View File

@ -1,14 +1,14 @@
import { getFile } from '$lib/util/album';
import { getFilePath, getZipName } from '$lib/util/links';
import { getFileName, getFilePath, getZipName } from '$lib/util/links';
import sharp from 'sharp';
/** @type {import('./$types').RequestHandler} */
export async function GET({ params }) {
let thumbnail = null;
console.log(`Getting thumbnail for ${params}`);
let width = 400;
try {
const content = await getFile(getZipName(params), getFilePath(params.item));
let width = 400;
if (params.width) {
if (params.width === 'full') {
thumbnail = await sharp(content).webp({ quality: 90 }).toBuffer();
@ -29,7 +29,7 @@ export async function GET({ params }) {
return new Response(thumbnail, {
headers: {
'Content-Type': 'image/webp',
'Content-Disposition': 'inline'
'Content-Disposition': `inline; filename="${getFileName(params.item)}-thumb-${params.width === 'full' ? 'full' : width}.webp"`,
}
});
}

View File

@ -1,20 +0,0 @@
import { error } from '@sveltejs/kit';
import StreamZip from 'node-stream-zip';
/** @type {import('./$types').PageLoad} */
export async function load({ params }) {
let entries = null;
try {
const zip = new StreamZip.async({ file: `./zip/${params.slug}.zip` });
entries = await zip.entries();
await zip.close();
} catch (err) {
console.error(err);
}
error(404, 'Not found');
return {
slug: params.slug,
timestamp: params.timestamp,
entries
};
}

View File

@ -1,13 +0,0 @@
<script>
/** @type {import('./$types').PageData} */
export let data;
/** @type {import('node-stream-zip').ZipEntry[]} */
$: entries = data.entries !== null ? (Array.isArray(data.entries) ? data.entries : Object.values(data.entries)) : [];
</script>
<h2>Zip Entries</h2>
{#each entries as entry}
{entry.name}
{:else}
No entries
{/each}