@phosart/common 0.4.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -0
- package/dist/FullGallery.svelte +51 -0
- package/dist/FullGallery.svelte.d.ts +17 -0
- package/dist/FullGallery.svelte.d.ts.map +1 -0
- package/dist/Gallery.svelte +30 -0
- package/dist/Gallery.svelte.d.ts +14 -0
- package/dist/Gallery.svelte.d.ts.map +1 -0
- package/dist/GalleryPreview.svelte +60 -0
- package/dist/GalleryPreview.svelte.d.ts +9 -0
- package/dist/GalleryPreview.svelte.d.ts.map +1 -0
- package/dist/HighResContext.svelte +21 -0
- package/dist/HighResContext.svelte.d.ts +8 -0
- package/dist/HighResContext.svelte.d.ts.map +1 -0
- package/dist/Image.svelte +171 -0
- package/dist/Image.svelte.d.ts +14 -0
- package/dist/Image.svelte.d.ts.map +1 -0
- package/dist/Modal.svelte +87 -0
- package/dist/Modal.svelte.d.ts +9 -0
- package/dist/Modal.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/Carousel.svelte +76 -0
- package/dist/ModalGallery/Carousel.svelte.d.ts +10 -0
- package/dist/ModalGallery/Carousel.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/ImageSection.svelte +156 -0
- package/dist/ModalGallery/ImageSection.svelte.d.ts +11 -0
- package/dist/ModalGallery/ImageSection.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/ImageView.svelte +92 -0
- package/dist/ModalGallery/ImageView.svelte.d.ts +9 -0
- package/dist/ModalGallery/ImageView.svelte.d.ts.map +1 -0
- package/dist/ModalGallery/Spinner.svelte +71 -0
- package/dist/ModalGallery/Spinner.svelte.d.ts +7 -0
- package/dist/ModalGallery/Spinner.svelte.d.ts.map +1 -0
- package/dist/ModalGallery.svelte +165 -0
- package/dist/ModalGallery.svelte.d.ts +16 -0
- package/dist/ModalGallery.svelte.d.ts.map +1 -0
- package/dist/OpengraphMeta.svelte +125 -0
- package/dist/OpengraphMeta.svelte.d.ts +15 -0
- package/dist/OpengraphMeta.svelte.d.ts.map +1 -0
- package/dist/Postcard/ArtistLink.svelte +46 -0
- package/dist/Postcard/ArtistLink.svelte.d.ts +9 -0
- package/dist/Postcard/ArtistLink.svelte.d.ts.map +1 -0
- package/dist/Postcard/Chip.svelte +100 -0
- package/dist/Postcard/Chip.svelte.d.ts +12 -0
- package/dist/Postcard/Chip.svelte.d.ts.map +1 -0
- package/dist/Postcard/Description/Character.svelte +79 -0
- package/dist/Postcard/Description/Character.svelte.d.ts +9 -0
- package/dist/Postcard/Description/Character.svelte.d.ts.map +1 -0
- package/dist/Postcard/Description.svelte +146 -0
- package/dist/Postcard/Description.svelte.d.ts +13 -0
- package/dist/Postcard/Description.svelte.d.ts.map +1 -0
- package/dist/Postcard/Headline.svelte +70 -0
- package/dist/Postcard/Headline.svelte.d.ts +10 -0
- package/dist/Postcard/Headline.svelte.d.ts.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +17 -0
- package/dist/server/artist.d.ts +7 -0
- package/dist/server/artist.d.ts.map +1 -0
- package/dist/server/artist.js +40 -0
- package/dist/server/character.d.ts +9 -0
- package/dist/server/character.d.ts.map +1 -0
- package/dist/server/character.js +76 -0
- package/dist/server/directories.d.ts +4 -0
- package/dist/server/directories.d.ts.map +1 -0
- package/dist/server/directories.js +39 -0
- package/dist/server/fastcache.d.ts +11 -0
- package/dist/server/fastcache.d.ts.map +1 -0
- package/dist/server/fastcache.js +43 -0
- package/dist/server/filter.d.ts +6 -0
- package/dist/server/filter.d.ts.map +1 -0
- package/dist/server/filter.js +53 -0
- package/dist/server/gallery.d.ts +16 -0
- package/dist/server/gallery.d.ts.map +1 -0
- package/dist/server/gallery.js +162 -0
- package/dist/server/imageprocess.d.ts +18 -0
- package/dist/server/imageprocess.d.ts.map +1 -0
- package/dist/server/imageprocess.js +243 -0
- package/dist/server/index.d.ts +15 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +15 -0
- package/dist/server/models/Artist.d.ts +7 -0
- package/dist/server/models/Artist.d.ts.map +1 -0
- package/dist/server/models/Artist.js +15 -0
- package/dist/server/models/Character.d.ts +108 -0
- package/dist/server/models/Character.d.ts.map +1 -0
- package/dist/server/models/Character.js +21 -0
- package/dist/server/models/Gallery.d.ts +373 -0
- package/dist/server/models/Gallery.d.ts.map +1 -0
- package/dist/server/models/Gallery.js +60 -0
- package/dist/server/models/image.d.ts +64 -0
- package/dist/server/models/image.d.ts.map +1 -0
- package/dist/server/models/image.js +17 -0
- package/dist/server/pack.d.ts +3 -0
- package/dist/server/pack.d.ts.map +1 -0
- package/dist/server/pack.js +26 -0
- package/dist/server/theme/schema.d.ts +57 -0
- package/dist/server/theme/schema.d.ts.map +1 -0
- package/dist/server/theme/schema.js +217 -0
- package/dist/server/util.d.ts +24 -0
- package/dist/server/util.d.ts.map +1 -0
- package/dist/server/util.js +71 -0
- package/dist/util/art.d.ts +52 -0
- package/dist/util/art.d.ts.map +1 -0
- package/dist/util/art.js +57 -0
- package/dist/util/artistcontext.svelte.d.ts +8 -0
- package/dist/util/artistcontext.svelte.d.ts.map +1 -0
- package/dist/util/artistcontext.svelte.js +18 -0
- package/dist/util/charactercontext.svelte.d.ts +4 -0
- package/dist/util/charactercontext.svelte.d.ts.map +1 -0
- package/dist/util/charactercontext.svelte.js +11 -0
- package/dist/util/date.d.ts +2 -0
- package/dist/util/date.d.ts.map +1 -0
- package/dist/util/date.js +6 -0
- package/dist/util/index.d.ts +13 -0
- package/dist/util/index.d.ts.map +1 -0
- package/dist/util/index.js +10 -0
- package/dist/util/markdown.d.ts +2 -0
- package/dist/util/markdown.d.ts.map +1 -0
- package/dist/util/markdown.js +16 -0
- package/dist/util/phosart_config.svelte.d.ts +44 -0
- package/dist/util/phosart_config.svelte.d.ts.map +1 -0
- package/dist/util/phosart_config.svelte.js +51 -0
- package/dist/util/search.d.ts +3 -0
- package/dist/util/search.d.ts.map +1 -0
- package/dist/util/search.js +24 -0
- package/dist/util/smoothscroll.d.ts +4 -0
- package/dist/util/smoothscroll.d.ts.map +1 -0
- package/dist/util/smoothscroll.js +21 -0
- package/dist/util/tree.d.ts +19 -0
- package/dist/util/tree.d.ts.map +1 -0
- package/dist/util/tree.js +58 -0
- package/dist/util/util.d.ts +4 -0
- package/dist/util/util.d.ts.map +1 -0
- package/dist/util/util.js +22 -0
- package/package.json +102 -0
- package/src/lib/FullGallery.svelte +51 -0
- package/src/lib/Gallery.svelte +30 -0
- package/src/lib/GalleryPreview.svelte +60 -0
- package/src/lib/HighResContext.svelte +21 -0
- package/src/lib/Image.svelte +171 -0
- package/src/lib/Modal.svelte +87 -0
- package/src/lib/ModalGallery/Carousel.svelte +76 -0
- package/src/lib/ModalGallery/ImageSection.svelte +156 -0
- package/src/lib/ModalGallery/ImageView.svelte +92 -0
- package/src/lib/ModalGallery/Spinner.svelte +71 -0
- package/src/lib/ModalGallery.svelte +165 -0
- package/src/lib/OpengraphMeta.svelte +125 -0
- package/src/lib/Postcard/ArtistLink.svelte +46 -0
- package/src/lib/Postcard/Chip.svelte +100 -0
- package/src/lib/Postcard/Description/Character.svelte +79 -0
- package/src/lib/Postcard/Description.svelte +146 -0
- package/src/lib/Postcard/Headline.svelte +70 -0
- package/src/lib/index.ts +20 -0
- package/src/lib/server/artist.ts +50 -0
- package/src/lib/server/character.ts +113 -0
- package/src/lib/server/directories.ts +45 -0
- package/src/lib/server/fastcache.ts +66 -0
- package/src/lib/server/filter.ts +71 -0
- package/src/lib/server/gallery.ts +259 -0
- package/src/lib/server/imageprocess.ts +382 -0
- package/src/lib/server/index.ts +57 -0
- package/src/lib/server/models/Artist.ts +19 -0
- package/src/lib/server/models/Character.ts +24 -0
- package/src/lib/server/models/Gallery.ts +70 -0
- package/src/lib/server/models/image.ts +20 -0
- package/src/lib/server/pack.ts +31 -0
- package/src/lib/server/theme/schema.ts +286 -0
- package/src/lib/server/util.ts +102 -0
- package/src/lib/util/art.ts +136 -0
- package/src/lib/util/artistcontext.svelte.ts +25 -0
- package/src/lib/util/charactercontext.svelte.ts +15 -0
- package/src/lib/util/date.ts +7 -0
- package/src/lib/util/index.ts +29 -0
- package/src/lib/util/markdown.ts +17 -0
- package/src/lib/util/phosart_config.svelte.ts +101 -0
- package/src/lib/util/search.ts +28 -0
- package/src/lib/util/smoothscroll.ts +21 -0
- package/src/lib/util/tree.ts +75 -0
- package/src/lib/util/util.ts +37 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { $DATA } from "./directories.js";
|
|
2
|
+
import * as fs from 'node:fs/promises';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import * as yaml from 'yaml';
|
|
5
|
+
import { FullCharacter, RawCharacter } from "./models/Character.js";
|
|
6
|
+
import { processImageFastcache } from "./imageprocess.js";
|
|
7
|
+
import { cacheVersion, getCache, fullPath, relPath } from "./util.js";
|
|
8
|
+
import { flushFastCache, readFastCache } from "./fastcache.js";
|
|
9
|
+
import { galleries } from "./gallery.js";
|
|
10
|
+
import { normalizeCharacter } from "../util/art.js";
|
|
11
|
+
const CHARACTER_PATH = path.join('characters', 'characters.yaml');
|
|
12
|
+
async function doResolveImage(filename, character, fc) {
|
|
13
|
+
const full = processImageFastcache(fc, fullPath(filename, character.picture.image), relPath(filename, character.picture.image));
|
|
14
|
+
const thumb = character.thumbnail
|
|
15
|
+
? processImageFastcache(fc, fullPath(filename, character.thumbnail.image), relPath(filename, character.thumbnail.image))
|
|
16
|
+
: undefined;
|
|
17
|
+
return {
|
|
18
|
+
...character,
|
|
19
|
+
picture: { ...(await full), alt: character.picture.alt },
|
|
20
|
+
thumbnail: thumb
|
|
21
|
+
? {
|
|
22
|
+
...(await thumb),
|
|
23
|
+
alt: character.thumbnail.alt
|
|
24
|
+
}
|
|
25
|
+
: undefined
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export async function rawCharacters() {
|
|
29
|
+
const cached = getCache().rawCharacterCache;
|
|
30
|
+
const nextVersion = await cacheVersion();
|
|
31
|
+
if (cached.cache && cached.version === nextVersion) {
|
|
32
|
+
return cached.cache;
|
|
33
|
+
}
|
|
34
|
+
const document = yaml.parse(await fs.readFile(path.join($DATA(), CHARACTER_PATH), { encoding: 'utf-8' }));
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
36
|
+
const characters = document
|
|
37
|
+
.flatMap((obj, idx) => {
|
|
38
|
+
const ch = RawCharacter.parse({ ...obj, index: idx++ });
|
|
39
|
+
return ch;
|
|
40
|
+
})
|
|
41
|
+
.reduce((acc, cur) => ({ ...acc, [cur.name]: cur }), {});
|
|
42
|
+
getCache().rawCharacterCache.cache = characters;
|
|
43
|
+
getCache().rawCharacterCache.version = nextVersion;
|
|
44
|
+
return characters;
|
|
45
|
+
}
|
|
46
|
+
export async function characters() {
|
|
47
|
+
const cached = getCache().characterCache;
|
|
48
|
+
const nextVersion = await cacheVersion();
|
|
49
|
+
if (cached.cache && cached.version === nextVersion) {
|
|
50
|
+
return cached.cache;
|
|
51
|
+
}
|
|
52
|
+
const characters = await rawCharacters();
|
|
53
|
+
const fc = await readFastCache();
|
|
54
|
+
const resolved = Object.fromEntries(await Promise.all(Object.entries(characters).map(async ([k, v]) => {
|
|
55
|
+
const resolved = await doResolveImage(CHARACTER_PATH, v, fc);
|
|
56
|
+
return [k, resolved];
|
|
57
|
+
})));
|
|
58
|
+
await flushFastCache(fc);
|
|
59
|
+
getCache().characterCache.cache = resolved;
|
|
60
|
+
getCache().characterCache.version = nextVersion;
|
|
61
|
+
return resolved;
|
|
62
|
+
}
|
|
63
|
+
export async function getAllCharacters() {
|
|
64
|
+
const all = await characters();
|
|
65
|
+
const mapped = Object.values(await galleries())
|
|
66
|
+
.flatMap((g) => g.pieces)
|
|
67
|
+
.flatMap((p) => p.characters)
|
|
68
|
+
.flatMap((ch) => normalizeCharacter(ch, all))
|
|
69
|
+
.concat(Object.values(all).map((ch) => normalizeCharacter(ch.name, all)));
|
|
70
|
+
// Collapse by name, from pair
|
|
71
|
+
const record = {};
|
|
72
|
+
for (const m of mapped) {
|
|
73
|
+
record[`${m.name}\x00${m.from}`] = m;
|
|
74
|
+
}
|
|
75
|
+
return Object.values(record);
|
|
76
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"directories.d.ts","sourceRoot":"","sources":["../../src/lib/server/directories.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,KAAK,cAAgC,CAAC;AACnD,eAAO,MAAM,KAAK,cAA8B,CAAC;AACjD,eAAO,MAAM,OAAO,cAA2C,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { join, dirname } from 'node:path';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
function tryFindRoot(start) {
|
|
4
|
+
let cur = dirname(start);
|
|
5
|
+
while (cur.length > 1) {
|
|
6
|
+
if (cur.includes('node_modules')) {
|
|
7
|
+
cur = join(cur, '..');
|
|
8
|
+
continue;
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
// If package.json parses correctly...
|
|
12
|
+
JSON.parse(fs.readFileSync(join(cur, 'package.json'), { encoding: 'utf-8' }));
|
|
13
|
+
return cur;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
cur = join(cur, '..');
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
let cachedRoot = null;
|
|
22
|
+
function findRoot() {
|
|
23
|
+
if (cachedRoot) {
|
|
24
|
+
return cachedRoot;
|
|
25
|
+
}
|
|
26
|
+
let root = null;
|
|
27
|
+
if (process.env.PROJECT_ROOT) {
|
|
28
|
+
root = tryFindRoot(process.env.PROJECT_ROOT);
|
|
29
|
+
}
|
|
30
|
+
root = root ?? tryFindRoot(process.argv[1]) ?? tryFindRoot(process.cwd());
|
|
31
|
+
if (!root) {
|
|
32
|
+
throw new Error('Failed to find root');
|
|
33
|
+
}
|
|
34
|
+
cachedRoot = root;
|
|
35
|
+
return root;
|
|
36
|
+
}
|
|
37
|
+
export const $ROOT = () => join(findRoot(), 'src');
|
|
38
|
+
export const $DATA = () => join($ROOT(), 'data');
|
|
39
|
+
export const $PUBLIC = () => join($ROOT(), '..', 'static', '_');
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface FastCache {
|
|
2
|
+
[relpath: string]: {
|
|
3
|
+
mtime: number;
|
|
4
|
+
hash: string;
|
|
5
|
+
};
|
|
6
|
+
}
|
|
7
|
+
export declare function getFastHash(fc: FastCache, fullpath: string, relpath: string): Promise<[string | null, number | null]>;
|
|
8
|
+
export declare function updateFastCache(fc: FastCache, fullpath: string, relpath: string, hash: string, premtime?: number | null): Promise<void>;
|
|
9
|
+
export declare function flushFastCache(fc: FastCache): Promise<void>;
|
|
10
|
+
export declare function readFastCache(): Promise<FastCache>;
|
|
11
|
+
//# sourceMappingURL=fastcache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fastcache.d.ts","sourceRoot":"","sources":["../../src/lib/server/fastcache.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,SAAS;IACzB,CAAC,OAAO,EAAE,MAAM,GAAG;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;KACb,CAAC;CACF;AAED,wBAAsB,WAAW,CAChC,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GACb,OAAO,CAAC,CAAC,MAAM,GAAG,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAYzC;AAED,wBAAsB,eAAe,CACpC,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,iBAQxB;AAED,wBAAsB,cAAc,CAAC,EAAE,EAAE,SAAS,iBAMjD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,SAAS,CAAC,CAOxD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { stat } from 'node:fs/promises';
|
|
2
|
+
import { $DATA } from "./directories.js";
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { Logger } from 'tslog';
|
|
5
|
+
import { getLogLevel } from "./util.js";
|
|
6
|
+
import { readPack, writePack } from "./pack.js";
|
|
7
|
+
const FastcacheLogger = new Logger({ minLevel: getLogLevel() });
|
|
8
|
+
const $FASTCACHEPATH = () => path.join($DATA(), '.fastcache.pack.gz');
|
|
9
|
+
export async function getFastHash(fc, fullpath, relpath) {
|
|
10
|
+
const cacheinfo = fc[relpath];
|
|
11
|
+
if (!cacheinfo)
|
|
12
|
+
return [null, null];
|
|
13
|
+
const fstat = await stat(fullpath);
|
|
14
|
+
const mtime = fstat.mtimeMs;
|
|
15
|
+
if (mtime !== cacheinfo.mtime) {
|
|
16
|
+
return [null, mtime];
|
|
17
|
+
}
|
|
18
|
+
return [cacheinfo.hash, mtime];
|
|
19
|
+
}
|
|
20
|
+
export async function updateFastCache(fc, fullpath, relpath, hash, premtime) {
|
|
21
|
+
const mtime = premtime ?? (await stat(fullpath)).mtimeMs;
|
|
22
|
+
fc[relpath] = {
|
|
23
|
+
mtime,
|
|
24
|
+
hash
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export async function flushFastCache(fc) {
|
|
28
|
+
try {
|
|
29
|
+
await writePack($FASTCACHEPATH(), fc);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
FastcacheLogger.warn('Failed to write fastcache', err);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export async function readFastCache() {
|
|
36
|
+
try {
|
|
37
|
+
return await readPack($FASTCACHEPATH());
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
FastcacheLogger.warn('Failed to read fastcache', err);
|
|
41
|
+
return {};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ArtPiece, type ResourceRef } from '../util/art.ts';
|
|
2
|
+
export declare function filter(gallery: ArtPiece[] | Record<string, ArtPiece>, by?: ResourceRef, { negated, sorted }?: {
|
|
3
|
+
negated?: boolean;
|
|
4
|
+
sorted?: boolean;
|
|
5
|
+
}): ArtPiece[];
|
|
6
|
+
//# sourceMappingURL=filter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../src/lib/server/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAGN,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,MAAM,gBAAgB,CAAC;AAgDxB,wBAAgB,MAAM,CACrB,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAC9C,EAAE,CAAC,EAAE,WAAW,EAChB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAO,GAC/D,QAAQ,EAAE,CAaZ"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { normalizeArtist, normalizeCharacter } from "../util/art.js";
|
|
2
|
+
function filterOne(piece, by, negated) {
|
|
3
|
+
if (!by.type || !by.resource) {
|
|
4
|
+
return false;
|
|
5
|
+
}
|
|
6
|
+
switch (by.type) {
|
|
7
|
+
case 'artist': {
|
|
8
|
+
const artists = normalizeArtist(piece.artist);
|
|
9
|
+
let hasArtist = artists.some((artist) => artist.name.toLowerCase() === by.resource.name.toLowerCase());
|
|
10
|
+
if (negated) {
|
|
11
|
+
hasArtist = !hasArtist;
|
|
12
|
+
}
|
|
13
|
+
return hasArtist;
|
|
14
|
+
}
|
|
15
|
+
case 'character': {
|
|
16
|
+
const characters = normalizeCharacter(piece.characters);
|
|
17
|
+
let hasCharacter = characters.some((ch) => ch.name.toLowerCase() === by.resource.name.toLowerCase() &&
|
|
18
|
+
(ch.from?.toLowerCase() === by.resource.from?.toLowerCase() ||
|
|
19
|
+
(!ch.from && !by.resource.from)));
|
|
20
|
+
if (negated) {
|
|
21
|
+
hasCharacter = !hasCharacter;
|
|
22
|
+
}
|
|
23
|
+
return hasCharacter;
|
|
24
|
+
}
|
|
25
|
+
case 'piece': {
|
|
26
|
+
let isPiece = by.resource.slug === piece.slug;
|
|
27
|
+
if (negated) {
|
|
28
|
+
isPiece = !isPiece;
|
|
29
|
+
}
|
|
30
|
+
return isPiece;
|
|
31
|
+
}
|
|
32
|
+
case 'tag': {
|
|
33
|
+
let hasTag = piece.tags.map((t) => t.toLowerCase()).includes(by.resource.toLowerCase());
|
|
34
|
+
if (negated) {
|
|
35
|
+
hasTag = !hasTag;
|
|
36
|
+
}
|
|
37
|
+
return hasTag;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export function filter(gallery, by, { negated, sorted } = {}) {
|
|
42
|
+
if (!Array.isArray(gallery))
|
|
43
|
+
gallery = Object.values(gallery);
|
|
44
|
+
const results = by
|
|
45
|
+
? gallery.filter((piece) => {
|
|
46
|
+
return filterOne(piece, by, negated ?? false);
|
|
47
|
+
})
|
|
48
|
+
: gallery;
|
|
49
|
+
if (!sorted) {
|
|
50
|
+
return results;
|
|
51
|
+
}
|
|
52
|
+
return results.sort((a, b) => b.date.getTime() - a.date.getTime());
|
|
53
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { FullGallery, RawGallery } from './models/Gallery.ts';
|
|
3
|
+
import type { ArtPiece } from '../util/art.ts';
|
|
4
|
+
type FileName = string;
|
|
5
|
+
type RawGalleryT = z.infer<typeof RawGallery>;
|
|
6
|
+
type FullGalleryT = z.infer<typeof FullGallery>;
|
|
7
|
+
type GalleryListing<T> = Record<FileName, T>;
|
|
8
|
+
export type GalleryCache = GalleryListing<FullGalleryT>;
|
|
9
|
+
export type RawGalleryCache = GalleryListing<RawGalleryT>;
|
|
10
|
+
export declare function rawGalleries(): Promise<RawGalleryCache>;
|
|
11
|
+
export declare function galleries(doRetry?: boolean): Promise<GalleryCache>;
|
|
12
|
+
export declare function allPieces(): Promise<Record<string, ArtPiece>>;
|
|
13
|
+
export declare function getPieceBySlug(slug: string): Promise<ArtPiece | null>;
|
|
14
|
+
export declare function hasNsfw(gallery: ArtPiece[]): boolean;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=gallery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gallery.d.ts","sourceRoot":"","sources":["../../src/lib/server/gallery.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAIN,WAAW,EACX,UAAU,EACV,MAAM,qBAAqB,CAAC;AAa7B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAI/C,KAAK,QAAQ,GAAG,MAAM,CAAC;AAEvB,KAAK,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAC9C,KAAK,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC;AAChD,KAAK,cAAc,CAAC,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;AACxD,MAAM,MAAM,eAAe,GAAG,cAAc,CAAC,WAAW,CAAC,CAAC;AAmH1D,wBAAsB,YAAY,IAAI,OAAO,CAAC,eAAe,CAAC,CAgC7D;AAED,wBAAsB,SAAS,CAAC,OAAO,GAAE,OAAc,yBAsDtD;AAMD,wBAAsB,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAKnE;AAED,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAE3E;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,GAAG,OAAO,CAEpD"}
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import * as yaml from 'yaml';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
import { Logger } from 'tslog';
|
|
7
|
+
import { BaseArtPiece, BaseGallery, FullArtPiece, FullGallery, RawGallery } from "./models/Gallery.js";
|
|
8
|
+
import { $DATA } from "./directories.js";
|
|
9
|
+
import { processImageFastcache, processVideoFastcache } from "./imageprocess.js";
|
|
10
|
+
import { cacheVersion, clearCache, getCache, hash, fullPath, relPath, getLogLevel } from "./util.js";
|
|
11
|
+
import { flushFastCache, readFastCache } from "./fastcache.js";
|
|
12
|
+
import { asRecord } from "../util/util.js";
|
|
13
|
+
const GalleryLogger = new Logger({ minLevel: getLogLevel() });
|
|
14
|
+
async function resolveExtendsRec(fname, gallery, rec, fc) {
|
|
15
|
+
if (!('$extends' in gallery)) {
|
|
16
|
+
return await resolveReferences(gallery, fname, fc);
|
|
17
|
+
}
|
|
18
|
+
const full = { pieces: [] };
|
|
19
|
+
for (const relative of gallery.$extends) {
|
|
20
|
+
const base = path.dirname(fname);
|
|
21
|
+
const target = path.join(base, relative);
|
|
22
|
+
if (rec[target]) {
|
|
23
|
+
const result = await resolveExtendsRec(target, rec[target], rec, fc);
|
|
24
|
+
if ('$extends' in result) {
|
|
25
|
+
throw new Error('Impossible');
|
|
26
|
+
}
|
|
27
|
+
full.pieces.push(...result.pieces);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
GalleryLogger.warn('[GALLERY] Could not find target for', target, 'when parsing', fname);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return full;
|
|
34
|
+
}
|
|
35
|
+
async function resolveExtends(rec, fc) {
|
|
36
|
+
const listing = {};
|
|
37
|
+
for (const [fname, gallery] of Object.entries(rec)) {
|
|
38
|
+
if ('$extends' in gallery) {
|
|
39
|
+
listing[fname] = await resolveExtendsRec(fname, gallery, rec, fc);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
listing[fname] = await resolveReferences(gallery, fname, fc);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return listing;
|
|
46
|
+
}
|
|
47
|
+
async function resolvePieceReferences(piece, filename, fc) {
|
|
48
|
+
const relpath = relPath(filename, piece.image);
|
|
49
|
+
const fullpath = fullPath(filename, piece.image);
|
|
50
|
+
const image = await processImageFastcache(fc, fullpath, relpath, { position: piece.position });
|
|
51
|
+
const alts = await Promise.all(piece.alts?.map(async (alt) => ({
|
|
52
|
+
...alt,
|
|
53
|
+
image: await processImageFastcache(fc, fullPath(filename, alt.image), relPath(filename, alt.image), { position: piece.position }),
|
|
54
|
+
video: alt.video
|
|
55
|
+
? {
|
|
56
|
+
full: await processVideoFastcache(fc, fullPath(filename, alt.video.full), relPath(filename, alt.video.full), 'full'),
|
|
57
|
+
thumb: await processVideoFastcache(fc, fullPath(filename, alt.video.thumb), relPath(filename, alt.video.thumb), 'thumb')
|
|
58
|
+
}
|
|
59
|
+
: undefined
|
|
60
|
+
})) ?? []);
|
|
61
|
+
const video = piece.video
|
|
62
|
+
? {
|
|
63
|
+
full: await processVideoFastcache(fc, fullPath(filename, piece.video.full), relPath(filename, piece.video.full), 'full'),
|
|
64
|
+
thumb: await processVideoFastcache(fc, fullPath(filename, piece.video.thumb), relPath(filename, piece.video.thumb), 'thumb')
|
|
65
|
+
}
|
|
66
|
+
: undefined;
|
|
67
|
+
return { ...piece, image, alts, video };
|
|
68
|
+
}
|
|
69
|
+
async function resolveReferences(gallery, fname, fc) {
|
|
70
|
+
return {
|
|
71
|
+
pieces: await Promise.all(gallery.pieces.map((piece) => resolvePieceReferences(piece, fname, fc)))
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export async function rawGalleries() {
|
|
75
|
+
const cached = getCache().rawGalleryCache;
|
|
76
|
+
const nextVersion = await cacheVersion();
|
|
77
|
+
if (cached.cache && cached.version === nextVersion) {
|
|
78
|
+
return cached.cache;
|
|
79
|
+
}
|
|
80
|
+
const allGalleries = await glob('./**/*.gallery', { cwd: $DATA() });
|
|
81
|
+
const documents = (await Promise.all(allGalleries.map((fn) => fs
|
|
82
|
+
.readFile(path.join($DATA(), fn), { encoding: 'utf-8' })
|
|
83
|
+
.then((text) => ({ filename: fn, text })))))
|
|
84
|
+
.map(({ filename, text }) => ({ filename, obj: yaml.parse(text) }))
|
|
85
|
+
.map(({ filename, obj }) => {
|
|
86
|
+
GalleryLogger.silly('[GALLERY] Parsing', filename);
|
|
87
|
+
obj.pieces = obj.pieces
|
|
88
|
+
? obj.pieces.map((p) => ({ ...p, slug: p.id ?? hash(p) }))
|
|
89
|
+
: undefined;
|
|
90
|
+
return { filename, obj: RawGallery.parse(obj) };
|
|
91
|
+
})
|
|
92
|
+
.reduce((rec, { filename, obj }) => ({ ...rec, [filename.replaceAll(path.sep, '/')]: obj }), {});
|
|
93
|
+
getCache().rawGalleryCache.cache = documents;
|
|
94
|
+
getCache().rawGalleryCache.version = nextVersion;
|
|
95
|
+
return documents;
|
|
96
|
+
}
|
|
97
|
+
export async function galleries(doRetry = true) {
|
|
98
|
+
const cached = getCache().galleryCache;
|
|
99
|
+
const nextVersion = await cacheVersion();
|
|
100
|
+
if (cached.cache && cached.version === nextVersion) {
|
|
101
|
+
return cached.cache;
|
|
102
|
+
}
|
|
103
|
+
const documents = Object.fromEntries(Object.entries(await rawGalleries())
|
|
104
|
+
.map(([path, g]) => {
|
|
105
|
+
if ('pieces' in g) {
|
|
106
|
+
g = {
|
|
107
|
+
pieces: g.pieces
|
|
108
|
+
.map((p) => {
|
|
109
|
+
if (p.deindexed) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
if (p.alts) {
|
|
113
|
+
p = { ...p, alts: p.alts.filter((a) => !a.deindexed) };
|
|
114
|
+
}
|
|
115
|
+
return p;
|
|
116
|
+
})
|
|
117
|
+
.filter(truthy)
|
|
118
|
+
};
|
|
119
|
+
if (g.pieces.length === 0) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
return [path, g];
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
if (g.$extends.length === 0) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
return [path, g];
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
.filter(truthy));
|
|
132
|
+
try {
|
|
133
|
+
const fc = await readFastCache();
|
|
134
|
+
const out = await resolveExtends(documents, fc);
|
|
135
|
+
await flushFastCache(fc);
|
|
136
|
+
getCache().galleryCache.cache = out;
|
|
137
|
+
getCache().galleryCache.version = nextVersion;
|
|
138
|
+
return out;
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
if (doRetry) {
|
|
142
|
+
GalleryLogger.warn('Encountered error, clearing cache and trying again', e);
|
|
143
|
+
clearCache();
|
|
144
|
+
return await galleries(/* doRetry = */ false);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
throw e;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function truthy(t) {
|
|
152
|
+
return !!t;
|
|
153
|
+
}
|
|
154
|
+
export async function allPieces() {
|
|
155
|
+
return asRecord(Object.values(await galleries()).flatMap((p) => p.pieces), (p) => p.slug);
|
|
156
|
+
}
|
|
157
|
+
export async function getPieceBySlug(slug) {
|
|
158
|
+
return (await allPieces())[slug] ?? null;
|
|
159
|
+
}
|
|
160
|
+
export function hasNsfw(gallery) {
|
|
161
|
+
return gallery.some((p) => p.nsfw);
|
|
162
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { Picture } from './models/image.ts';
|
|
3
|
+
import { type FastCache } from './fastcache.ts';
|
|
4
|
+
interface ProcessOptions {
|
|
5
|
+
forceKeep?: boolean;
|
|
6
|
+
position?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function getProcessedHashes(): ReadonlySet<string>;
|
|
9
|
+
export declare function clearProcessedHashes(): void;
|
|
10
|
+
export declare function getUnusedHashes(): Promise<ReadonlySet<string>>;
|
|
11
|
+
export declare function deleteHashes(unused: ReadonlySet<string>): Promise<void>;
|
|
12
|
+
export declare function cleanUnusedHashes(): Promise<void>;
|
|
13
|
+
export declare function processVideoFastcache(fc: FastCache, fullpath: string, relpath: string, name: string, processOptions?: ProcessOptions): Promise<string>;
|
|
14
|
+
export declare function processVideo(url: string, name: string): Promise<string>;
|
|
15
|
+
export declare function processImageFastcache(fc: FastCache, fullpath: string, relpath: string, processOptions?: ProcessOptions): Promise<z.infer<typeof Picture>>;
|
|
16
|
+
export declare function processImage(url: string, processOptions?: ProcessOptions): Promise<z.infer<typeof Picture>>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=imageprocess.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"imageprocess.d.ts","sourceRoot":"","sources":["../../src/lib/server/imageprocess.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AA0B9E,UAAU,cAAc;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAOD,wBAAgB,kBAAkB,IAAI,WAAW,CAAC,MAAM,CAAC,CAExD;AACD,wBAAgB,oBAAoB,SAEnC;AACD,wBAAsB,eAAe,IAAI,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAiBpE;AACD,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,iBAsB7D;AACD,wBAAsB,iBAAiB,kBAEtC;AAYD,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,cAAc,GAAE,cAAmB,GACjC,OAAO,CAAC,MAAM,CAAC,CAQjB;AAED,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAE7E;AAsBD,wBAAsB,qBAAqB,CAC1C,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,cAAmB,GACjC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC,CAQlC;AAED,wBAAsB,YAAY,CACjC,GAAG,EAAE,MAAM,EACX,cAAc,GAAE,cAAmB,GACjC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,OAAO,CAAC,CAAC,CAElC"}
|