From 7af80ded6fdab0ae2f282a0693d2a7d9285cd8ef Mon Sep 17 00:00:00 2001 From: Alex Bates Date: Mon, 12 Oct 2026 11:31:40 +0100 Subject: [PATCH] say image instead of picture --- assets/components.css | 4 ++-- assets/components/media_input.js | 2 +- assets/components/share_form.js | 4 ++-- src/homepage.rs | 10 +++++----- src/markdown.rs | 2 +- src/mods.rs | 24 ++++++++++++------------ tests/helpers.py | 14 +++++++------- tests/test_homepage.py | 6 +++--- tests/test_media_gallery.py | 16 ++++++++-------- tests/test_mod_listing.py | 10 +++++----- tests/test_mod_transfer.py | 2 +- 11 files changed, 47 insertions(+), 47 deletions(-) diff --git a/assets/components.css b/assets/components.css index cc9f14d..82c6098 100644 --- a/assets/components.css +++ b/assets/components.css @@ -1631,7 +1631,7 @@ download-fields { } } -/* Three mods' pictures, scattered like photos on a desk. */ +/* Three mods' images, scattered like photos on a desk. */ .home-shots { position: relative; block-size: 21.25rem; @@ -2177,7 +2177,7 @@ download-fields { font-size: var(--text-sm); } -/* What a mod without a picture shows in its place: its game and title on a +/* What a mod without an image shows in its place: its game and title on a sheet of paper. */ .mod-placeholder { container-type: inline-size; diff --git a/assets/components/media_input.js b/assets/components/media_input.js index b914f40..7491146 100644 --- a/assets/components/media_input.js +++ b/assets/components/media_input.js @@ -83,7 +83,7 @@ class MediaInput extends HTMLElement { fileInput.addEventListener("change", () => addFiles(fileInput.files)); - // On the pictures the page came with as well as those added since. + // On the images the page came with as well as those added since. gallery.addEventListener("click", (event) => { event.target.closest(".remove")?.closest(".item")?.remove(); }); diff --git a/assets/components/share_form.js b/assets/components/share_form.js index 17e4bcd..847032b 100644 --- a/assets/components/share_form.js +++ b/assets/components/share_form.js @@ -1,7 +1,7 @@ import { clearErrors, postJson, putFile, showErrors } from "./upload.js"; // publishes a new mod and its first version together, asking -// only for that version's download. Its pictures upload as they're added, +// only for that version's download. Its images upload as they're added, // the download's file uploads when it's sent, and then the server writes // both records. A file is offered only for a game whose files Star Haven // hosts, and otherwise a link. @@ -29,7 +29,7 @@ class ShareForm extends HTMLElement { const errors = []; if (!form.elements.title.value.trim()) errors.push(["title", "Enter a title"]); if (!game()) errors.push(["game", "Select a game"]); - if (!form.querySelector("media-input .item")) errors.push(["media", "Add a picture"]); + if (!form.querySelector("media-input .item")) errors.push(["media", "Add an image"]); if (!download.value) errors.push(["download", download.missing]); return errors; } diff --git a/src/homepage.rs b/src/homepage.rs index 2e4c3e2..5da3380 100644 --- a/src/homepage.rs +++ b/src/homepage.rs @@ -28,7 +28,7 @@ const HOME_LIMIT: i64 = 8; /// How many mods `/mods` shows. const LIST_LIMIT: i64 = 100; -/// How many of a featured mod's other pictures it shows beside its first. +/// How many of a featured mod's other images it shows beside its first. const FEATURED_THUMBS: usize = 4; /// How many days, today included, Popular counts stars, downloads, and views @@ -63,7 +63,7 @@ pub struct Card { } impl Card { - /// The `n`th picture in the mod's gallery, through the blob proxy. + /// The `n`th image in the mod's gallery, through the blob proxy. fn image_url(&self, n: usize) -> Option { let item = self.media.get(n)?; Some(format!( @@ -280,7 +280,7 @@ async fn handle_get_index( .map_err(AppError::Internal)?; } - // The intro's pictures: the first of each popular mod that the carousel + // The intro's images: the first of each popular mod that the carousel // below doesn't already show, then of the featured ones if there aren't // enough. let is_featured = |card: &&Card| { @@ -562,7 +562,7 @@ fn card_byline(card: &Card, class: &str) -> Markup { } } -/// A mod's first picture, title, description, author, and stars. +/// A mod's first image, title, description, author, and stars. pub fn mod_card(card: &Card) -> Markup { let inner = html! { div.mod-card-image { @@ -585,7 +585,7 @@ pub fn mod_card(card: &Card) -> Markup { } } -/// Where a mod's picture would be, for a mod without one: its game and title +/// Where a mod's image would be, for a mod without one: its game and title /// on paper. pub fn image_placeholder(game: Option, title: &str) -> Markup { html! { diff --git a/src/markdown.rs b/src/markdown.rs index 88b6993..cf4c985 100644 --- a/src/markdown.rs +++ b/src/markdown.rs @@ -79,7 +79,7 @@ pub fn render(markdown: &str) -> Markup { attrs, }), Event::End(TagEnd::Heading(level)) => Event::End(TagEnd::Heading(demote(level))), - // A listing has a gallery for its pictures, so an image here is + // A listing has a gallery for its images, so an image here is // only a link to one. Event::Start(Tag::Image { link_type, diff --git a/src/mods.rs b/src/mods.rs index 8d3d0f1..9e91cdc 100644 --- a/src/mods.rs +++ b/src/mods.rs @@ -187,7 +187,7 @@ async fn handle_get_create(_session: SessionCookie, page: Page) -> Html /// its first version. Nothing reaches the author's repo until they publish, /// so leaving halfway leaves nothing behind. /// -/// Not a plain form post: the pictures and the version's file upload as +/// Not a plain form post: the images and the version's file upload as /// they're chosen and as it's sent, so `` drives it, and there is /// nothing useful to fall back to without it. fn share_form() -> Markup { @@ -208,7 +208,7 @@ fn share_form() -> Markup { div.accent-red id="share-summary" role="alert" tabindex="-1" hidden {} h1 { "Share a mod" } noscript { - p.error { "Sharing a mod needs JavaScript, because its pictures and file upload as you add them." } + p.error { "Sharing a mod needs JavaScript, because its images and file upload as you add them." } } (form::text_field("title", "Title", "", None, None)) (form::radio_group("game", "Game the mod is for", &game_options, None, None)) @@ -312,7 +312,7 @@ struct ShareRequest { game: String, #[serde(default)] description: String, - /// The gallery editor's JSON list of uploaded pictures. + /// The gallery editor's JSON list of uploaded images. #[serde(default)] media: String, /// The key `handle_post_create_presign` handed out, now that it has been @@ -352,10 +352,10 @@ async fn handle_post_create( return Err(refuse("Select a game").await); }; let Ok(media) = parse_media_field(&request.media) else { - return Err(refuse("The pictures could not be read - try adding them again").await); + return Err(refuse("The images could not be read - try adding them again").await); }; if media.is_empty() { - return Err(refuse("Add a picture").await); + return Err(refuse("Add an image").await); } // An uploaded file's key already names the listing it was signed for. @@ -854,7 +854,7 @@ fn edit_form(existing: &Found, errors: &EditFormErrors) -> Markup { } } -/// The pictures already in `did`'s `listing`, for its gallery editor. +/// The images already in `did`'s `listing`, for its gallery editor. fn gallery_items(did: &Did, listing: &ModListing) -> Vec { listing .media @@ -869,7 +869,7 @@ fn gallery_items(did: &Did, listing: &ModListing) -> Vec Markup { html! { div.form-item id="media" { - label { "Pictures" } + label { "Images" } div.hint { "4:3" } div.error id="media-error" hidden[error.is_none()] { (error.unwrap_or_default()) } noscript { - p.error { "Editing the pictures needs JavaScript, because each image is uploaded as soon as it's chosen." } + p.error { "Editing the images needs JavaScript, because each image is uploaded as soon as it's chosen." } } (crate::components::media_input::render(media_endpoint, "media", items)) } @@ -994,9 +994,9 @@ async fn handle_post_settings( } else if existing.record.title.chars().count() > 300 { errors.title = Some("Title must be 300 characters or less"); } - // A mod is listed by its first picture, so it keeps at least one. + // A mod is listed by its first image, so it keeps at least one. if existing.record.media.is_empty() { - errors.media = Some("Add a picture"); + errors.media = Some("Add an image"); } if errors.title.is_some() || errors.media.is_some() { @@ -1071,7 +1071,7 @@ async fn handle_post_media( } /// Like [`handle_post_media`], for a mod that isn't shared yet, so the -/// picture goes to the signed-in account's own PDS. +/// image goes to the signed-in account's own PDS. async fn handle_post_create_media( State(state): State, session: SessionCookie, diff --git a/tests/helpers.py b/tests/helpers.py index 8f4aeb5..ea7af2f 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -42,7 +42,7 @@ class Actor: title: str = "Test Mod", game: str = "Paper Mario", ) -> None: - """Shares a mod with one picture and a download, its first version, + """Shares a mod with one image and a download, its first version, leaving the page on the new mod. `slug` must match what the title slugifies to - the form derives it @@ -53,7 +53,7 @@ class Actor: self.page.get_by_label("Title").fill(title) self.page.get_by_label(game, exact=True).check() self.page.locator("media-input input[type=file]").set_input_files( - files=[{"name": "picture.png", "mimeType": "image/png", "buffer": PNG}] + files=[{"name": "image.png", "mimeType": "image/png", "buffer": PNG}] ) expect(self.page.locator("media-input .item")).to_have_count(1) if self.page.get_by_text("Upload…").is_visible(): @@ -72,8 +72,8 @@ class Actor: expect(self.page).to_have_url(f"{self.app_url}/{self.handle}/{slug}") - def remove_pictures(self) -> None: - """Takes every picture out of the gallery on the settings page it's + def remove_images(self) -> None: + """Takes every image out of the gallery on the settings page it's on, without saving.""" remove = self.page.locator("media-input .remove") for _ in range(remove.count()): @@ -176,9 +176,9 @@ class Actor: return response.json()["records"] -def strip_pictures(database: Path, slug: str) -> None: - """Leaves a mod with no pictures as far as the appview knows, as one - imported or shared before pictures were required can be.""" +def strip_images(database: Path, slug: str) -> None: + """Leaves a mod with no images as far as the appview knows, as one + imported or shared before images were required can be.""" with sqlite3.connect(database) as db: db.execute("UPDATE mod_listing SET media = '[]' WHERE slug = ?", (slug,)) diff --git a/tests/test_homepage.py b/tests/test_homepage.py index 5264681..fc55351 100644 --- a/tests/test_homepage.py +++ b/tests/test_homepage.py @@ -5,7 +5,7 @@ from pathlib import Path import requests from conftest import Appview -from helpers import Actor, strip_pictures +from helpers import Actor, strip_images from playwright.sync_api import Page, expect @@ -109,10 +109,10 @@ def test_without_scripts_the_first_featured_mod_shows( context.close() -def test_a_mod_without_pictures_shows_its_game_and_title(actor: Actor, appview: Appview): +def test_a_mod_without_images_shows_its_game_and_title(actor: Actor, appview: Appview): actor.login() actor.create_mod("master-quest", title="Master Quest") - strip_pictures(appview.database, "master-quest") + strip_images(appview.database, "master-quest") actor.page.goto(actor.app_url) card = actor.page.get_by_role("region", name="New").get_by_role("link", name="Master Quest") diff --git a/tests/test_media_gallery.py b/tests/test_media_gallery.py index 10a3b3e..352eb47 100644 --- a/tests/test_media_gallery.py +++ b/tests/test_media_gallery.py @@ -3,7 +3,7 @@ from playwright.sync_api import expect from conftest import Appview -from helpers import PNG, Actor, strip_pictures +from helpers import PNG, Actor, strip_images LISTING_COLLECTION = "dev.starhaven.mod.listing" @@ -13,7 +13,7 @@ def test_uploading_images_saves_an_ordered_tagged_gallery_to_the_pds(actor: Acto actor.create_mod("master-quest", title="Master Quest") actor.page.goto(f"{actor.app_url}/{actor.handle}/master-quest/settings") - actor.remove_pictures() + actor.remove_images() actor.page.locator("media-input input[type=file]").set_input_files( files=[ {"name": "one.png", "mimeType": "image/png", "buffer": PNG}, @@ -39,7 +39,7 @@ def test_the_gallerys_first_image_is_the_carousel_and_search_thumbnail(actor: Ac actor.create_mod("master-quest", title="Master Quest") actor.page.goto(f"{actor.app_url}/{actor.handle}/master-quest/settings") - actor.remove_pictures() + actor.remove_images() actor.page.locator("media-input input[type=file]").set_input_files( files=[{"name": "one.png", "mimeType": "image/png", "buffer": PNG}] ) @@ -62,23 +62,23 @@ def test_the_gallerys_first_image_is_the_carousel_and_search_thumbnail(actor: Ac def test_a_mod_with_no_gallery_shows_the_plain_placeholder(actor: Actor, appview: Appview): actor.login() actor.create_mod("master-quest", title="Master Quest") - strip_pictures(appview.database, "master-quest") + strip_images(appview.database, "master-quest") actor.page.reload() expect(actor.page.locator(".mod-image-placeholder")).to_be_visible() expect(actor.page.locator("media-carousel")).to_have_count(0) -def test_a_mod_keeps_at_least_one_picture(actor: Actor): +def test_a_mod_keeps_at_least_one_image(actor: Actor): actor.login() actor.create_mod("master-quest", title="Master Quest") actor.page.goto(f"{actor.app_url}/{actor.handle}/master-quest/settings") - actor.remove_pictures() + actor.remove_images() actor.page.get_by_role("button", name="Save").click() - expect(actor.page.locator("#error-summary")).to_contain_text("Add a picture") - expect(actor.page.locator("#media-error")).to_have_text("Add a picture") + expect(actor.page.locator("#error-summary")).to_contain_text("Add an image") + expect(actor.page.locator("#media-error")).to_have_text("Add an image") [listing] = actor.records(LISTING_COLLECTION) assert len(listing["value"]["media"]) == 1 diff --git a/tests/test_mod_listing.py b/tests/test_mod_listing.py index 5c13461..769c153 100644 --- a/tests/test_mod_listing.py +++ b/tests/test_mod_listing.py @@ -85,13 +85,13 @@ def test_details_render_as_markdown_with_no_html_of_their_own(actor: Actor): expect(actor.page.locator(".mod-card-description")).to_have_text("A very good mod") -def test_sharing_a_mod_publishes_it_with_its_picture_and_first_version(actor: Actor): +def test_sharing_a_mod_publishes_it_with_its_image_and_first_version(actor: Actor): actor.login() actor.create_mod("test-mod") [listing] = actor.records(COLLECTION) - [picture] = listing["value"]["media"] - assert picture["file"]["mimeType"] == "image/png" + [image] = listing["value"]["media"] + assert image["file"]["mimeType"] == "image/png" assert actor.version_record("1.0")["value"]["mod"] == listing["uri"] expect(actor.page.get_by_role("link", name="Download 1.0")).to_be_visible() @@ -106,10 +106,10 @@ def test_a_mod_is_only_shared_whole(actor: Actor): assert summary.locator("li").all_text_contents() == [ "Enter a title", "Select a game", - "Add a picture", + "Add an image", "Select a file or paste a link", ] - expect(actor.page.locator("#media-error")).to_have_text("Add a picture") + expect(actor.page.locator("#media-error")).to_have_text("Add an image") # The server holds to it too, and writes nothing. refused = actor.page.request.post( diff --git a/tests/test_mod_transfer.py b/tests/test_mod_transfer.py index 49a922e..6076aa7 100644 --- a/tests/test_mod_transfer.py +++ b/tests/test_mod_transfer.py @@ -96,7 +96,7 @@ def test_accepting_moves_the_mod_its_versions_and_downloads(actor: Actor, other_ actor.login() actor.create_mod("test-mod") actor.page.goto(f"{actor.app_url}/{actor.handle}/test-mod/settings") - actor.remove_pictures() + actor.remove_images() actor.page.locator("media-input input[type=file]").set_input_files( files=[{"name": "one.png", "mimeType": "image/png", "buffer": PNG}] ) -- 2.51.2