pandorga 1.7.3 → 1.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/_includes/content-runtime/60-fragments.html +1 -1
- data/assets/css/ledger/detail.css +9 -28
- data/assets/css/ledger/footer.css +5 -2
- data/assets/css/ledger/home.css +1 -2
- data/lib/pandorga/commands/new.rb +1 -1
- data/lib/pandorga/version.rb +1 -1
- data/scripts/content/band_art.rb +1 -1
- data/scripts/content/export-content-json.rb +1 -1
- data/scripts/test/test-css-structure.rb +5 -0
- data/scripts/test/test-home-band-art.rb +1 -1
- data/scripts/test/test-new.rb +40 -0
- data/scripts/test/test-r2-config-consistency.rb +1 -1
- data/scripts/test/test-theme-contrast.rb +21 -1
- metadata +1 -3
- data/scripts/content/backfill-content-keys.rb +0 -99
- data/scripts/test/test-cloudflare-watch-paths-doc.rb +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8935cbf5ca2ee93ea990c5e18d61831877f04f03b3ba569b3d4347dec3387718
|
|
4
|
+
data.tar.gz: 5c9663302fcce8b2ecf4a5197b03ca66f1f0cca0c7eb2ee0b9d9c9ab2d5e320e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ba771e313ba7ecbc5d13473c75454468d22d18f6f2ec1d22ca896d3bf9bec124aa9b32f5efff0dce38c7495a20a422110313910d56808f7b123ce4e07b29e322
|
|
7
|
+
data.tar.gz: b29d2e32efc698af41f0fdcf7b9da605adfbc238a249dd050c157103493b9305e9fb71a355f919e8189a4a43d41b76b25df2a96b446627a3ba6380f6631fc1f5
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.7.4] — 2026-10-12
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- The footer imprint separator uses `outline` on the panel step.
|
|
8
|
+
`outline-variant` on that panel is 1.80:1 in light (`#b8b8b8` on
|
|
9
|
+
`#f4f4f4`) and 1.93:1 in dark (`#45454c` on `#141418`). `outline`
|
|
10
|
+
on the same panels is 6.08:1 and 5.95:1.
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Unused selectors are gone. `assets/css/ledger/home.css` drops
|
|
15
|
+
`.home-hero-pandorga-svg` (25 bytes). The hero SVG uses
|
|
16
|
+
`home-hero-art-svg`. `assets/css/ledger/detail.css` drops 916 bytes:
|
|
17
|
+
the author byline suppressor and the `.table-csv` companions. No
|
|
18
|
+
template or runtime emits either class. 941 bytes in all.
|
|
19
|
+
- The one-shot key backfill is gone (`scripts/content/backfill-content-keys.rb`,
|
|
20
|
+
3,432 bytes). Nothing called it.
|
|
21
|
+
- The watch-path test that read `docs/ops/cloudflare.md` is gone
|
|
22
|
+
(1,230 bytes). That path is not in the tree.
|
|
23
|
+
- Deploy notes pin `~> 1.3` and tag `v1.7.4`. The Pages watch paths
|
|
24
|
+
include `*` and exclude `content/*` and `docs/*`.
|
|
25
|
+
|
|
26
|
+
No `pandorga:` config keys were added or renamed. Font roles and the
|
|
27
|
+
ledger fallbacks are unchanged.
|
|
28
|
+
|
|
3
29
|
## [1.7.3] — 2026-10-12
|
|
4
30
|
|
|
5
31
|
### Fixed
|
|
@@ -385,7 +385,7 @@
|
|
|
385
385
|
}
|
|
386
386
|
|
|
387
387
|
/* The home page's reference band opens each panel with a plate drawn from
|
|
388
|
-
* that section's own content by the export (docs/
|
|
388
|
+
* that section's own content by the export (docs/deploy/cloudflare.md).
|
|
389
389
|
* The markup arrives as an SVG document and is injected inline, never as an
|
|
390
390
|
* <img>: every stroke and fill in it is a custom property, and an external
|
|
391
391
|
* document cannot see the palette the page is currently wearing.
|
|
@@ -485,11 +485,9 @@ aside:has(> .text-detail-sidebar) {
|
|
|
485
485
|
font-variant-numeric: tabular-nums;
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
-
/* Projects and products can carry no meta at all
|
|
489
|
-
the byline below is the block's only child. Either way an all-empty meta
|
|
488
|
+
/* Projects and products can carry no meta at all. An all-empty meta
|
|
490
489
|
block must not hang a stub of padding off the bottom of the panel. */
|
|
491
|
-
.text-detail-sidebar .article-meta:has(> div:empty)
|
|
492
|
-
.text-detail-sidebar .article-meta:has(> div > span.text-secondary:not(.font-bold):only-child) {
|
|
490
|
+
.text-detail-sidebar .article-meta:has(> div:empty) {
|
|
493
491
|
display: none;
|
|
494
492
|
}
|
|
495
493
|
|
|
@@ -497,14 +495,6 @@ aside:has(> .text-detail-sidebar) {
|
|
|
497
495
|
gap: var(--space-sm);
|
|
498
496
|
}
|
|
499
497
|
|
|
500
|
-
/* Author byline. Dropped: single-author site. The runtime still emits it, so
|
|
501
|
-
it is suppressed here until `buildTextSidebar` stops rendering it — see the
|
|
502
|
-
runtime-change note in this branch's commit message. The product/company
|
|
503
|
-
line is the same colour but carries `font-bold`, hence the :not(). */
|
|
504
|
-
.text-detail-sidebar .article-meta>div>span.text-secondary:not(.font-bold) {
|
|
505
|
-
display: none;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
498
|
.text-detail-sidebar .article-meta .text-tertiary,
|
|
509
499
|
.text-detail-sidebar .article-meta span.font-bold {
|
|
510
500
|
font-family: var(--font-label);
|
|
@@ -861,8 +851,7 @@ aside:has(> .text-detail-sidebar) {
|
|
|
861
851
|
header, and figures that line up. */
|
|
862
852
|
/* No table surface: the header band and the hover row are the only fills, so
|
|
863
853
|
both read against the page canvas in either palette. */
|
|
864
|
-
.article-content table
|
|
865
|
-
.article-content .table-csv {
|
|
854
|
+
.article-content table {
|
|
866
855
|
margin: var(--space-xl) 0;
|
|
867
856
|
font-size: var(--type-dek);
|
|
868
857
|
font-variant-numeric: tabular-nums;
|
|
@@ -870,9 +859,7 @@ aside:has(> .text-detail-sidebar) {
|
|
|
870
859
|
}
|
|
871
860
|
|
|
872
861
|
.article-content th,
|
|
873
|
-
.article-content td
|
|
874
|
-
.article-content .table-csv th,
|
|
875
|
-
.article-content .table-csv td {
|
|
862
|
+
.article-content td {
|
|
876
863
|
border: 0;
|
|
877
864
|
border-bottom: 1px solid var(--border-gentle-subtle);
|
|
878
865
|
padding: var(--space-sm) var(--space-md);
|
|
@@ -899,8 +886,7 @@ aside:has(> .text-detail-sidebar) {
|
|
|
899
886
|
font-variant-numeric: tabular-nums;
|
|
900
887
|
}
|
|
901
888
|
|
|
902
|
-
.article-content thead th
|
|
903
|
-
.article-content .table-csv thead th {
|
|
889
|
+
.article-content thead th {
|
|
904
890
|
background: var(--color-surface-container);
|
|
905
891
|
font-family: var(--font-body);
|
|
906
892
|
font-size: var(--type-body);
|
|
@@ -910,13 +896,11 @@ aside:has(> .text-detail-sidebar) {
|
|
|
910
896
|
}
|
|
911
897
|
|
|
912
898
|
/* Zebra striping fights the row rules; the hover row is the reading aid. */
|
|
913
|
-
.article-content tbody tr:nth-child(even)
|
|
914
|
-
.article-content .table-csv tbody tr:nth-child(even) td {
|
|
899
|
+
.article-content tbody tr:nth-child(even) {
|
|
915
900
|
background: transparent;
|
|
916
901
|
}
|
|
917
902
|
|
|
918
|
-
.article-content tbody tr:hover
|
|
919
|
-
.article-content .table-csv tbody tr:hover {
|
|
903
|
+
.article-content tbody tr:hover {
|
|
920
904
|
background: var(--color-surface-container-low);
|
|
921
905
|
}
|
|
922
906
|
|
|
@@ -1131,8 +1115,7 @@ nav.text-page-nav:not(:has(a)) {
|
|
|
1131
1115
|
too wide then scrolls inside the table rather than moving the page. The
|
|
1132
1116
|
runtime emits the table with no wrapper, so the table itself has to be the
|
|
1133
1117
|
scroll container. */
|
|
1134
|
-
.article-content table
|
|
1135
|
-
.article-content .table-csv {
|
|
1118
|
+
.article-content table {
|
|
1136
1119
|
display: block;
|
|
1137
1120
|
width: 100%;
|
|
1138
1121
|
max-width: 100%;
|
|
@@ -1140,9 +1123,7 @@ nav.text-page-nav:not(:has(a)) {
|
|
|
1140
1123
|
}
|
|
1141
1124
|
|
|
1142
1125
|
.article-content th,
|
|
1143
|
-
.article-content td
|
|
1144
|
-
.article-content .table-csv th,
|
|
1145
|
-
.article-content .table-csv td {
|
|
1126
|
+
.article-content td {
|
|
1146
1127
|
padding: var(--space-xs) var(--space-sm);
|
|
1147
1128
|
}
|
|
1148
1129
|
}
|
|
@@ -230,11 +230,14 @@
|
|
|
230
230
|
}
|
|
231
231
|
|
|
232
232
|
/* A middot between items rather than a separator element, so an absent
|
|
233
|
-
license leaves no orphaned punctuation behind.
|
|
233
|
+
license leaves no orphaned punctuation behind. outline-variant is the
|
|
234
|
+
hairline token: #b8b8b8 on #f4f4f4 is 1.80:1, and #45454c on #141418
|
|
235
|
+
is 1.93:1. outline clears 4.5:1 on the same panel (6.08:1 light,
|
|
236
|
+
5.95:1 dark). */
|
|
234
237
|
.site-footer-imprint-item+.site-footer-imprint-item::before {
|
|
235
238
|
content: "·";
|
|
236
239
|
margin-right: var(--space-md);
|
|
237
|
-
color: var(--color-outline
|
|
240
|
+
color: var(--color-outline);
|
|
238
241
|
}
|
|
239
242
|
|
|
240
243
|
.site-footer-imprint-link {
|
data/assets/css/ledger/home.css
CHANGED
|
@@ -24,7 +24,7 @@ module Pandorga
|
|
|
24
24
|
|
|
25
25
|
gem "pandorga", "~> 1.3"
|
|
26
26
|
# Local checkout: gem "pandorga", path: "../pandorga"
|
|
27
|
-
# GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.
|
|
27
|
+
# GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.7.4"
|
|
28
28
|
gem "csv"
|
|
29
29
|
gem "base64"
|
|
30
30
|
RUBY
|
data/lib/pandorga/version.rb
CHANGED
data/scripts/content/band_art.rb
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
# because the plates went stale otherwise. Cloudflare Pages excludes `content/*`
|
|
28
28
|
# from its build watch paths, so a Studio save never rebuilds the shell, and art
|
|
29
29
|
# committed into a layout is art that stops counting the day it is written. See
|
|
30
|
-
# docs/
|
|
30
|
+
# docs/deploy/cloudflare.md.
|
|
31
31
|
#
|
|
32
32
|
# The output is SVG whose every stroke and fill is a custom property, because the
|
|
33
33
|
# site has two complete palettes and switches between them on a `data-theme`
|
|
@@ -653,7 +653,7 @@ def export_derived_data(content_root, output_root)
|
|
|
653
653
|
end
|
|
654
654
|
|
|
655
655
|
# The home page's reference band, drawn from the corpus this run just exported
|
|
656
|
-
# rather than from committed markup. See docs/
|
|
656
|
+
# rather than from committed markup. See docs/deploy/cloudflare.md for why
|
|
657
657
|
# it lives here: a Studio save never rebuilds the shell, so art baked into a
|
|
658
658
|
# layout stops counting the day it is written.
|
|
659
659
|
def export_band_art(output_root, writing_index)
|
|
@@ -86,7 +86,12 @@ sheets.each do |path|
|
|
|
86
86
|
home-index-shard--gamma
|
|
87
87
|
home-index-note
|
|
88
88
|
post-content
|
|
89
|
+
home-hero-pandorga-svg
|
|
90
|
+
table-csv
|
|
89
91
|
]
|
|
92
|
+
if cleaned.include?("span.text-secondary:not(.font-bold)")
|
|
93
|
+
errors << "#{relative}: author byline suppressor matches no markup"
|
|
94
|
+
end
|
|
90
95
|
retired.each do |name|
|
|
91
96
|
next unless cleaned.match?(/[.#]#{Regexp.escape(name)}\b/)
|
|
92
97
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
# Home band art
|
|
4
|
+
# Home band art. Watch paths: docs/deploy/cloudflare.md.
|
|
5
5
|
#
|
|
6
6
|
# AC-BAND-01 the export writes both plates under data/
|
|
7
7
|
# AC-BAND-03 a second export with no content change reports them unchanged
|
data/scripts/test/test-new.rb
CHANGED
|
@@ -32,6 +32,46 @@ if readme.include?("once 1.1 is on RubyGems")
|
|
|
32
32
|
exit 1
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
+
version = ROOT.join("lib/pandorga/version.rb").read[/VERSION = "([^"]+)"/, 1]
|
|
36
|
+
unless version
|
|
37
|
+
warn "FAIL test-new: Pandorga::VERSION missing"
|
|
38
|
+
exit 1
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
deploy = ROOT.join("docs/deploy/cloudflare.md").read
|
|
42
|
+
upgrading = ROOT.join("docs/upgrading.md").read
|
|
43
|
+
scaffold = ROOT.join("lib/pandorga/commands/new.rb").read
|
|
44
|
+
[
|
|
45
|
+
[deploy, "docs/deploy/cloudflare.md"],
|
|
46
|
+
[upgrading, "docs/upgrading.md"],
|
|
47
|
+
[scaffold, "lib/pandorga/commands/new.rb"]
|
|
48
|
+
].each do |text, label|
|
|
49
|
+
if text.include?("v1.0.0") || text.include?("v1.3.11") || text.include?("v1.5.0")
|
|
50
|
+
warn "FAIL test-new: #{label} still names a stale release pin"
|
|
51
|
+
exit 1
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
unless deploy.include?('~> 1.3') && deploy.include?(%(tag: "v#{version}"))
|
|
55
|
+
warn "FAIL test-new: deploy doc must pin ~> 1.3 and tag v#{version}"
|
|
56
|
+
exit 1
|
|
57
|
+
end
|
|
58
|
+
unless deploy.include?("content/*") && deploy.include?("docs/*") && deploy.include?("Gemfile.lock")
|
|
59
|
+
warn "FAIL test-new: deploy doc lost the watch-path include and excludes"
|
|
60
|
+
exit 1
|
|
61
|
+
end
|
|
62
|
+
unless deploy.include?("3.4.4") && deploy.include?("SKIP_DEPENDENCY_INSTALL")
|
|
63
|
+
warn "FAIL test-new: deploy doc lost the Pages Ruby pin or SKIP_DEPENDENCY_INSTALL"
|
|
64
|
+
exit 1
|
|
65
|
+
end
|
|
66
|
+
unless upgrading.include?(%(tag: "v#{version}")) && upgrading.include?("pandorga-#{version}.gem")
|
|
67
|
+
warn "FAIL test-new: upgrading examples are not v#{version}"
|
|
68
|
+
exit 1
|
|
69
|
+
end
|
|
70
|
+
unless scaffold.include?(%(tag: "v#{version}"))
|
|
71
|
+
warn "FAIL test-new: scaffold comment is not tag v#{version}"
|
|
72
|
+
exit 1
|
|
73
|
+
end
|
|
74
|
+
|
|
35
75
|
FileUtils.rm_rf(DEST)
|
|
36
76
|
|
|
37
77
|
stdout, stderr, status = run_new(DEST.to_s)
|
|
@@ -36,7 +36,7 @@ end
|
|
|
36
36
|
|
|
37
37
|
if ContentStorageConfig.placeholder?(base)
|
|
38
38
|
puts "SKIP: R2 URL alignment checks (content_api_base_url is still placeholder: #{base})"
|
|
39
|
-
puts " Fill the URL per docs/
|
|
39
|
+
puts " Fill the URL per docs/deploy/cloudflare.md before production cutover."
|
|
40
40
|
exit 0
|
|
41
41
|
end
|
|
42
42
|
|
|
@@ -40,4 +40,24 @@ fail!("dark tertiary container moved") unless background.casecmp("#6a684f").zero
|
|
|
40
40
|
ratio = contrast(foreground, background)
|
|
41
41
|
fail!("#{foreground} on #{background} is #{ratio.round(2)}:1") unless ratio >= 4.5
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
# Footer imprint middot. outline-variant is a hairline and fails as ink
|
|
44
|
+
# on the panel step. The separator uses outline, which clears 4.5:1.
|
|
45
|
+
footer = ROOT.join("assets/css/ledger/footer.css").read
|
|
46
|
+
fail!("footer imprint separator still uses outline-variant") if footer.include?("color: var(--color-outline-variant)")
|
|
47
|
+
fail!("footer imprint separator lost outline") unless footer.include?("color: var(--color-outline)")
|
|
48
|
+
|
|
49
|
+
light = YAML.safe_load(ROOT.join("_data/themes/light.yml").read) || {}
|
|
50
|
+
pairs = {
|
|
51
|
+
"light" => [light.dig("neutrals", "outline"), light.dig("neutrals", "panel_contrast")],
|
|
52
|
+
"dark" => [dark.dig("neutrals", "outline"), dark.dig("neutrals", "panel_contrast")]
|
|
53
|
+
}
|
|
54
|
+
reports = []
|
|
55
|
+
pairs.each do |name, (ink, panel)|
|
|
56
|
+
fail!("#{name} outline or panel missing") if ink.to_s.empty? || panel.to_s.empty?
|
|
57
|
+
|
|
58
|
+
pair_ratio = contrast(ink, panel)
|
|
59
|
+
fail!("#{name} outline #{ink} on panel #{panel} is #{pair_ratio.round(2)}:1") unless pair_ratio >= 4.5
|
|
60
|
+
reports << "#{name} #{ink} on #{panel} = #{pair_ratio.round(2)}:1"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
puts "PASS test-theme-contrast (#{foreground} on #{background} = #{ratio.round(2)}:1; #{reports.join('; ')})"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: pandorga
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.7.
|
|
4
|
+
version: 1.7.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -328,7 +328,6 @@ files:
|
|
|
328
328
|
- lib/pandorga/version.rb
|
|
329
329
|
- scripts/cdn-allowlist.json
|
|
330
330
|
- scripts/check_home_lists.mjs
|
|
331
|
-
- scripts/content/backfill-content-keys.rb
|
|
332
331
|
- scripts/content/band_art.rb
|
|
333
332
|
- scripts/content/export-content-json.rb
|
|
334
333
|
- scripts/content/flatten-ansi-capture.mjs
|
|
@@ -405,7 +404,6 @@ files:
|
|
|
405
404
|
- scripts/test/render-parity/youtube.json
|
|
406
405
|
- scripts/test/test-absent-field-absent-element.rb
|
|
407
406
|
- scripts/test/test-cdn-pins.rb
|
|
408
|
-
- scripts/test/test-cloudflare-watch-paths-doc.rb
|
|
409
407
|
- scripts/test/test-configuration-doc.rb
|
|
410
408
|
- scripts/test/test-content-backend.rb
|
|
411
409
|
- scripts/test/test-content-detail-urls.rb
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require "pathname"
|
|
5
|
-
require "yaml"
|
|
6
|
-
|
|
7
|
-
require_relative "../../_plugins/content_keys"
|
|
8
|
-
require_relative "../../_plugins/content_detail_paths"
|
|
9
|
-
require_relative "../../_plugins/git_chronology"
|
|
10
|
-
|
|
11
|
-
REPO_ROOT = Pathname.new(__dir__).join("..", "..").expand_path
|
|
12
|
-
CONTENT_ROOT = REPO_ROOT.join("content")
|
|
13
|
-
|
|
14
|
-
KEY_OVERRIDES = {
|
|
15
|
-
"content/collections/posts/2026-03-06-horse-auto-follow.md" => "horse-auto-follow-pt",
|
|
16
|
-
"content/collections/posts/2026-03-02-mcmc.md" => "mcmc-pt"
|
|
17
|
-
}.freeze
|
|
18
|
-
|
|
19
|
-
def split_front_matter(text)
|
|
20
|
-
ContentKeys.split_front_matter(text)
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def write_front_matter(path, front_matter, body)
|
|
24
|
-
yaml = front_matter.to_yaml.sub(/\A---\n/, "").strip
|
|
25
|
-
path.write("---\n#{yaml}\n---\n\n#{body}")
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def infer_key(entry)
|
|
29
|
-
override = KEY_OVERRIDES[entry["repo_relative_path"]]
|
|
30
|
-
return override if override
|
|
31
|
-
|
|
32
|
-
key = ContentKeys.normalize_key(entry["key"])
|
|
33
|
-
return key unless key.empty?
|
|
34
|
-
|
|
35
|
-
ContentKeys.infer_key_from_filename(entry["path"], entry["type"])
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def legacy_detail_path(type, legacy_segment)
|
|
39
|
-
case type
|
|
40
|
-
when "article" then ContentDetailPaths.article_detail_path(legacy_segment)
|
|
41
|
-
when "post" then ContentDetailPaths.post_detail_path(legacy_segment)
|
|
42
|
-
when "project" then ContentDetailPaths.project_detail_path(legacy_segment)
|
|
43
|
-
when "product" then ContentDetailPaths.product_detail_path(legacy_segment)
|
|
44
|
-
else
|
|
45
|
-
raise "unknown type #{type}"
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def migrate_redirect_fields!(front_matter)
|
|
50
|
-
redirects = ContentKeys.normalize_redirects(front_matter)
|
|
51
|
-
front_matter.delete("redirect_from")
|
|
52
|
-
front_matter["redirects"] = redirects unless redirects.empty?
|
|
53
|
-
front_matter
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
def ensure_legacy_redirect!(front_matter, type, legacy_segment, canonical_path)
|
|
57
|
-
redirects = ContentKeys.normalize_redirects(front_matter)
|
|
58
|
-
legacy = legacy_detail_path(type, legacy_segment).chomp("/")
|
|
59
|
-
canonical = canonical_path.chomp("/")
|
|
60
|
-
redirects << legacy unless legacy == canonical
|
|
61
|
-
redirects = redirects.map { |path| ContentKeys.normalize_redirect_path(path) }.compact.uniq
|
|
62
|
-
front_matter["redirects"] = redirects unless redirects.empty?
|
|
63
|
-
front_matter.delete("redirects") if redirects.empty?
|
|
64
|
-
front_matter
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
updated = 0
|
|
68
|
-
ContentKeys::CONTENT_PATHS.each do |type, relative_dir|
|
|
69
|
-
directory = CONTENT_ROOT.join(relative_dir.sub(%r{\Acontent/}, ""))
|
|
70
|
-
next unless directory.directory?
|
|
71
|
-
|
|
72
|
-
Dir.glob(directory.join("*.{md,markdown}")).sort.each do |absolute_path|
|
|
73
|
-
entry = ContentKeys.load_entry(absolute_path, type, repo_root: REPO_ROOT)
|
|
74
|
-
text = File.read(absolute_path).sub(/\A\xEF\xBB\xBF/, "")
|
|
75
|
-
front_matter, body = split_front_matter(text)
|
|
76
|
-
original_yaml = front_matter.to_yaml
|
|
77
|
-
|
|
78
|
-
key = infer_key(entry)
|
|
79
|
-
front_matter["key"] = key
|
|
80
|
-
migrate_redirect_fields!(front_matter)
|
|
81
|
-
|
|
82
|
-
if %w[article post].include?(type)
|
|
83
|
-
GitChronology.apply!(front_matter, entry["repo_relative_path"], type)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
canonical = ContentKeys.detail_path(type, key, date: front_matter["date"])
|
|
87
|
-
ensure_legacy_redirect!(front_matter, type, entry["legacy_segment"], canonical)
|
|
88
|
-
|
|
89
|
-
next if front_matter.to_yaml == original_yaml
|
|
90
|
-
|
|
91
|
-
write_front_matter(Pathname(absolute_path), front_matter, body.sub(/\A\n+/, ""))
|
|
92
|
-
updated += 1
|
|
93
|
-
puts "updated #{entry['repo_relative_path']} (key=#{key})"
|
|
94
|
-
end
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
ContentKeys.validate!(REPO_ROOT)
|
|
98
|
-
ContentKeys.sync_redirects_file!(REPO_ROOT)
|
|
99
|
-
puts "Backfill complete (#{updated} file(s) updated). Redirects synced to _redirects."
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
require "pathname"
|
|
5
|
-
|
|
6
|
-
ROOT = Pathname.new(__dir__).join("..", "..").expand_path
|
|
7
|
-
DOC = ROOT.join("docs/ops/cloudflare.md")
|
|
8
|
-
|
|
9
|
-
def check!(condition, message = "condition was false")
|
|
10
|
-
raise "Assertion failed: #{message}" unless condition
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
text = DOC.read
|
|
14
|
-
|
|
15
|
-
puts "Testing Cloudflare watch paths documentation..."
|
|
16
|
-
|
|
17
|
-
check! text.include?("`*`"), "missing include pattern `*`"
|
|
18
|
-
check! text.include?("`content/*`"), "missing exclude pattern content/*"
|
|
19
|
-
check! text.include?("`docs/*`"), "missing exclude pattern docs/*"
|
|
20
|
-
check! text.include?("Settings → Build → Build watch paths"),
|
|
21
|
-
"missing dashboard navigation path"
|
|
22
|
-
check! text.include?("SKIP_DEPENDENCY_INSTALL"),
|
|
23
|
-
"missing SKIP_DEPENDENCY_INSTALL (avoids Pages pip install of study deps)"
|
|
24
|
-
check! text.include?("bundle install") && text.include?("jekyll build"),
|
|
25
|
-
"missing lean Pages build command with explicit bundle install"
|
|
26
|
-
check! text.include?("pandorga install-functions"),
|
|
27
|
-
"missing pandorga install-functions in Pages build command (PLT-0.2)"
|
|
28
|
-
check! text.include?("3.4.4"),
|
|
29
|
-
"missing Pages v3 Ruby 3.4.4 pin (avoids compiling Ruby from source)"
|
|
30
|
-
|
|
31
|
-
puts "Cloudflare watch paths documentation OK."
|