fix assets transform in prod
@@ -23,6 +23,7 @@
|
|||||||
"@sveltejs/adapter-static": "^2.0.3",
|
"@sveltejs/adapter-static": "^2.0.3",
|
||||||
"@sveltejs/kit": "^1.24.1",
|
"@sveltejs/kit": "^1.24.1",
|
||||||
"@types/compression": "^1.7.3",
|
"@types/compression": "^1.7.3",
|
||||||
|
"@types/glob": "^8.1.0",
|
||||||
"@types/markdown-it": "^13.0.1",
|
"@types/markdown-it": "^13.0.1",
|
||||||
"@types/morgan": "^1.9.6",
|
"@types/morgan": "^1.9.6",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||||
@@ -30,6 +31,7 @@
|
|||||||
"eslint": "^8.49.0",
|
"eslint": "^8.49.0",
|
||||||
"eslint-config-prettier": "^8.10.0",
|
"eslint-config-prettier": "^8.10.0",
|
||||||
"eslint-plugin-svelte": "^2.33.1",
|
"eslint-plugin-svelte": "^2.33.1",
|
||||||
|
"glob": "^10.3.10",
|
||||||
"openapi-types": "^12.1.3",
|
"openapi-types": "^12.1.3",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"prettier-plugin-svelte": "^2.10.1",
|
"prettier-plugin-svelte": "^2.10.1",
|
||||||
|
|||||||
35
pnpm-lock.yaml
generated
@@ -13,7 +13,7 @@ dependencies:
|
|||||||
version: 0.1.0-next.9
|
version: 0.1.0-next.9
|
||||||
'@appwrite.io/repo':
|
'@appwrite.io/repo':
|
||||||
specifier: github:appwrite/appwrite
|
specifier: github:appwrite/appwrite
|
||||||
version: github.com/appwrite/appwrite/8a4302ffe6173e6b1256da5e7c86042d73983cdb
|
version: github.com/appwrite/appwrite/030f9629a69f7db0f3da3e76d1805383bb3a3acd
|
||||||
'@splinetool/viewer':
|
'@splinetool/viewer':
|
||||||
specifier: 0.9.455
|
specifier: 0.9.455
|
||||||
version: 0.9.455
|
version: 0.9.455
|
||||||
@@ -61,6 +61,9 @@ devDependencies:
|
|||||||
'@types/compression':
|
'@types/compression':
|
||||||
specifier: ^1.7.3
|
specifier: ^1.7.3
|
||||||
version: 1.7.3
|
version: 1.7.3
|
||||||
|
'@types/glob':
|
||||||
|
specifier: ^8.1.0
|
||||||
|
version: 8.1.0
|
||||||
'@types/markdown-it':
|
'@types/markdown-it':
|
||||||
specifier: ^13.0.1
|
specifier: ^13.0.1
|
||||||
version: 13.0.1
|
version: 13.0.1
|
||||||
@@ -82,6 +85,9 @@ devDependencies:
|
|||||||
eslint-plugin-svelte:
|
eslint-plugin-svelte:
|
||||||
specifier: ^2.33.1
|
specifier: ^2.33.1
|
||||||
version: 2.33.2(eslint@8.49.0)(svelte@4.2.0)
|
version: 2.33.2(eslint@8.49.0)(svelte@4.2.0)
|
||||||
|
glob:
|
||||||
|
specifier: ^10.3.10
|
||||||
|
version: 10.3.10
|
||||||
openapi-types:
|
openapi-types:
|
||||||
specifier: ^12.1.3
|
specifier: ^12.1.3
|
||||||
version: 12.1.3
|
version: 12.1.3
|
||||||
@@ -876,6 +882,13 @@ packages:
|
|||||||
'@types/node': 20.5.0
|
'@types/node': 20.5.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/glob@8.1.0:
|
||||||
|
resolution: {integrity: sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==}
|
||||||
|
dependencies:
|
||||||
|
'@types/minimatch': 5.1.2
|
||||||
|
'@types/node': 20.5.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/http-errors@2.0.2:
|
/@types/http-errors@2.0.2:
|
||||||
resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==}
|
resolution: {integrity: sha512-lPG6KlZs88gef6aD85z3HNkztpj7w2R7HmR3gygjfXCQmsLloWNARFkMuzKiiY8FGdh1XDpgBdrSf4aKDiA7Kg==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -922,6 +935,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ==}
|
resolution: {integrity: sha512-Wj+fqpTLtTbG7c0tH47dkahefpLKEbB+xAZuLq7b4/IDHPl/n6VoXcyUQ2bypFlbSwvCr0y+bD4euTTqTJsPxQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/minimatch@5.1.2:
|
||||||
|
resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/morgan@1.9.6:
|
/@types/morgan@1.9.6:
|
||||||
resolution: {integrity: sha512-xfKogz5WcKww2DAiVT9zxMgrqQt+Shq8tDVeLT+otoj6dJnkRkyJxMF51mHtUc3JCPKGk5x1EBU0buuGpfftlQ==}
|
resolution: {integrity: sha512-xfKogz5WcKww2DAiVT9zxMgrqQt+Shq8tDVeLT+otoj6dJnkRkyJxMF51mHtUc3JCPKGk5x1EBU0buuGpfftlQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -1525,7 +1542,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@npmcli/fs': 3.1.0
|
'@npmcli/fs': 3.1.0
|
||||||
fs-minipass: 3.0.3
|
fs-minipass: 3.0.3
|
||||||
glob: 10.3.4
|
glob: 10.3.10
|
||||||
lru-cache: 7.18.3
|
lru-cache: 7.18.3
|
||||||
minipass: 7.0.3
|
minipass: 7.0.3
|
||||||
minipass-collect: 1.0.2
|
minipass-collect: 1.0.2
|
||||||
@@ -2649,13 +2666,13 @@ packages:
|
|||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/glob@10.3.4:
|
/glob@10.3.10:
|
||||||
resolution: {integrity: sha512-6LFElP3A+i/Q8XQKEvZjkEWEOTgAIALR9AO2rwT8bgPhDd1anmqDJDZ6lLddI4ehxxxR1S5RIqKe1uapMQfYaQ==}
|
resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==}
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
foreground-child: 3.1.1
|
foreground-child: 3.1.1
|
||||||
jackspeak: 2.3.1
|
jackspeak: 2.3.6
|
||||||
minimatch: 9.0.3
|
minimatch: 9.0.3
|
||||||
minipass: 7.0.3
|
minipass: 7.0.3
|
||||||
path-scurry: 1.10.1
|
path-scurry: 1.10.1
|
||||||
@@ -3105,8 +3122,8 @@ packages:
|
|||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/jackspeak@2.3.1:
|
/jackspeak@2.3.6:
|
||||||
resolution: {integrity: sha512-4iSY3Bh1Htv+kLhiiZunUhQ+OYXIn0ze3ulq8JeWrFKmhPAJSySV2+kdtRh2pGcCeF0s6oR8Oc+pYZynJj4t8A==}
|
resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@isaacs/cliui': 8.0.2
|
'@isaacs/cliui': 8.0.2
|
||||||
@@ -5553,8 +5570,8 @@ packages:
|
|||||||
engines: {node: '>=12.20'}
|
engines: {node: '>=12.20'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
github.com/appwrite/appwrite/8a4302ffe6173e6b1256da5e7c86042d73983cdb:
|
github.com/appwrite/appwrite/030f9629a69f7db0f3da3e76d1805383bb3a3acd:
|
||||||
resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/8a4302ffe6173e6b1256da5e7c86042d73983cdb}
|
resolution: {tarball: https://codeload.github.com/appwrite/appwrite/tar.gz/030f9629a69f7db0f3da3e76d1805383bb3a3acd}
|
||||||
name: '@appwrite.io/repo'
|
name: '@appwrite.io/repo'
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|||||||
37
scripts/transform-images.js
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { existsSync } from 'fs';
|
||||||
|
import { globSync } from 'glob';
|
||||||
|
import path from 'path';
|
||||||
|
import sharp from 'sharp';
|
||||||
|
|
||||||
|
console.log('Transforming images...');
|
||||||
|
|
||||||
|
const inputFormats = ['png', 'jpg', 'svg'];
|
||||||
|
const outputFormats = ['png', 'jpg'];
|
||||||
|
const files = globSync(`./static/assets/**/*.{${inputFormats.join(',')}}`);
|
||||||
|
|
||||||
|
console.log('Found files:', files);
|
||||||
|
|
||||||
|
files.forEach((file) => {
|
||||||
|
const fileName = path.basename(file, path.extname(file));
|
||||||
|
const fileDir = path.dirname(file);
|
||||||
|
|
||||||
|
console.log('Transforming file:', file);
|
||||||
|
|
||||||
|
outputFormats.forEach((format) => {
|
||||||
|
const outputFile = path.join(fileDir, `${fileName}.${format}`);
|
||||||
|
|
||||||
|
if (!existsSync(outputFile)) {
|
||||||
|
sharp(file)
|
||||||
|
.toFormat(format)
|
||||||
|
.toFile(outputFile, (err) => {
|
||||||
|
if (err) {
|
||||||
|
console.error(`Error transforming file ${file} to ${format}:`, err);
|
||||||
|
} else {
|
||||||
|
console.log(`Transformed file ${file} to ${format}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log(`File ${outputFile} already exists. Skipping transformation.`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import { error } from '@sveltejs/kit';
|
|
||||||
import sharp from 'sharp';
|
|
||||||
|
|
||||||
const formats = ['webp', 'jpeg', 'png', 'tiff', 'avif'] as const;
|
|
||||||
|
|
||||||
const filenameMap: Record<ImageFormat, string> = {
|
|
||||||
webp: 'webp',
|
|
||||||
jpeg: 'jpg',
|
|
||||||
png: 'png',
|
|
||||||
tiff: 'tiff',
|
|
||||||
avif: 'avif'
|
|
||||||
};
|
|
||||||
|
|
||||||
const getFilename = (imgUrl: string, format: ImageFormat) => {
|
|
||||||
const filename = imgUrl.split('/').pop() ?? '';
|
|
||||||
const ext = filename.split('.').pop() ?? '';
|
|
||||||
if (ext === filenameMap[format]) return filename;
|
|
||||||
return filename.replace(ext, filenameMap[format]);
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ImageFormat = (typeof formats)[number];
|
|
||||||
|
|
||||||
const isFormat = (format: unknown): format is ImageFormat => {
|
|
||||||
return typeof format === 'string' && formats.includes(format as ImageFormat);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const GET = async ({ fetch, url }) => {
|
|
||||||
const img = url.searchParams.get('img');
|
|
||||||
const format = url.searchParams.get('format') || 'webp';
|
|
||||||
if (!img) throw error(400, 'Missing image parameter');
|
|
||||||
if (!isFormat(format)) throw error(400, 'Invalid format parameter');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const fetchedImg = await fetch(img);
|
|
||||||
const imgBuffer = await fetchedImg.arrayBuffer();
|
|
||||||
return new Response(await sharp(imgBuffer).toFormat(format).toBuffer(), {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': `image/${format}`,
|
|
||||||
'Content-Disposition': `attachment; filename="${getFilename(img, format)}"`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
throw error(400, 'Invalid image URL');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
import { visible } from '$lib/actions';
|
import { visible } from '$lib/actions';
|
||||||
import { Main } from '$lib/layouts';
|
import { Main } from '$lib/layouts';
|
||||||
import { copy } from '$lib/utils/copy';
|
import { copy } from '$lib/utils/copy';
|
||||||
import { getImageUrl } from '$lib/utils/image';
|
|
||||||
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
|
import { DEFAULT_DESCRIPTION, DEFAULT_HOST } from '$lib/utils/metadata';
|
||||||
import { TITLE_SUFFIX } from '$routes/titles';
|
import { TITLE_SUFFIX } from '$routes/titles';
|
||||||
import FooterNav from '../../lib/components/FooterNav.svelte';
|
import FooterNav from '../../lib/components/FooterNav.svelte';
|
||||||
@@ -178,7 +178,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl('/assets/logotype/white.svg', 'png')}
|
href="/assets/logotype/white.png"
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
@@ -206,7 +206,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl('/assets/logotype/black.svg', 'png')}
|
href="/assets/logotype/black.png"
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
@@ -275,7 +275,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl('/assets/logomark/logo.svg', 'png')}
|
href="/assets/logomark/logo.png"
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
@@ -303,7 +303,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl('/assets/logomark/logo.svg', 'png')}
|
href="/assets/logomark/logo.png"
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
@@ -429,14 +429,11 @@
|
|||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl(
|
href="/assets/visuals/dashboard.jpg"
|
||||||
'/assets/visuals/dashboard.png',
|
|
||||||
'jpeg'
|
|
||||||
)}
|
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
<span>JPEG</span>
|
<span>JPG</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
@@ -457,11 +454,11 @@
|
|||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl('/assets/visuals/auth.png', 'jpeg')}
|
href="/assets/visuals/auth.jpg"
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
<span>JPEG</span>
|
<span>JPG</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
@@ -482,14 +479,11 @@
|
|||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl(
|
href="/assets/visuals/databases.jpg"
|
||||||
'/assets/visuals/databases.png',
|
|
||||||
'jpeg'
|
|
||||||
)}
|
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
<span>JPEG</span>
|
<span>JPG</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
@@ -511,14 +505,11 @@
|
|||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl(
|
href="/assets/visuals/storage.jpg"
|
||||||
'/assets/visuals/storage.png',
|
|
||||||
'jpeg'
|
|
||||||
)}
|
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
<span>JPEG</span>
|
<span>JPG</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
@@ -540,14 +531,11 @@
|
|||||||
<div class="buttons">
|
<div class="buttons">
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
href={getImageUrl(
|
href="/assets/visuals/functions.jpg"
|
||||||
'/assets/visuals/functions.png',
|
|
||||||
'jpeg'
|
|
||||||
)}
|
|
||||||
download
|
download
|
||||||
>
|
>
|
||||||
<span class="aw-icon-download" aria-label="download" />
|
<span class="aw-icon-download" aria-label="download" />
|
||||||
<span>JPEG</span>
|
<span>JPG</span>
|
||||||
</a>
|
</a>
|
||||||
<a
|
<a
|
||||||
class="aw-button is-secondary"
|
class="aw-button is-secondary"
|
||||||
|
|||||||
BIN
static/assets/logomark/co-brand.jpg
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
static/assets/logomark/co-brand.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
BIN
static/assets/logomark/logo.jpg
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
static/assets/logomark/logo.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
static/assets/logotype/black.jpg
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
static/assets/logotype/black.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
static/assets/logotype/co-brand.jpg
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
static/assets/logotype/co-brand.png
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
static/assets/logotype/white.jpg
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
static/assets/logotype/white.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
static/assets/visuals/auth.jpg
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
static/assets/visuals/dashboard.jpg
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
static/assets/visuals/databases.jpg
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
static/assets/visuals/functions.jpg
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
static/assets/visuals/storage.jpg
Normal file
|
After Width: | Height: | Size: 75 KiB |