diff --git a/.github/ISSUE_TEMPLATE/docs.yml b/.github/ISSUE_TEMPLATE/docs.yml index 5bc9820..3a99de4 100644 --- a/.github/ISSUE_TEMPLATE/docs.yml +++ b/.github/ISSUE_TEMPLATE/docs.yml @@ -1,7 +1,7 @@ name: 📚 Documentation issue description: Something on the site or in the README is missing, wrong, or unclear. title: 'docs: ' -labels: [docs, triage] +labels: [documentation, triage] body: - type: input id: url diff --git a/.github/workflows/links.yml b/.github/workflows/links.yml index 5cb72a6..bd534eb 100644 --- a/.github/workflows/links.yml +++ b/.github/workflows/links.yml @@ -28,15 +28,36 @@ jobs: - name: Collect external URLs from sources run: | mkdir -p lychee - # Allow `)` inside URLs (Wikipedia disambiguation titles), then strip - # a single trailing `)` only when unbalanced (handles markdown - # `[text](url)`). Drop resolver templates containing `{placeholder}`. - # Restrict to YAML/MD so lockfiles inside data/ are not scanned. + # A URL may legitimately contain `(` and `)`, because Wikipedia and + # Wikisource put disambiguation titles there. The match therefore + # keeps parentheses and the trailing markup is trimmed afterwards. + # + # The trim runs as one loop, not as a fixed sequence. A URL at the + # end of a markdown link, a bold run, or a sentence carries several + # layers of trailing markup at once — `…/4.0/).`, `…/arks.org/)**`, + # `…/rfc3987))` — so each pass strips punctuation, then one + # unbalanced `)`, until the string stops changing. Doing this in a + # single pass leaves a `)` behind whenever punctuation follows it, + # which is what produced the false 404s in #3. + # + # Resolver templates are dropped: `{placeholder}` literally, and + # `%7B`/`%7D` for the percent-encoded spelling. + # + # Restrict to YAML/MD, and skip node_modules, so lockfiles and + # dependency READMEs inside data/ are not scanned. grep -rhoE --include='*.yaml' --include='*.yml' --include='*.md' --include='*.mdx' \ + --exclude-dir=node_modules \ 'https?://[^]["'\''<>[:space:]]+' data/ src/content/docs/ \ - | awk '{ n=gsub(/\(/,"&"); m=gsub(/\)/,"&"); if (m>n) sub(/\)$/,""); print }' \ - | grep -v '[{}]' \ - | sed -E 's/[.,;:]+$//' \ + | awk '{ + do { + changed = 0 + if (sub(/[.,;:!?*_`]+$/, "")) changed = 1 + n = gsub(/\(/, "&"); m = gsub(/\)/, "&") + if (m > n && sub(/\)$/, "")) changed = 1 + } while (changed) + if (length($0) > 0) print + }' \ + | grep -viE '[{}]|%7b|%7d' \ | sort -u > lychee/urls.txt echo "Collected $(wc -l < lychee/urls.txt) unique URLs" diff --git a/lychee.toml b/lychee.toml index f2f8688..ff0f57f 100644 --- a/lychee.toml +++ b/lychee.toml @@ -34,6 +34,8 @@ exclude = [ "^https?://([a-z0-9-]+\\.)*twitter\\.com", "^https?://([a-z0-9-]+\\.)*x\\.com", "^https?://([a-z0-9-]+\\.)*opencollective\\.com", + "^https?://([a-z0-9-]+\\.)*iso\\.org", + "^https?://([a-z0-9-]+\\.)*loc\\.gov", "^https?://localhost(:\\d+)?(/|$)", ] diff --git a/src/components/CitationBox.astro b/src/components/CitationBox.astro deleted file mode 100644 index ec1a9a7..0000000 --- a/src/components/CitationBox.astro +++ /dev/null @@ -1,134 +0,0 @@ ---- -import type { - Work, - CanonicalReference, - CitationSystem, -} from '../../standard/schema/index.js'; -import { toCSL, formatChicago, toCOinS } from '../lib/citation.ts'; - -interface Props { - work: Work | undefined; - ref: CanonicalReference; - system: CitationSystem | undefined; -} - -const { work, ref, system } = Astro.props; -const csl = toCSL(work, ref, system); -const chicago = formatChicago(csl); -const coins = toCOinS(csl); -const cslJson = JSON.stringify(csl, null, 2); - -const escapeHtml = (s: string) => - s - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"'); - -const chicagoHtml = escapeHtml(chicago).replace(/\*([^*]+)\*/g, '$1'); ---- - -
-

