Something went wrong. Try again.
atproto git client
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322//! The assets atgc.codes is built from, which are the ones only this tree//! knows.//!//! The site itself is an Astro project in `www/`, and its markup, copy and//! layout live there, where copy belongs. What lives here is everything the//! page cannot be trusted to write down for itself://!//! - **The facts.** The version `cargo release` computed and the install//! line the README's own test guards, as `facts.json`. A marketing page is//! where a claim about software goes to rot, and these are the two claims//! a stranger acts on.//! - **The look.** `theme.css`, `field.css` and `mark.svg`, written out from//! [`crate::html::brand`] — *the same constants* the OAuth callback page//! is built from. That is the point rather than a convenience: the field//! of DNA behind `atgc auth login` and the field behind atgc.codes are the//! same bytes, because there is one palette in this project and neither//! side gets a copy of it.//! - **The drawings.** `field.html` and `terminal.html` come out of//! [`crate::art`], which is Rust and cannot be anything else: the field is//! nineteen thousand cells of generated art and the terminal is `atgc//! about`'s own rendering rather than a screenshot of it.//! - **The face.** The two Comic Neue weights, copied out so Astro can serve//! them from its own origin.//!//! Everything else — every heading, every feature line, the whole of the//! quickstart — is `.astro` in `www/src`, editable by anybody, with no Rust//! rebuild in the loop.
use crate::art::{self, Canvas, PAD, panel_lines, width_of};use crate::html::brand::{self, Scheme};
/// The one line somebody is meant to leave with. Stated once, here, and/// checked against the README's copy of it by the test at the bottom of this/// file — a second install line outside that check is a second thing to be/// wrong, and the one a stranger reads first. Astro is handed this rather/// than writing its own, and a check refuses any `cargo install` line that/// appears in the site's own sources.const INSTALL: &str = "cargo install --git https://tangled.org/permadeath.com/atgc";
/// Where the source is. Also `CARGO_PKG_REPOSITORY`, which is what the panel/// on the terminal prints, so the two cannot disagree.const REPO: &str = env!("CARGO_PKG_REPOSITORY");
/// Comic Neue, in the two weights the headings use. Compiled in so the/// emitter can write them out wherever Astro wants them; see/// `fonts/README.md` for where the bytes came from, and `fonts/OFL.txt` for/// the licence that lets them be here.const FONT_REGULAR: &[u8] = include_bytes!("fonts/ComicNeue-Regular.woff2");const FONT_BOLD: &[u8] = include_bytes!("fonts/ComicNeue-Bold.woff2");
/// `atgc about`, drawn rather than photographed.////// The epic that asked for this wanted "a repeatable capture — a recorded/// session rendered to an image by a command". This is the shorter answer to/// the same problem: the command's own drawing code, called here, at a frame/// the page picks instead of one a terminal reported. There is no capture to/// re-run after a release and no cropped PNG to go stale, and the version on/// it is the version of the binary that built the page.////// The frame is fixed because a page has no terminal to ask. 88 columns/// leaves the panel about a helix of field either side, and 25 rows is a/// whole number of half turns ([`art::snap_rows`]), so the field is as wide/// along the bottom edge as along the top.const DEMO_COLUMNS: i32 = 88;const DEMO_ROWS: i32 = 25;
fn about_demo() -> String { let lines = panel_lines(); let content = lines.iter().map(width_of).max().unwrap_or(0) as i32; let panel_w = content + 2 * PAD + 2; let panel_h = lines.len() as i32 + 2;
let mut canvas = Canvas::new(DEMO_COLUMNS, DEMO_ROWS); art::draw_field(&mut canvas); art::draw_panel( &mut canvas, (DEMO_COLUMNS - panel_w) / 2, (DEMO_ROWS - panel_h) / 2, panel_w, &lines, ); super::field::panel(&canvas)}
/// The facts the page states and the tree can check, as JSON for Astro to/// read at build time.////// Hand-rolled rather than `serde_json`, because escaping five known strings/// is not worth a derive: every value here is a version, a URL or an ASCII/// command line, and [`escape_json`] holds that.fn facts() -> String { let fields = [ ("version", env!("CARGO_PKG_VERSION")), ("install", INSTALL), ("repo", REPO), ("rustVersion", env!("CARGO_PKG_RUST_VERSION")), ("description", env!("CARGO_PKG_DESCRIPTION")), ]; let body: Vec<String> = fields .iter() .map(|(key, value)| format!(" \"{key}\": \"{}\"", escape_json(value))) .collect(); format!("{{\n{}\n}}\n", body.join(",\n"))}
/// The two characters that can end a JSON string, and the control range./// Everything written through this is a value from `Cargo.toml` or a/// constant above, so this is a guard rather than a parser.fn escape_json(text: &str) -> String { let mut out = String::with_capacity(text.len()); for ch in text.chars() { match ch { '"' => out.push_str("\\\""), '\\' => out.push_str("\\\\"), c if (c as u32) < 0x20 => out.push_str(&format!("\\u{:04x}", c as u32)), c => out.push(c), } } out}
/// Every file the site is built from, as a relative path and its bytes.////// One list, so the command that writes them has no opinions of its own and/// a test can walk the same set the build does.pub(crate) fn assets() -> Vec<(&'static str, Vec<u8>)> { vec![ ("facts.json", facts().into_bytes()), // The look, from the same constants the login page is built from. ( "theme.css", brand::theme_css(Scheme::DarkFirst).into_bytes(), ), ("field.css", brand::FIELD_CSS.as_bytes().to_vec()), ("mark.svg", brand::MARK_SVG.as_bytes().to_vec()), ("favicon.svg", brand::favicon_svg().into_bytes()), // The drawings, which are Rust and cannot be anything else. ("field.html", brand::field_markup().into_bytes()), ("terminal.html", about_demo().into_bytes()), // The face. ("fonts/ComicNeue-Regular.woff2", FONT_REGULAR.to_vec()), ("fonts/ComicNeue-Bold.woff2", FONT_BOLD.to_vec()), ]}
#[cfg(test)]mod tests { use super::*;
/// The install line the page shows is the install line in the README. /// /// This is the whole reason any of this is emitted by the binary rather /// than typed into a `.astro` file: a second copy of the one command a /// stranger types is a second thing to be wrong, and it is the copy they /// read first. The README is included only in a test build. #[test] fn the_install_line_is_the_readme_s() { let readme = include_str!("../../../README.md"); assert!( readme.contains(INSTALL), "the README does not contain {INSTALL:?}" ); assert!(facts().contains(INSTALL), "the facts dropped it"); }
/// The version in the facts is the version of the binary that emitted /// them, which is what makes the page's claim about itself checkable. #[test] fn the_facts_name_the_running_version() { let facts = facts(); assert!(facts.contains(&format!("\"version\": \"{}\"", env!("CARGO_PKG_VERSION")))); assert!(facts.contains(env!("CARGO_PKG_RUST_VERSION")), "no MSRV"); assert!(facts.contains(REPO), "no repo"); // Parseable: every brace and quote balanced, no trailing comma. assert!(facts.starts_with("{\n") && facts.ends_with("}\n")); assert_eq!(facts.matches('"').count() % 2, 0, "odd quote count"); assert!(!facts.contains(",\n}"), "trailing comma"); }
/// A value that would end its own string is escaped rather than trusted. /// Nothing in `Cargo.toml` does this today, which is exactly when a /// guard is worth writing. #[test] fn a_quote_cannot_break_out_of_the_facts() { assert_eq!(escape_json(r#"a"b"#), r#"a\"b"#); assert_eq!(escape_json(r"a\b"), r"a\\b"); assert_eq!(escape_json("a\nb"), "a\\u000ab"); }
/// The site and the login page are drawn from one palette. Not "look the /// same" — the same bytes, because both come from `html::brand`, and a /// second copy of `--a` anywhere is the drift this arrangement exists to /// prevent. #[test] fn the_site_and_the_login_page_share_one_look() { let emitted = |name: &str| { assets() .into_iter() .find(|(path, _)| *path == name) .map(|(_, bytes)| String::from_utf8(bytes).expect("utf-8")) .unwrap_or_else(|| panic!("no {name} in the assets")) }; // The field's stylesheet and the mark go out verbatim. assert_eq!(emitted("field.css"), brand::FIELD_CSS); assert_eq!(emitted("mark.svg"), brand::MARK_SVG); // The palette differs only in which way round the schemes are // declared, and both blocks are in both. let theme = emitted("theme.css"); let login = brand::theme_css(Scheme::System); for block in theme.split("@media") { let vars: Vec<&str> = block .match_indices("--") .map(|(i, _)| &block[i..i + 5]) .collect(); for var in vars { assert!( login.contains(var), "the site declares {var:?} and the login page does not" ); } } // And the field itself is the art, not a picture of it. assert_eq!(emitted("field.html"), brand::field_markup()); }
/// The terminal on the page is `atgc about`'s own drawing: the panel, /// the field it hangs on, and the muted border marked up so it reads /// quieter than the text inside it. #[test] fn the_terminal_is_the_command_and_not_a_picture_of_it() { let demo = about_demo(); assert!(demo.contains("atgc"), "no wordmark in the lid"); assert!(demo.contains('╭') && demo.contains('╯'), "no panel"); assert!(demo.contains("<i class=m>"), "the border is not muted"); assert!(demo.contains(REPO), "no repo line"); // The site line too, which is this page's own address: Astro knows // where it serves from and is handed no fact about it, but the panel // drawn here prints what the command prints. assert!(demo.contains(env!("CARGO_PKG_HOMEPAGE")), "no site line"); assert!( demo.contains(env!("CARGO_PKG_VERSION")), "the demo is stale" ); assert_eq!(demo.lines().count(), DEMO_ROWS as usize); }
/// The site's own sources do not restate a fact the binary emits. /// /// This is the other half of `the_install_line_is_the_readme_s`: that /// one holds the emitted value to the README, and this one stops the /// Astro side quietly typing its own copy beside it. A page that says /// `cargo install …` in an `.astro` file is a page that will still say /// it after the URL changes, and no test would notice. /// /// Skipped when `www/` is not there, which is the packaged crate: the /// tarball ships `src/` and not the site. #[test] fn the_site_does_not_hardcode_what_the_binary_emits() { let root = std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("www/src"); if !root.is_dir() { return; } let mut checked = 0; let mut stack = vec![root]; while let Some(dir) = stack.pop() { for entry in std::fs::read_dir(&dir).expect("read_dir").flatten() { let path = entry.path(); // `generated/` is the binary's own output, and is where // these values are *supposed* to appear. if path.is_dir() { if path.file_name().is_some_and(|n| n == "generated") { continue; } stack.push(path); continue; } if !path .extension() .is_some_and(|e| e == "astro" || e == "ts" || e == "js" || e == "css") { continue; } let text = std::fs::read_to_string(&path).expect("read"); checked += 1; for claim in ["cargo install", env!("CARGO_PKG_VERSION")] { assert!( !text.contains(claim), "{} hardcodes {claim:?}; read it from facts.json instead", path.display() ); } } } assert!(checked > 0, "no site sources were checked"); }
/// Every asset has a path Astro can write to and bytes in it, and the /// set is the one the command writes — nothing is emitted twice and /// nothing escapes the directory it was pointed at. #[test] fn the_asset_list_is_a_set_of_relative_paths() { let assets = assets(); let mut paths: Vec<&str> = assets.iter().map(|(path, _)| *path).collect(); let count = paths.len(); paths.sort_unstable(); paths.dedup(); assert_eq!(paths.len(), count, "an asset is emitted twice"); for (path, bytes) in &assets { assert!(!path.starts_with('/') && !path.contains(".."), "{path}"); assert!(!bytes.is_empty(), "{path} is empty"); } // The two fonts are bytes, not text, and arrive whole. assert_eq!( assets .iter() .find(|(p, _)| p.ends_with("Bold.woff2")) .map(|(_, b)| b.len()), Some(FONT_BOLD.len()) ); }}