Add fediverse:creator tag to pages

This commit is contained in:
Bad Manners 2024-11-21 10:10:49 -03:00
parent 51cdd232ad
commit 5d701069e9
Signed by: badmanners
GPG key ID: 8C88292CCB075609
9 changed files with 22 additions and 137 deletions

View file

@ -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`.

60
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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();

View file

@ -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 = [

View file

@ -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")}

View file

@ -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")}

View file

@ -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

View file

@ -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")}