docs: the repository of its own: licences, CI, citations checked in form (P13 step 6)
spec/ and examples/ are CC BY 4.0, the code MIT OR Apache-2.0. The verbatim-pin and rules.md-id checks need wanderbooks' vendored sources and rules.md, so they move to wanderbooks; here a citation is checked in form. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
1 parent
82b53945c9
commit
fc4430c685
8 files changed
+678
-63
No files matched your search
@@ -1,28 +0,0 @@
|
||||
//! The documentation bookspec's identifiers live in: `docs/spec/rules.md`
|
||||
//! carries each stated rule's id and speaks bookspec's `CHOICE`.
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use bookspec_checker::rules;
|
||||
|
||||
/// `docs/spec/rules.md` carries every stated rule's id under its heading,
|
||||
/// and no longer calls a choice a decision (P13 step 3).
|
||||
#[test]
|
||||
fn rules_md_carries_every_id() {
|
||||
let text = std::fs::read_to_string(
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../docs/spec/rules.md"),
|
||||
)
|
||||
.expect("docs/spec/rules.md");
|
||||
for rule in rules().iter().filter(|r| r.status.is_some()) {
|
||||
assert!(
|
||||
text.contains(&format!("**bookspec:** `{}`", rule.id)),
|
||||
"B-{} carries {}",
|
||||
rule.b,
|
||||
rule.id
|
||||
);
|
||||
}
|
||||
assert!(
|
||||
!text.contains("DECISION"),
|
||||
"rules.md speaks bookspec's CHOICE"
|
||||
);
|
||||
}
|
||||
+9
-22
@@ -11,10 +11,6 @@ fn spec_dir() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("../spec")
|
||||
}
|
||||
|
||||
fn sources_dir() -> PathBuf {
|
||||
Path::new(env!("CARGO_MANIFEST_DIR")).join("../../docs/spec/sources")
|
||||
}
|
||||
|
||||
/// A rule's section as the text gives it.
|
||||
#[derive(Default, Debug)]
|
||||
struct Section {
|
||||
@@ -86,15 +82,6 @@ fn one<'a>(s: &'a Section, id: &str, field: &str) -> &'a str {
|
||||
&v[0]
|
||||
}
|
||||
|
||||
/// Whitespace and typographic quotes made plain, so a pin copied from a
|
||||
/// wrapped or curly-quoted source still matches.
|
||||
fn squash(s: &str) -> String {
|
||||
let plain = s
|
||||
.replace(['\u{2019}', '\u{2018}'], "'")
|
||||
.replace(['\u{201c}', '\u{201d}'], "\"");
|
||||
plain.split_whitespace().collect::<Vec<_>>().join(" ")
|
||||
}
|
||||
|
||||
fn backticked(s: &str) -> Vec<&str> {
|
||||
s.split('`').skip(1).step_by(2).collect()
|
||||
}
|
||||
@@ -178,8 +165,9 @@ fn the_examples_are_the_catalogues() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Every citation resolves: a vendored source exists, and a verbatim
|
||||
/// pin appears in it; an external reference names its paragraph.
|
||||
/// Every citation is well formed: a vendored source names its file and a
|
||||
/// pin (checked verbatim by the consumer); an external reference names its
|
||||
/// paragraph.
|
||||
#[test]
|
||||
fn every_citation_resolves() {
|
||||
let sections = sections();
|
||||
@@ -203,15 +191,14 @@ fn every_citation_resolves() {
|
||||
let (file, rest) = rest
|
||||
.split_once("`:")
|
||||
.unwrap_or_else(|| panic!("{id}: {item}"));
|
||||
let path = sources_dir().join(file.strip_prefix("sources/").unwrap_or(file));
|
||||
let text = std::fs::read_to_string(&path)
|
||||
.unwrap_or_else(|_| panic!("{id}: {file} is not vendored"));
|
||||
let hay = squash(&text);
|
||||
// Every quoted pin is verbatim in the file.
|
||||
// The vendored texts live with the consumer (wanderbooks'
|
||||
// `docs/spec/sources`), which checks each pin verbatim;
|
||||
// here a citation names its file and quotes a pin.
|
||||
assert!(file.ends_with(".md"), "{id}: {file}");
|
||||
let quoted: Vec<&str> = rest.split('"').skip(1).step_by(2).collect();
|
||||
for q in "ed {
|
||||
if !hay.contains(&squash(q)) {
|
||||
bad.push(format!("{id}: {q:?} is not in {file}"));
|
||||
if q.trim().is_empty() {
|
||||
bad.push(format!("{id}: an empty pin in {file}"));
|
||||
}
|
||||
}
|
||||
if quoted.is_empty() {
|
||||
|
||||
Reference in new issue
Block a user