diff --git a/README.md b/README.md index 3d94ae1..96127e7 100644 --- a/README.md +++ b/README.md @@ -56,14 +56,3 @@ Then, if you're using rsync, after configuring the `gallerybm` host (or the name ```bash rsync --delete-after -acP dist/ gallerybm:/home/public ``` - -Or if you prefer LFTP, create a `.env` file at the root of the project: - -```env -DEPLOY_LFTP_HOST=https://example-webdav-server.com -DEPLOY_LFTP_USER=example_user -DEPLOY_LFTP_PASSWORD=sup3r_s3cr3t_password -DEPLOY_LFTP_TARGETFOLDER=sites/gallery.badmanners.xyz/ -``` - -Then run `npm run deploy-lftp`. diff --git a/package-lock.json b/package-lock.json index 06d416b..71d2bd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gallery.badmanners.xyz", - "version": "1.13.0", + "version": "1.13.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gallery.badmanners.xyz", - "version": "1.13.0", + "version": "1.13.1", "hasInstallScript": true, "dependencies": { "@astrojs/alpinejs": "^0.4.0", @@ -39,7 +39,6 @@ "@types/node": "^22.7.4", "@types/sanitize-html": "^2.13.0", "commander": "^12.1.0", - "dotenv-cli": "^7.4.2", "fetch-retry": "^6.0.0", "prettier": "^3.3.3", "prettier-plugin-astro": "^0.14.1", @@ -3107,9 +3106,9 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3297,45 +3296,6 @@ "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/dotenv": { - "version": "16.4.5", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", - "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://dotenvx.com" - } - }, - "node_modules/dotenv-cli": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/dotenv-cli/-/dotenv-cli-7.4.2.tgz", - "integrity": "sha512-SbUj8l61zIbzyhIbg0FwPJq6+wjbzdn9oEtozQpZ6kW2ihCcapKVZj49oCT3oPM+mgQm+itgvUQcG5szxVrZTA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "dotenv": "^16.3.0", - "dotenv-expand": "^10.0.0", - "minimist": "^1.2.6" - }, - "bin": { - "dotenv": "cli.js" - } - }, - "node_modules/dotenv-expand": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", - "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, "node_modules/dset": { "version": "3.1.4", "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", @@ -5843,16 +5803,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", diff --git a/package.json b/package.json index 2ba5a52..738c499 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "gallery.badmanners.xyz", "type": "module", - "version": "1.13.0", + "version": "1.13.1", "scripts": { "postinstall": "astro sync", "dev": "astro dev", @@ -12,8 +12,7 @@ "check": "astro check", "astro": "astro", "prettier": "prettier --write .", - "export-story": "tsx scripts/export-story.ts", - "deploy-lftp": "dotenv tsx scripts/deploy-lftp.ts --" + "export-story": "tsx scripts/export-story.ts" }, "dependencies": { "@astrojs/alpinejs": "^0.4.0", @@ -46,7 +45,6 @@ "@types/node": "^22.7.4", "@types/sanitize-html": "^2.13.0", "commander": "^12.1.0", - "dotenv-cli": "^7.4.2", "fetch-retry": "^6.0.0", "prettier": "^3.3.3", "prettier-plugin-astro": "^0.14.1", diff --git a/scripts/deploy-lftp.ts b/scripts/deploy-lftp.ts deleted file mode 100644 index c6c5914..0000000 --- a/scripts/deploy-lftp.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { spawn } from "node:child_process"; -import { join, normalize as n } from "node:path/posix"; -import { program, Option } from "commander"; - -interface DeployLftpOptions { - host: string; - user: string; - password: string; - targetFolder: string; - sourceFolder: string; - assetsFolder: string; -} - -async function deployLftp({ host, user, password, targetFolder, sourceFolder, assetsFolder }: DeployLftpOptions) { - const process = spawn( - "lftp", - [ - "-c", - [ - `open -u ${user},${password.replaceAll(/([ \t.,:;?!`'"^|*+#&$\(\)\[\]{}<>\\/-])/, "\\$1")} ${host}`, - `mirror --reverse --include-glob ${join(assetsFolder, "*")} --delete --only-missing --no-perms --verbose ${n(sourceFolder)} ${n(targetFolder)}`, - `mirror --reverse --exclude-glob ${join(assetsFolder, "*")} --delete --no-perms --verbose ${n(sourceFolder)} ${n(targetFolder)}`, - `bye`, - ].join("\n"), - ], - { - stdio: "inherit", - }, - ); - await new Promise((resolve, reject) => { - process.on("close", (code) => (code === 0 ? resolve(0) : reject(`lftp failed with code ${code}`))); - }); -} - -await program - .name("deploy-lftp") - .description("Deploy files to remote server with LFTP") - .addOption( - new Option("-h, --host <hostname>", "Hostname of the LFTP (i.e. WebDav, SCP, SFTP...) remote.").env( - "DEPLOY_LFTP_HOST", - ), - ) - .addOption(new Option("-u, --user <username>", "Username portion of the LFTP credentials").env("DEPLOY_LFTP_USER")) - .addOption( - new Option("-p, --password <pass>", "Password portion of the LFTP credentials").env("DEPLOY_LFTP_PASSWORD"), - ) - .addOption( - new Option("-t, --target-folder <remoteDir>", "Folder to mirror files to in the LFTP remote").env( - "DEPLOY_LFTP_TARGETFOLDER", - ), - ) - .addOption( - new Option("-s, --source-folder <localDir>", "Folder to read files from in the local machine") - .env("DEPLOY_LFTP_SOURCEFOLDER") - .default("dist/"), - ) - .addOption( - new Option("-a, --assets-folder <localDir>", "Directory inside of --source-folder of assets with hash-based names") - .env("DEPLOY_LFTP_ASSETSFOLDER") - .default("assets/"), - ) - .action(deployLftp) - .parseAsync(); diff --git a/src/data/licenses.toml b/src/data/licenses.toml index 15b7b14..26bc3ef 100644 --- a/src/data/licenses.toml +++ b/src/data/licenses.toml @@ -1,11 +1,12 @@ -# licenses.toml +file = "licenses.toml" +url = "https://gallery.badmanners.xyz/licenses.toml" [copyright] title = "gallery.badmanners.xyz" description = "Bad Manners's self-hosted gallery." type = "website" date = "2024" -author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz>" } +author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz" } source = "https://git.badmanners.xyz/badmanners/gallery.badmanners.xyz" license = { name = "MIT", url = "https://opensource.org/license/mit" } notes = """All rights reserved. \ @@ -24,7 +25,7 @@ notes = """My characters, whether directly attributed to me or unattributed, are type = "content" description = "Content hosted on this website, i.e. the stories, games, and blog posts." date = "2022-2024" -author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz>" } +author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz" } source = "https://git.badmanners.xyz/badmanners/gallery.badmanners.xyz/src/branch/main/src/content" license = { name = "CC-BY-NC-ND-4.0", url = "https://creativecommons.org/licenses/by-nc-nd/4.0/" } notes = "All rights reserved." @@ -60,7 +61,7 @@ notes = """All third-party copyrights and trademarks belong to their respective [[attributions]] description = "Edited icons for other websites." type = "icons" -author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz>" } +author = { name = "Bad Manners", url = "https://badmanners.xyz", email = "me@badmanners.xyz" } source = "https://git.badmanners.xyz/badmanners/badmanners.xyz/src/branch/main/src/components/icons/brands" license = { name = "CC0 1.0 Universal", url = "https://creativecommons.org/publicdomain/zero/1.0/" } items = [ diff --git a/src/layouts/BlogPostLayout.astro b/src/layouts/BlogPostLayout.astro index fad4c47..faaceff 100644 --- a/src/layouts/BlogPostLayout.astro +++ b/src/layouts/BlogPostLayout.astro @@ -47,6 +47,7 @@ const relatedBlogPosts = (await getEntries(props.relatedBlogPosts)).filter((post relatedGames={relatedGames} relatedBlogPosts={relatedBlogPosts} posts={props.posts} + authors={authorsList} labelReturnTo={{ title: t(props.lang, "blog/return_to_blog_posts"), link: "/blog" }} labelPreviousContent={t(props.lang, "blog/previous_post_aria_label")} labelNextContent={t(props.lang, "blog/next_post_aria_label")} diff --git a/src/layouts/GameLayout.astro b/src/layouts/GameLayout.astro index d26e6af..5a029aa 100644 --- a/src/layouts/GameLayout.astro +++ b/src/layouts/GameLayout.astro @@ -44,6 +44,7 @@ const metaDescription = t(props.lang, "game/warnings", props.platforms, props.co relatedGames={relatedGames} relatedBlogPosts={relatedBlogPosts} posts={props.posts} + authors={authorsList} labelReturnTo={{ title: t(props.lang, "game/return_to_games"), link: "/games" }} labelPreviousContent={t(props.lang, "game/previous_game_aria_label")} labelNextContent={t(props.lang, "game/next_game_aria_label")} diff --git a/src/layouts/PublishedContentLayout.astro b/src/layouts/PublishedContentLayout.astro index 79e500e..c720a19 100644 --- a/src/layouts/PublishedContentLayout.astro +++ b/src/layouts/PublishedContentLayout.astro @@ -49,6 +49,7 @@ type Props = { relatedGames?: CollectionEntry<"games">[]; relatedBlogPosts?: CollectionEntry<"blog">[]; posts: Posts; + authors: CollectionEntry<"users">[]; /* Layout attributes */ publishedContentType: "story" | "game" | "blog post"; @@ -126,6 +127,12 @@ const returnTo = series </Fragment> ) : null } + { + props.authors + .map((user) => user.data.links.mastodon?.username) + .filter((value) => value) + .map((username) => <meta name="fediverse:creator" content={`@${username}`} />) + } <slot name="head" /> </Fragment> <div diff --git a/src/layouts/StoryLayout.astro b/src/layouts/StoryLayout.astro index ddcca0b..cede7c6 100644 --- a/src/layouts/StoryLayout.astro +++ b/src/layouts/StoryLayout.astro @@ -55,6 +55,7 @@ const metaDescription = t(props.lang, "story/warnings", wordCount, props.content relatedGames={relatedGames} relatedBlogPosts={relatedBlogPosts} posts={props.posts} + authors={authorsList} labelReturnTo={{ title: t(props.lang, "story/return_to_stories"), link: "/stories" }} labelPreviousContent={t(props.lang, "story/previous_story_aria_label")} labelNextContent={t(props.lang, "story/next_story_aria_label")}