Cite this reference

-

Chicago (notes-bibliography)

-
- -
- - -
- - - diff --git a/src/components/Tombstone.astro b/src/components/Tombstone.astro index 0a3cd14..a51c744 100644 --- a/src/components/Tombstone.astro +++ b/src/components/Tombstone.astro @@ -6,8 +6,15 @@ interface Props { const { status, supersededBy } = Astro.props; +// ADR-0004 and specification.md §12 make `deprecated`, `withdrawn` and `blocked` +// one tombstone category, and the compiler agrees (`RETIRED_STATUSES` in +// scripts/compile.ts). The three differ in reach, not in kind: a `deprecated` +// record is retained and still resolves, while a `withdrawn` or `blocked` record +// is additionally excluded from `Work` mapping projections. The banner therefore +// stays one presentation, and the copy below states which of the three applies. const isDraft = status === 'draft'; -const isTombstone = status === 'withdrawn' || status === 'blocked'; +const isTombstone = + status === 'deprecated' || status === 'withdrawn' || status === 'blocked'; --- { @@ -33,9 +40,16 @@ const isTombstone = status === 'withdrawn' || status === 'blocked'; {status === 'blocked' ? 'This record is blocked by a rights, trust, or policy dispute.' - : 'This record has been withdrawn.'} + : status === 'deprecated' + ? 'This record is deprecated.' + : 'This record has been withdrawn.'}

+ {status === 'deprecated' && ( +

+ It is retained and it still resolves, but it is no longer recommended. +

+ )} {supersededBy ? (

Superseded by {supersededBy}. diff --git a/src/pages/id/ref/[uuid]/index.astro b/src/pages/id/ref/[uuid]/index.astro index 1a55f99..d7a47cd 100644 --- a/src/pages/id/ref/[uuid]/index.astro +++ b/src/pages/id/ref/[uuid]/index.astro @@ -81,8 +81,18 @@ const escapeHtml = (s: string) => .replace(/"/g, '"'); const chicagoHtml = escapeHtml(chicago).replace(/\*([^*]+)\*/g, '$1'); +// ADR-0004 and specification.md §12 make `deprecated`, `withdrawn` and `blocked` +// one tombstone category, and the compiler agrees (`RETIRED_STATUSES` in +// scripts/compile.ts). The three differ in reach, not in kind: a `deprecated` +// record is retained and still resolves, while a `withdrawn` or `blocked` record +// is additionally excluded from `Work` mapping projections. The banner therefore +// stays one presentation, and the copy below states which of the three applies. +// Kept in step with src/components/Tombstone.astro by hand until #100 lands. const isDraft = ref.status === 'draft'; -const isTombstone = ref.status === 'withdrawn' || ref.status === 'blocked'; +const isTombstone = + ref.status === 'deprecated' || + ref.status === 'withdrawn' || + ref.status === 'blocked'; --- {ref.status === 'blocked' ? 'This record is blocked by a rights, trust, or policy dispute.' - : 'This record has been withdrawn.'} + : ref.status === 'deprecated' + ? 'This record is deprecated.' + : 'This record has been withdrawn.'}

+ {ref.status === 'deprecated' && ( +

+ It is retained and it still resolves, but it is no longer + recommended. +

+ )} {ref.superseded_by ? (

Superseded by {ref.superseded_by}.