├── .yarnrc.yml ├── gallery ├── src │ ├── lib │ │ ├── browser.ts │ │ └── index.ts │ ├── modules │ │ ├── clean │ │ │ ├── types │ │ │ │ └── index.ts │ │ │ └── index.ts │ │ ├── thumbnails │ │ │ ├── types │ │ │ │ └── index.ts │ │ │ └── utils │ │ │ │ └── index.ts │ │ ├── init │ │ │ ├── types │ │ │ │ ├── node-ffprobe.d.ts │ │ │ │ └── index.ts │ │ │ └── utils │ │ │ │ └── index.ts │ │ ├── telemetry │ │ │ ├── clients │ │ │ │ ├── console.ts │ │ │ │ └── api.ts │ │ │ ├── types │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── service │ │ │ │ └── index.ts │ │ └── build │ │ │ ├── types │ │ │ └── index.ts │ │ │ └── utils │ │ │ └── index.ts │ ├── types │ │ └── index.ts │ ├── config │ │ └── index.ts │ ├── utils │ │ ├── blurhash.ts │ │ ├── descriptions.ts │ │ ├── index.ts │ │ ├── gallery.ts │ │ ├── video.ts │ │ ├── image.ts │ │ └── version.ts │ └── index.ts ├── .prettierignore ├── tests │ ├── fixtures │ │ ├── multi │ │ │ ├── img_1.jpg │ │ │ ├── img_2.jpg │ │ │ ├── img_3.jpg │ │ │ ├── first │ │ │ │ ├── img_4.jpg │ │ │ │ └── img_5.jpg │ │ │ └── second │ │ │ │ ├── img_6.jpg │ │ │ │ └── img_7.jpg │ │ ├── single │ │ │ ├── img_1.jpg │ │ │ ├── img_2.jpg │ │ │ └── img_3.jpg │ │ └── images │ │ │ ├── test_image_xptitle.jpg │ │ │ ├── test_image_xpcomment.jpg │ │ │ ├── test_image_description.avif │ │ │ ├── test_image_description.jpg │ │ │ ├── test_image_description.png │ │ │ ├── test_image_description.tif │ │ │ ├── test_image_description.webp │ │ │ ├── test_image_user_comment.jpg │ │ │ ├── test_image_caption_abstract.jpg │ │ │ ├── test_image_image_description.jpg │ │ │ ├── test_image_extended_description.jpg │ │ │ ├── test_image_exif_orientation_horizontal.jpg │ │ │ └── test_image_exif_orientation_vertical.jpg │ ├── analytics.test.ts │ ├── images.test.ts │ └── thumbnails.test.ts ├── .prettierrc.mjs ├── tsconfig.json ├── tsup.config.ts ├── jest.config.cjs ├── package.json ├── eslint.config.mjs └── README.md ├── common ├── .prettierignore ├── tsconfig.json ├── tsup.config.ts ├── .prettierrc.mjs ├── package.json ├── eslint.config.mjs └── src │ └── gallery.ts ├── docs ├── images │ └── simple-photo-gallery-demo.jpg ├── README.md ├── commands │ ├── clean.md │ ├── README.md │ ├── thumbnails.md │ ├── build.md │ └── init.md ├── deployment.md └── embedding.md ├── themes └── modern │ ├── .vscode │ ├── extensions.json │ └── launch.json │ ├── src │ ├── pages │ │ └── index.astro │ ├── features │ │ └── themes │ │ │ └── base-theme │ │ │ ├── components │ │ │ ├── container │ │ │ │ └── Container.astro │ │ │ ├── footer │ │ │ │ └── Footer.astro │ │ │ ├── gallery-section │ │ │ │ ├── GallerySectionHeader.astro │ │ │ │ ├── GallerySection.astro │ │ │ │ └── GallerySectionItem.astro │ │ │ ├── hero │ │ │ │ ├── HeroScrollToGalleryBtn.astro │ │ │ │ └── Hero.astro │ │ │ ├── cta │ │ │ │ └── CtaBanner.astro │ │ │ ├── sub-galleries │ │ │ │ └── SubGalleries.astro │ │ │ └── lightbox │ │ │ │ └── PhotoSwipe.astro │ │ │ ├── utils │ │ │ ├── index.ts │ │ │ └── queryParams.ts │ │ │ ├── pages │ │ │ └── index.astro │ │ │ └── layouts │ │ │ ├── MainLayout.astro │ │ │ └── MainHead.astro │ └── lib │ │ └── markdown.ts │ ├── example │ ├── japan │ │ ├── ai-generated-nature-177.webp │ │ ├── ai-generated-nature-179.webp │ │ ├── ai-generated-nature-185.webp │ │ ├── ai-generated-nature-192.webp │ │ ├── ai-generated-nature-195.webp │ │ ├── ai-generated-nature-196.webp │ │ └── ai-generated-nature-199.webp │ └── usa │ │ ├── new-york │ │ ├── ai-generated-nature-147.webp │ │ ├── ai-generated-nature-148.webp │ │ ├── ai-generated-nature-156.webp │ │ ├── ai-generated-nature-159.webp │ │ ├── ai-generated-nature-177.webp │ │ ├── ai-generated-nature-179.webp │ │ ├── ai-generated-nature-185.webp │ │ ├── ai-generated-nature-192.webp │ │ ├── ai-generated-nature-195.webp │ │ ├── ai-generated-nature-196.webp │ │ └── ai-generated-nature-199.webp │ │ └── san-francisco │ │ ├── ai-generated-nature-160.webp │ │ ├── ai-generated-nature-167.webp │ │ ├── ai-generated-nature-170.webp │ │ ├── ai-generated-nature-172.webp │ │ ├── ai-generated-nature-177.webp │ │ ├── ai-generated-nature-179.webp │ │ ├── ai-generated-nature-185.webp │ │ ├── ai-generated-nature-192.webp │ │ ├── ai-generated-nature-195.webp │ │ ├── ai-generated-nature-196.webp │ │ ├── ai-generated-nature-199.webp │ │ └── twin-peaks │ │ ├── ai-generated-nature-167.webp │ │ ├── ai-generated-nature-170.webp │ │ ├── ai-generated-nature-172.webp │ │ ├── ai-generated-nature-177.webp │ │ ├── ai-generated-nature-179.webp │ │ ├── ai-generated-nature-185.webp │ │ └── ai-generated-nature-192.webp │ ├── .prettierignore │ ├── README.md │ ├── tsconfig.json │ ├── .prettierrc.mjs │ ├── package.json │ ├── astro.config.ts │ ├── gallery.json │ └── eslint.config.mjs ├── tsconfig.json ├── package.json ├── LICENSE ├── .github └── workflows │ └── check-cli.yml ├── .gitignore └── README.md /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | 3 | yarnPath: .yarn/releases/yarn-4.9.3.cjs 4 | -------------------------------------------------------------------------------- /gallery/src/lib/browser.ts: -------------------------------------------------------------------------------- 1 | export { getImageDescription } from '../utils/descriptions'; 2 | -------------------------------------------------------------------------------- /common/.prettierignore: -------------------------------------------------------------------------------- 1 | **/dist/* 2 | **/node_modules/* 3 | **/coverage/* 4 | **/temp/* 5 | **/dist/* 6 | -------------------------------------------------------------------------------- /gallery/.prettierignore: -------------------------------------------------------------------------------- 1 | **/dist/* 2 | **/node_modules/* 3 | **/coverage/* 4 | **/temp/* 5 | **/dist/* 6 | -------------------------------------------------------------------------------- /gallery/tests/fixtures/multi/img_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/multi/img_1.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/multi/img_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/multi/img_2.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/multi/img_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/multi/img_3.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/single/img_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/single/img_1.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/single/img_2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/single/img_2.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/single/img_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/single/img_3.jpg -------------------------------------------------------------------------------- /docs/images/simple-photo-gallery-demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/docs/images/simple-photo-gallery-demo.jpg -------------------------------------------------------------------------------- /themes/modern/.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["astro-build.astro-vscode"], 3 | "unwantedRecommendations": [] 4 | } 5 | -------------------------------------------------------------------------------- /gallery/tests/fixtures/multi/first/img_4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/multi/first/img_4.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/multi/first/img_5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/multi/first/img_5.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/multi/second/img_6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/multi/second/img_6.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/multi/second/img_7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/multi/second/img_7.jpg -------------------------------------------------------------------------------- /themes/modern/src/pages/index.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import BaseTheme from '@/features/themes/base-theme/pages/index.astro'; 3 | --- 4 | 5 | 6 | -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_xptitle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_xptitle.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_xpcomment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_xpcomment.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_description.avif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_description.avif -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_description.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_description.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_description.png -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_description.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_description.tif -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_description.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_description.webp -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_user_comment.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_user_comment.jpg -------------------------------------------------------------------------------- /themes/modern/example/japan/ai-generated-nature-177.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/japan/ai-generated-nature-177.webp -------------------------------------------------------------------------------- /themes/modern/example/japan/ai-generated-nature-179.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/japan/ai-generated-nature-179.webp -------------------------------------------------------------------------------- /themes/modern/example/japan/ai-generated-nature-185.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/japan/ai-generated-nature-185.webp -------------------------------------------------------------------------------- /themes/modern/example/japan/ai-generated-nature-192.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/japan/ai-generated-nature-192.webp -------------------------------------------------------------------------------- /themes/modern/example/japan/ai-generated-nature-195.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/japan/ai-generated-nature-195.webp -------------------------------------------------------------------------------- /themes/modern/example/japan/ai-generated-nature-196.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/japan/ai-generated-nature-196.webp -------------------------------------------------------------------------------- /themes/modern/example/japan/ai-generated-nature-199.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/japan/ai-generated-nature-199.webp -------------------------------------------------------------------------------- /common/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": true 5 | }, 6 | "include": ["src/**/*.ts", "tsup.config.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_caption_abstract.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_caption_abstract.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_image_description.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_image_description.jpg -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-147.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-147.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-148.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-148.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-156.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-156.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-159.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-159.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-177.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-177.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-179.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-179.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-185.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-185.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-192.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-192.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-195.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-195.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-196.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-196.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/new-york/ai-generated-nature-199.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/new-york/ai-generated-nature-199.webp -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_extended_description.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_extended_description.jpg -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-160.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-160.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-167.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-167.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-170.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-170.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-172.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-172.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-177.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-177.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-179.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-179.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-185.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-185.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-192.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-192.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-195.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-195.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-196.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-196.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/ai-generated-nature-199.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/ai-generated-nature-199.webp -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_exif_orientation_horizontal.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_exif_orientation_horizontal.jpg -------------------------------------------------------------------------------- /gallery/tests/fixtures/images/test_image_exif_orientation_vertical.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/gallery/tests/fixtures/images/test_image_exif_orientation_vertical.jpg -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-167.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-167.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-170.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-170.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-172.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-172.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-177.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-177.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-179.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-179.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-185.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-185.webp -------------------------------------------------------------------------------- /themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-192.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SimplePhotoGallery/core/HEAD/themes/modern/example/usa/san-francisco/twin-peaks/ai-generated-nature-192.webp -------------------------------------------------------------------------------- /themes/modern/.prettierignore: -------------------------------------------------------------------------------- 1 | **/temp/* 2 | **/dist/* 3 | **/node_modules/* 4 | **/coverage/* 5 | **/temp/* 6 | **/dist/* 7 | .next/* 8 | prisma/generated/* 9 | **/src/frontend/design-system/design-tokens/* 10 | .astro/* -------------------------------------------------------------------------------- /themes/modern/src/features/themes/base-theme/components/container/Container.astro: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 11 | -------------------------------------------------------------------------------- /themes/modern/README.md: -------------------------------------------------------------------------------- 1 | # Simple Photo Gallery - Modern Theme 2 | 3 | This is the modern theme for Simple Photo Gallery built with Astro. This theme provides a clean, responsive interface for displaying photo galleries. 4 | 5 | > Note: advanced theme support is coming soon. 6 | -------------------------------------------------------------------------------- /themes/modern/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "command": "./node_modules/.bin/astro dev", 6 | "name": "Development server", 7 | "request": "launch", 8 | "type": "node-terminal" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /gallery/src/modules/clean/types/index.ts: -------------------------------------------------------------------------------- 1 | /** Options for cleaning gallery files */ 2 | export interface CleanOptions { 3 | /** Path to the directory containing the gallery */ 4 | gallery: string; 5 | /** Whether to clean galleries in subdirectories recursively */ 6 | recursive: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "ESNext", 5 | "moduleResolution": "Bundler", 6 | "strict": true, 7 | "esModuleInterop": true, 8 | "resolveJsonModule": true, 9 | "skipLibCheck": true, 10 | "noEmit": true 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /gallery/src/modules/thumbnails/types/index.ts: -------------------------------------------------------------------------------- 1 | /** Options for generating thumbnails */ 2 | export interface ThumbnailOptions { 3 | /** Path to the directory containing the gallery */ 4 | gallery: string; 5 | /** Whether to process galleries in subdirectories recursively */ 6 | recursive: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@simple-photo-gallery/workspace", 3 | "version": "1.0.0", 4 | "private": true, 5 | "workspaces": { 6 | "packages": [ 7 | "common", 8 | "gallery", 9 | "themes/*" 10 | ] 11 | }, 12 | "engines": { 13 | "node": ">=20.0.0" 14 | }, 15 | "packageManager": "yarn@4.9.3" 16 | } 17 | -------------------------------------------------------------------------------- /themes/modern/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "include": [".astro/types.d.ts", "**/*"], 4 | "exclude": ["dist"], 5 | "compilerOptions": { 6 | "baseUrl": ".", 7 | "paths": { 8 | "@/*": ["src/*"], 9 | "@simple-photo-gallery/common/src/*": ["../../common/src/*"] 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /common/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/gallery.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: true, 7 | splitting: false, 8 | sourcemap: true, 9 | clean: true, 10 | minify: false, 11 | target: 'node20', 12 | outDir: 'dist', 13 | treeshake: true, 14 | external: ['zod'], 15 | }); 16 | -------------------------------------------------------------------------------- /gallery/src/modules/thumbnails/utils/index.ts: -------------------------------------------------------------------------------- 1 | import { promises as fs } from 'node:fs'; 2 | 3 | /** 4 | * Gets the last modification time of a file 5 | * @param filePath - Path to the file 6 | * @returns Promise resolving to the file's modification date 7 | */ 8 | export async function getFileMtime(filePath: string): Promise { 9 | const stats = await fs.stat(filePath); 10 | return stats.mtime; 11 | } 12 | -------------------------------------------------------------------------------- /common/.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://prettier.io/docs/configuration 3 | * @type {import("prettier").Config} 4 | */ 5 | const config = { 6 | semi: true, 7 | printWidth: 125, 8 | tabWidth: 2, 9 | useTabs: false, 10 | singleQuote: true, 11 | endOfLine: 'lf', 12 | bracketSpacing: true, 13 | trailingComma: 'all', 14 | quoteProps: 'as-needed', 15 | bracketSameLine: true, 16 | }; 17 | 18 | export default config; 19 | -------------------------------------------------------------------------------- /gallery/.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://prettier.io/docs/configuration 3 | * @type {import("prettier").Config} 4 | */ 5 | const config = { 6 | semi: true, 7 | printWidth: 125, 8 | tabWidth: 2, 9 | useTabs: false, 10 | singleQuote: true, 11 | endOfLine: 'lf', 12 | bracketSpacing: true, 13 | trailingComma: 'all', 14 | quoteProps: 'as-needed', 15 | bracketSameLine: true, 16 | }; 17 | 18 | export default config; 19 | -------------------------------------------------------------------------------- /gallery/src/modules/init/types/node-ffprobe.d.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | 3 | declare module 'node-ffprobe' { 4 | export interface Stream { 5 | codec_type: string; 6 | width?: number; 7 | height?: number; 8 | [key: string]: any; 9 | } 10 | 11 | export interface ProbeResult { 12 | streams: Stream[]; 13 | format: any; 14 | } 15 | 16 | export default function ffprobe(filePath: string): Promise; 17 | } 18 | -------------------------------------------------------------------------------- /gallery/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./dist", 5 | "types": ["node", "jest"], 6 | "declaration": true, 7 | "declarationMap": true, 8 | "sourceMap": true, 9 | "removeComments": false, 10 | "baseUrl": ".", 11 | "paths": { 12 | "@simple-photo-gallery/common": ["../common/src/gallery.ts"] 13 | } 14 | }, 15 | "include": ["src/**/*.ts", "tests/**/*.ts", "tsup.config.ts"], 16 | "exclude": ["dist"] 17 | } 18 | -------------------------------------------------------------------------------- /gallery/src/modules/telemetry/clients/console.ts: -------------------------------------------------------------------------------- 1 | import { stdout } from 'node:process'; 2 | 3 | import type { TelemetryClient, TelemetryEvent } from '../types'; 4 | 5 | /** 6 | * Telemetry client that prints events to the console. 7 | * Useful for local development and testing without sending network requests. 8 | */ 9 | export class ConsoleTelemetryClient implements TelemetryClient { 10 | async record(event: TelemetryEvent): Promise { 11 | const serialized = JSON.stringify(event, null, 2); 12 | 13 | stdout.write(`TELEMETRY EVENT: ${serialized}\n`); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gallery/src/modules/build/types/index.ts: -------------------------------------------------------------------------------- 1 | /** Options for building gallery HTML output */ 2 | export interface BuildOptions { 3 | /** Path to the directory containing the gallery */ 4 | gallery: string; 5 | /** Whether to build galleries in subdirectories recursively */ 6 | recursive: boolean; 7 | /** Optional base URL where the photos are hosted */ 8 | baseUrl?: string; 9 | /** Optional base URL where the thumbnails are hosted */ 10 | thumbsBaseUrl?: string; 11 | /** Scan for new photos */ 12 | scan: boolean; 13 | /** Create thumbnails */ 14 | thumbnails: boolean; 15 | } 16 | -------------------------------------------------------------------------------- /gallery/src/types/index.ts: -------------------------------------------------------------------------------- 1 | import type { Metadata, Sharp } from 'sharp'; 2 | 3 | /** Represents width and height dimensions */ 4 | export interface Dimensions { 5 | /** Width in pixels */ 6 | width: number; 7 | /** Height in pixels */ 8 | height: number; 9 | } 10 | 11 | /** Represents an image with metadata */ 12 | export interface ImageWithMetadata { 13 | /** The image */ 14 | image: Sharp; 15 | 16 | /** The metadata */ 17 | metadata: Metadata; 18 | } 19 | 20 | /** Represents the telemetry option */ 21 | export interface TelemetryOption { 22 | telemetry?: '0' | '1'; 23 | } 24 | -------------------------------------------------------------------------------- /gallery/tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts', 'src/lib/index.ts', 'src/lib/browser.ts'], 5 | format: ['esm', 'cjs'], 6 | dts: true, 7 | splitting: false, 8 | sourcemap: true, 9 | clean: true, 10 | minify: false, 11 | target: 'node20', 12 | outDir: 'dist', 13 | treeshake: true, 14 | external: [ 15 | '@simple-photo-gallery/theme-modern', 16 | '@simple-photo-gallery/common', 17 | 'blurhash', 18 | 'commander', 19 | 'exifreader', 20 | 'node-ffprobe', 21 | 'sharp', 22 | 'zod', 23 | ], 24 | }); 25 | -------------------------------------------------------------------------------- /themes/modern/.prettierrc.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://prettier.io/docs/configuration 3 | * @type {import("prettier").Config} 4 | */ 5 | const config = { 6 | semi: true, 7 | printWidth: 125, 8 | tabWidth: 2, 9 | useTabs: false, 10 | singleQuote: true, 11 | endOfLine: 'lf', 12 | bracketSpacing: true, 13 | trailingComma: 'all', 14 | quoteProps: 'as-needed', 15 | bracketSameLine: true, 16 | plugins: ['prettier-plugin-astro'], 17 | overrides: [ 18 | { 19 | files: '*.astro', 20 | options: { 21 | parser: 'astro', 22 | }, 23 | }, 24 | ], 25 | }; 26 | 27 | export default config; 28 | -------------------------------------------------------------------------------- /gallery/src/config/index.ts: -------------------------------------------------------------------------------- 1 | /** Default thumbnail size in pixels */ 2 | export const DEFAULT_THUMBNAIL_SIZE = 300; 3 | 4 | /** Set of supported image file extensions */ 5 | export const IMAGE_EXTENSIONS = new Set(['.jpg', '.jpeg', '.png', '.gif', '.webp', '.tiff', '.tif', '.svg', '.avif']); 6 | 7 | /** Set of supported video file extensions */ 8 | export const VIDEO_EXTENSIONS = new Set(['.mp4', '.avi', '.mov', '.wmv', '.flv', '.webm', '.mkv', '.m4v', '.3gp']); 9 | 10 | /** Set of supported header image landscape widths */ 11 | export const HEADER_IMAGE_LANDSCAPE_WIDTHS = [3840, 2560, 1920, 1280, 960, 640]; 12 | 13 | /** Set of supported header image portrait widths */ 14 | export const HEADER_IMAGE_PORTRAIT_WIDTHS = [1080, 720, 480, 360]; 15 | -------------------------------------------------------------------------------- /gallery/src/lib/index.ts: -------------------------------------------------------------------------------- 1 | // Re-export types from common package for use in other JS apps 2 | export type { 3 | GalleryData, 4 | GalleryMetadata, 5 | GallerySection, 6 | MediaFile, 7 | MediaFileWithPath, 8 | SubGallery, 9 | Thumbnail, 10 | } from '@simple-photo-gallery/common'; 11 | 12 | // Re-export utility functions from the CLI 13 | export { generateBlurHash } from '../utils/blurhash'; 14 | export { loadImage, loadImageWithMetadata, resizeImage, cropAndResizeImage, createImageThumbnails } from '../utils/image'; 15 | export { getVideoDimensions, createVideoThumbnails } from '../utils/video'; 16 | export type { Dimensions, ImageWithMetadata } from '../types'; 17 | 18 | export { createGallerySocialMediaCardImage } from '../modules/build/utils'; 19 | -------------------------------------------------------------------------------- /gallery/jest.config.cjs: -------------------------------------------------------------------------------- 1 | /** @type {import('ts-jest').JestConfigWithTsJest} */ 2 | module.exports = { 3 | preset: 'ts-jest/presets/default-esm', 4 | testEnvironment: 'node', 5 | extensionsToTreatAsEsm: ['.ts'], 6 | testMatch: ['**/tests/**/*.test.ts'], 7 | testPathIgnorePatterns: ['/node_modules/', '/dist/'], 8 | transformIgnorePatterns: ['node_modules/(?!(@simple-photo-gallery/common)/)'], 9 | moduleNameMapper: { 10 | '^(\\.{1,2}/.*)\\.js$': '$1', 11 | '^@simple-photo-gallery/common$': '/../common/src/gallery.ts', 12 | }, 13 | transform: { 14 | '^.+\\.tsx?$': [ 15 | 'ts-jest', 16 | { 17 | useESM: true, 18 | tsconfig: { 19 | module: 'ES2022', 20 | }, 21 | }, 22 | ], 23 | }, 24 | // Run tests serially to avoid race conditions with file system operations 25 | maxWorkers: 1, 26 | }; 27 | -------------------------------------------------------------------------------- /gallery/src/modules/telemetry/clients/api.ts: -------------------------------------------------------------------------------- 1 | import process from 'node:process'; 2 | 3 | import axios from 'axios'; 4 | 5 | import type { TelemetryClient, TelemetryEvent } from '../types'; 6 | 7 | /** 8 | * Telemetry client that sends events to the Simple Photo Gallery telemetry API. 9 | */ 10 | export class ApiTelemetryClient implements TelemetryClient { 11 | private readonly endpoint = 'https://tools.simple.photo/api/telemetry'; 12 | 13 | async record(event: TelemetryEvent): Promise { 14 | try { 15 | axios.post(this.endpoint, event, { 16 | headers: { 17 | 'content-type': 'application/json', 18 | 'user-agent': `simple-photo-gallery/${event.packageVersion} (${process.platform}; ${process.arch})`, 19 | }, 20 | }); 21 | } catch { 22 | // Swallow network errors - telemetry must never interrupt the CLI flow. 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | Complete documentation for the Simple Photo Gallery CLI tool. 4 | 5 | ## Reference 6 | 7 | - **[Commands](./commands/README.md)** - All CLI commands and options 8 | - **[Gallery Configuration](./configuration.md)** - Manual editing of gallery.json 9 | - **[Deployment](./deployment.md)** - Hosting and deployment options 10 | - **[Embedding](./embedding.md)** - Customize the gallery when embedding in another site 11 | 12 | ## Need Help? 13 | 14 | 1. **Quick start**: Follow the [main README](../README.md) 15 | 2. **Common issues**: Check the troubleshooting sections in each guide 16 | 3. **Configuration**: See the [Gallery Configuration](./configuration.md) guide for advanced setup 17 | 18 | ## Contributing 19 | 20 | Found an issue or want to improve the documentation? 21 | 22 | - Open an issue in the GitHub repository 23 | - Submit a pull request with documentation improvements 24 | - Help us keep the documentation accurate and up-to-date 25 | -------------------------------------------------------------------------------- /gallery/src/modules/telemetry/types/index.ts: -------------------------------------------------------------------------------- 1 | import type os from 'node:os'; 2 | 3 | export type CommandResultSummaryValue = string | number | boolean | undefined; 4 | 5 | export type CommandResultSummary = Record; 6 | 7 | export interface TelemetryOptions { 8 | state?: '0' | '1'; 9 | } 10 | 11 | export interface TelemetryConfigSchema { 12 | telemetryEnabled?: boolean; 13 | } 14 | 15 | export interface TelemetryEvent { 16 | command: string; 17 | argumentsProvided: string[]; 18 | globalOptionsProvided: string[]; 19 | timestamp: string; 20 | durationMs: number; 21 | packageName: string; 22 | packageVersion: string; 23 | nodeVersion: string; 24 | osPlatform: ReturnType; 25 | osRelease: string; 26 | osArch: string; 27 | result: 'success' | 'error'; 28 | metrics?: CommandResultSummary; 29 | errorName?: string; 30 | errorMessage?: string; 31 | } 32 | 33 | export interface TelemetryClient { 34 | record(event: TelemetryEvent): Promise; 35 | } 36 | -------------------------------------------------------------------------------- /themes/modern/src/features/themes/base-theme/components/footer/Footer.astro: -------------------------------------------------------------------------------- 1 | --- 2 | // Footer component for Simple Photo Gallery 3 | --- 4 | 5 | 12 | 13 | 44 | -------------------------------------------------------------------------------- /themes/modern/src/lib/markdown.ts: -------------------------------------------------------------------------------- 1 | import { marked } from 'marked'; 2 | 3 | // Configure marked to only allow specific formatting options 4 | const renderer = new marked.Renderer(); 5 | 6 | // Disable headings by rendering them as paragraphs 7 | renderer.heading = ({ text }: { text: string }) => { 8 | return '

' + text + '

\n'; 9 | }; 10 | 11 | // Disable images 12 | renderer.image = () => ''; 13 | 14 | // Disable HTML 15 | renderer.html = () => ''; 16 | 17 | // Disable tables 18 | renderer.table = () => ''; 19 | renderer.tablerow = () => ''; 20 | renderer.tablecell = () => ''; 21 | 22 | // Configure marked options 23 | marked.use({ 24 | renderer: renderer, 25 | breaks: true, 26 | gfm: true, 27 | }); 28 | 29 | /** 30 | * Renders markdown with limited formatting options. 31 | * Supported: paragraphs, bold, italic, lists, code blocks, blockquotes, links 32 | * Disabled: headings (rendered as paragraphs), images, HTML, tables 33 | */ 34 | export async function renderMarkdown(markdown: string): Promise { 35 | if (!markdown) return ''; 36 | return await marked.parse(markdown); 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 CreafexLab 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /gallery/src/modules/init/utils/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'node:path'; 2 | 3 | import { IMAGE_EXTENSIONS, VIDEO_EXTENSIONS } from '../../../config'; 4 | 5 | import type { MediaFileType } from '../types'; 6 | 7 | /** 8 | * Determines the media file type based on file extension 9 | * @param fileName - Name of the file to check 10 | * @returns Media file type ('image' or 'video') or null if not supported 11 | */ 12 | export function getMediaFileType(fileName: string): MediaFileType | null { 13 | const ext = path.extname(fileName).toLowerCase(); 14 | if (IMAGE_EXTENSIONS.has(ext)) return 'image'; 15 | if (VIDEO_EXTENSIONS.has(ext)) return 'video'; 16 | return null; 17 | } 18 | 19 | /** 20 | * Converts a folder name into a properly capitalized title 21 | * @param folderName - The folder name to convert 22 | * @returns Formatted title with proper capitalization 23 | */ 24 | export function capitalizeTitle(folderName: string): string { 25 | return folderName 26 | .replace('-', ' ') 27 | .replace('_', ' ') 28 | .split(' ') 29 | .map((word: string) => word.charAt(0).toUpperCase() + word.slice(1)) 30 | .join(' '); 31 | } 32 | -------------------------------------------------------------------------------- /gallery/src/utils/blurhash.ts: -------------------------------------------------------------------------------- 1 | import { encode } from 'blurhash'; 2 | 3 | import { loadImage } from './image'; 4 | 5 | /** 6 | * Generates a BlurHash from an image file or Sharp instance 7 | * @param imagePath - Path to image file or Sharp instance 8 | * @param componentX - Number of x components (default: 4) 9 | * @param componentY - Number of y components (default: 3) 10 | * @returns Promise resolving to BlurHash string 11 | */ 12 | export async function generateBlurHash(imagePath: string, componentX: number = 4, componentY: number = 3): Promise { 13 | const image = await loadImage(imagePath); 14 | 15 | // Resize to small size for BlurHash computation to improve performance 16 | // BlurHash doesn't need high resolution 17 | const { data, info } = await image 18 | .resize(32, 32, { fit: 'inside' }) 19 | .ensureAlpha() 20 | .raw() 21 | .toBuffer({ resolveWithObject: true }); 22 | 23 | // Convert to Uint8ClampedArray format expected by blurhash 24 | const pixels = new Uint8ClampedArray(data.buffer); 25 | 26 | // Generate BlurHash 27 | return encode(pixels, info.width, info.height, componentX, componentY); 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/check-cli.yml: -------------------------------------------------------------------------------- 1 | name: Run Checks and Tests for the CLI 2 | 3 | on: 4 | pull_request: 5 | branches: [main] 6 | types: [opened, synchronize, reopened] 7 | paths: 8 | - "gallery/**" 9 | 10 | jobs: 11 | test: 12 | runs-on: ubuntu-latest 13 | 14 | strategy: 15 | matrix: 16 | node-version: [20.x] 17 | 18 | steps: 19 | - name: Checkout code 20 | uses: actions/checkout@v4 21 | 22 | - name: Setup Node.js 23 | uses: actions/setup-node@v4 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | cache: "yarn" 27 | cache-dependency-path: "yarn.lock" 28 | 29 | - name: Enable Corepack 30 | run: corepack enable 31 | 32 | - name: Install dependencies 33 | run: yarn install --immutable 34 | 35 | - name: Run checks (common) 36 | working-directory: ./common 37 | run: yarn check 38 | 39 | - name: Run checks (gallery) 40 | working-directory: ./gallery 41 | run: yarn check 42 | 43 | - name: Run tests 44 | working-directory: ./gallery 45 | run: yarn test 46 | -------------------------------------------------------------------------------- /docs/commands/clean.md: -------------------------------------------------------------------------------- 1 | # clean 2 | 3 | Removes gallery files while preserving original photos. 4 | 5 | ```bash 6 | spg clean [options] 7 | ``` 8 | 9 | ## How it works 10 | 11 | The command will remove the `index.html` file and the `gallery` folder from the gallery directory. It will also remove the `gallery.json` file. After running this command, your photos folder will return to the same state as it was before you initialized the gallery. 12 | 13 | ## Options 14 | 15 | | Option | Description | Default | 16 | | ---------------------- | ------------------------- | ----------------- | 17 | | `-g, --gallery ` | Path to gallery directory | Current directory | 18 | | `-r, --recursive` | Clean all galleries | `false` | 19 | | `-v, --verbose` | Show detailed output | | 20 | | `-q, --quiet` | Only show warnings/errors | | 21 | | `-h, --help` | Show command help | | 22 | 23 | ## Examples 24 | 25 | ```bash 26 | # Clean current directory 27 | spg clean 28 | 29 | # Clean specific directory 30 | spg clean -g /path/to/gallery 31 | 32 | # Clean all galleries recursively 33 | spg clean -r 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/commands/README.md: -------------------------------------------------------------------------------- 1 | # Commands 2 | 3 | This is the command reference for Simple Photo Gallery CLI. All commands can be run with `npx simple-photo-gallery@latest `. 4 | 5 | > **Navigation:** [Configuration Guide](../configuration.md) | [Deployment Guide](../deployment.md) | [Main Documentation](../README.md) 6 | 7 | ## Available Commands 8 | 9 | - **[init](./init.md)** - Initialize a new gallery by scanning a folder for images and videos 10 | - **[build](./build.md)** - Generate the HTML gallery from your photos and gallery.json 11 | - **[thumbnails](./thumbnails.md)** - Generate optimized thumbnail images for all media files 12 | - **[clean](./clean.md)** - Remove gallery files while preserving original photos 13 | 14 | ## Quick Reference 15 | 16 | For the fastest way to get started, install the `simple-photo-gallery` package globally and then you can use the `spg` command: 17 | 18 | ```bash 19 | npm install -g simple-photo-gallery@latest 20 | spg init 21 | spg build 22 | ``` 23 | 24 | Alternatively you can use `npx` to run the commands directly: 25 | 26 | ```bash 27 | npx simple-photo-gallery@latest init 28 | npx simple-photo-gallery@latest build 29 | ``` 30 | 31 | For more advanced workflows and configuration options, see the individual command documentation above. 32 | -------------------------------------------------------------------------------- /gallery/src/modules/telemetry/index.ts: -------------------------------------------------------------------------------- 1 | import type { TelemetryService } from './service'; 2 | import type { CommandResultSummary, TelemetryOptions } from './types'; 3 | import type { ConsolaInstance } from 'consola'; 4 | 5 | /** 6 | * Handles the `gallery telemetry` command allowing users to configure telemetry preferences. 7 | */ 8 | export async function telemetry( 9 | options: TelemetryOptions, 10 | ui: ConsolaInstance, 11 | telemetryService: TelemetryService, 12 | ): Promise { 13 | const updates: CommandResultSummary = {}; 14 | 15 | // Return the status if no state is provided 16 | if (options.state === undefined) { 17 | const current = telemetryService.getStoredPreference(); 18 | if (current === undefined) { 19 | ui.info('Telemetry preference not set yet. It will be requested on next command run.'); 20 | updates.telemetryStatus = 'unset'; 21 | } else { 22 | ui.info(`Telemetry is currently ${current ? 'enabled' : 'disabled'}.`); 23 | updates.telemetryEnabled = current; 24 | } 25 | } else { 26 | // Set the telemetry preference 27 | telemetryService.setStoredPreference(options.state === '1'); 28 | ui.success(`Anonymous telemetry ${options.state === '1' ? 'enabled' : 'disabled'}.`); 29 | updates.telemetryEnabled = options.state === '1'; 30 | } 31 | 32 | return updates; 33 | } 34 | -------------------------------------------------------------------------------- /themes/modern/src/features/themes/base-theme/components/gallery-section/GallerySectionHeader.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { renderMarkdown } from '@/lib/markdown'; 3 | 4 | import type { GallerySection as GallerySectionType } from '@simple-photo-gallery/common/src/gallery'; 5 | 6 | interface Props { 7 | section: GallerySectionType; 8 | } 9 | 10 | const { section } = Astro.props; 11 | 12 | // Parse description as Markdown if it exists 13 | const parsedDescription = section.description ? await renderMarkdown(section.description) : ''; 14 | --- 15 | 16 |