pandorga 1.5.0 → 1.5.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: eab1ea9696bdf99c28026f135762061c5a627ea398df5ddd8080f2d10dd9abc7
4
- data.tar.gz: 89b13dcd397f666cf5660845d7ffece69478d6275b1d821d9500a4bf08046e5b
3
+ metadata.gz: c33cb11f60569d5280aa7079b6f59ad7776f90705f54f67d958d8b149390714d
4
+ data.tar.gz: 4a52dcb27be1f4d2a809417bc9b98e89e3c8aa8d92e642fca9ebab156942a192
5
5
  SHA512:
6
- metadata.gz: e83aceb1f79cdd9f3ab201315b19532f3182cad64ed34ac4ed285be49f4257e4038a672aada1e6b7ce6b2ce7fb837749fc3eeb4347b99687f07fc2a33a8a6367
7
- data.tar.gz: 7d987a05926fa2d9653faf04fc66585219430e57cd12d5383421aa9a32fcb6b1a52831fa4576f321e5392e482d6128bf4755cb36e237eb6ae8a1788f086848e3
6
+ metadata.gz: ecf8762ab684b723db57bb8d291609a3decf8ecae02f21b0158c3fd34afce67b9a34347255e790e26d480e8ef0b2eaab577dbe3d6ed571a02ce713cc5a2e09d9
7
+ data.tar.gz: 0c30da38132b4b87f2caf982a73f7c8eea1cf157600ecffb9b6f87e24fe289a47952fe3f9c8291c11719531a90cabd0149db89ba13b076c341a4eafabd6577b5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.5.1] — 2026-10-10
4
+
5
+ ### Fixed
6
+
7
+ - The shell has a "Skip to content" link. When `site.author` is blank, the
8
+ home link's accessible name uses `pandorga.identity.name`, then the top-bar
9
+ wordmark, instead of a bare dash. The footer wordmark uses the same
10
+ fallback. A site that sets `site.author` is unchanged.
11
+ - `pandorga doctor` says when `pandorga.pages` is missing, and says when the
12
+ list is empty.
13
+ - `./scripts/validate.sh` fails if a listed gate file is missing.
14
+
15
+ ### Changed
16
+
17
+ - Getting started and the README name the scaffold pin `~> 1.3`.
18
+ - `pandorga new` comments the `v1.5.0` tag.
19
+ - Home CSS drops an empty `@media (min-width: 768px)` block and the unused
20
+ `.home-profile-summary` rules.
21
+ - Chord chart and transcript include comments are English. The visible
22
+ transcript labels are unchanged.
23
+
24
+ No `pandorga:` config keys were added or renamed.
25
+
3
26
  ## [1.5.0] — 2026-10-10
4
27
 
5
28
  ### Added
data/README.md CHANGED
@@ -17,7 +17,7 @@ An aesthetic Jekyll publishing platform for creative and technical writing. The
17
17
  Scaffold a site (Ada Example defaults, `content.backend: static`):
18
18
 
19
19
  ```bash
20
- gem install pandorga # once 1.1 is on RubyGems; or use a local checkout
20
+ gem install pandorga # or use a local checkout
21
21
  pandorga new my-site
22
22
  cd my-site
23
23
  bundle install
@@ -1,14 +1,14 @@
1
1
  {% comment %}
2
2
  chord-tab.html
3
- Exibe uma cifra estruturada em N colunas monoespaçadas, usando toda a largura disponível.
4
- Cada coluna respeita o limite de 79 caracteres por linha.
5
- Uso: {% include chord-tab.html tab=tab_data %}
6
- Onde tab_data tem:
7
- intro: "linha de acordes do intro (opcional)"
3
+ Renders a chord chart in N monospaced columns, using the full available width.
4
+ Each column stays within 79 characters per line.
5
+ Use: {% include chord-tab.html tab=tab_data %}
6
+ tab_data has:
7
+ intro: "intro chord line (optional)"
8
8
  sections:
9
- - label: "rótulo da seção (opcional)"
9
+ - label: "section label (optional)"
10
10
  content: |
11
- linhas de cifra/letra
11
+ chord and lyric lines
12
12
  {% endcomment %}
13
13
 
14
14
  <div class="chord-tab-container mt-16 mb-8"
@@ -29,6 +29,7 @@
29
29
  {%- endcomment -%}
30
30
 
31
31
  {%- assign footer_active = include.nav_active -%}
32
+ {%- assign footer_name = site.author | default: site.pandorga.identity.name -%}
32
33
  {%- assign footer_license = site.content_license -%}
33
34
 
34
35
  <footer class="site-footer">
@@ -39,9 +40,9 @@
39
40
  <div class="site-footer-grid">
40
41
 
41
42
  <div class="site-footer-block site-footer-masthead">
42
- <a href="/" class="site-footer-wordmark-link" aria-label="{{ site.author }} – Home">
43
+ <a href="/" class="site-footer-wordmark-link" aria-label="{% if footer_name != blank %}{{ footer_name }} – Home{% else %}Home{% endif %}">
43
44
  {% include theme/site-logo.html %}
44
- <span class="site-footer-wordmark">{{ site.author }}</span>
45
+ <span class="site-footer-wordmark">{{ footer_name }}</span>
45
46
  </a>
46
47
  {%- comment -%}
47
48
  The same fragment the home hero mounts, so the line the site opens
@@ -1,11 +1,11 @@
1
1
  {% comment %}
2
2
  transcription.html
3
- Exibe uma transcrição estruturada, com até 4 personagens (cores definidas por ordem de aparição).
4
- Uso: {% include transcription.html transcription=page.transcription youtube_id='fpmZiY24U0k' %}
5
- Ou para usar um arquivo em _data:
3
+ Renders a structured transcript, with up to 4 speakers (colors follow order of appearance).
4
+ Use: {% include transcription.html transcription=page.transcription youtube_id='fpmZiY24U0k' %}
5
+ Or to load a file from _data:
6
6
  {% assign transcription_data = site.data.transcriptions[page.transcription].transcription %}
7
7
  {% include transcription.html transcription=transcription_data youtube_id='fpmZiY24U0k' %}
8
- Também suporta url e image para thumbnail:
8
+ Also accepts url and image for a thumbnail:
9
9
  {% include transcription.html transcription=transcription_data url='https://...' image='https://...' %}
10
10
 
11
11
  Speaker labels are title-cased at render time (Patrícia, not PATRÍCIA) so
@@ -26,7 +26,7 @@
26
26
  <hr class="border-t border-gentle-divider mb-6">
27
27
  {% if include.youtube_id %}
28
28
  <div class="mb-2">
29
- {% include youtube.html id=include.youtube_id %} <!-- Exibe o vídeo do YouTube -->
29
+ {% include youtube.html id=include.youtube_id %} <!-- YouTube video -->
30
30
  <span class="font-label text-xs text-on-surface-variant">Transcrição do vídeo</span>
31
31
  </div>
32
32
  {% elsif include.url and include.image %}
data/_layouts/shell.html CHANGED
@@ -83,8 +83,10 @@
83
83
  </head>
84
84
 
85
85
  <body class="bg-background text-on-surface">
86
+ <a class="skip-link" href="#page-content">Skip to content</a>
86
87
 
87
88
  {% assign _nav_name = site.pandorga.identity | pandorga_hero_name: site.author, site.title %}
89
+ {% assign _home_label = site.author | default: site.pandorga.identity.name | default: _nav_name.wordmark %}
88
90
  {% assign nav_active = nil %}
89
91
  {% if page.collection == "articles" %}{% assign nav_active = "articles" %}{% endif %}
90
92
  {% if page.collection == "posts" %}{% assign nav_active = "blog" %}{% endif %}
@@ -98,7 +100,7 @@
98
100
  <nav class="sticky top-0 z-50 bg-surface">
99
101
  <div class="flex justify-between items-center w-full px-6 sm:px-8 md:px-10 pt-5 pb-3.5 leading-none max-w-7xl mx-auto">
100
102
  <div class="flex items-center gap-3 sm:gap-4 min-w-0">
101
- <a href="/" aria-label="{{ site.author }} – Home" class="shrink-0 inline-flex items-center gap-3 site-wordmark-link">
103
+ <a href="/" aria-label="{% if _home_label != blank %}{{ _home_label }} – Home{% else %}Home{% endif %}" class="shrink-0 inline-flex items-center gap-3 site-wordmark-link">
102
104
  {% include theme/site-logo.html %}
103
105
  <span class="site-wordmark">{{ _nav_name.wordmark }}</span>
104
106
  </a>
@@ -190,7 +192,9 @@
190
192
 
191
193
  {% include page/content-runtime.html %}
192
194
 
195
+ <div id="page-content" tabindex="-1">
193
196
  {{ content }}
197
+ </div>
194
198
 
195
199
  {% include page/figure-lightbox.html %}
196
200
 
@@ -6,6 +6,29 @@
6
6
  one source of navigation; only the presentation changes. The Explore menu
7
7
  stays for narrow viewports, where six links do not fit. */
8
8
 
9
+ .skip-link {
10
+ position: absolute;
11
+ left: 0.75rem;
12
+ top: 0.75rem;
13
+ z-index: 80;
14
+ padding: 0.45rem 0.75rem;
15
+ background: var(--color-surface);
16
+ color: var(--color-on-surface);
17
+ border: 1px solid var(--color-outline);
18
+ text-decoration: none;
19
+ font-family: var(--font-label);
20
+ font-size: var(--type-label);
21
+ transform: translateY(-150%);
22
+ }
23
+
24
+ .skip-link:focus {
25
+ transform: none;
26
+ }
27
+
28
+ #page-content:focus {
29
+ outline: none;
30
+ }
31
+
9
32
  .site-wordmark-link {
10
33
  display: inline-flex;
11
34
  align-items: center;
@@ -1498,26 +1498,6 @@ html[data-theme="light"] .home-hero-plate {
1498
1498
  }
1499
1499
  }
1500
1500
 
1501
- @media (min-width: 768px) {}
1502
-
1503
- /* ── Profile band, hero plate scale, section action order ──
1504
- Appended after the parallel page work; see the redesign PR. */
1505
-
1506
- /* The portrait sits at the end of its grid column so its right edge meets
1507
- the edge every band below aligns to. Cap lives on the earlier
1508
- `.home-hero-portrait` rule (Borders Edition). */
1509
- .home-profile-summary {
1510
- max-width: var(--reading-measure);
1511
- }
1512
-
1513
- .home-profile-summary p {
1514
- margin-bottom: var(--space-md);
1515
- }
1516
-
1517
- .home-profile-summary p:last-child {
1518
- margin-bottom: 0;
1519
- }
1520
-
1521
1501
  /* ── Reference band: Sources + Network of Ideas ──────────────────────────
1522
1502
  Two destinations in one band, each a card whose poster is a plate drawn
1523
1503
  from that section's own content by the export and fetched at runtime.
@@ -30,7 +30,9 @@ module Pandorga
30
30
  end
31
31
  pages = pandorga["pages"]
32
32
  if pages.nil?
33
- warnings << "pandorga.pages is empty — no pages will be generated"
33
+ warnings << "pandorga.pages is missing; no pages will be generated"
34
+ elsif pages.is_a?(Array) && pages.empty?
35
+ warnings << "pandorga.pages is empty; no pages will be generated"
34
36
  elsif !pages.is_a?(Array)
35
37
  errors << "pandorga.pages must be an array"
36
38
  else
@@ -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.3.11"
27
+ # GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.5.0"
28
28
  gem "csv"
29
29
  gem "base64"
30
30
  RUBY
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pandorga
4
- VERSION = "1.5.0"
4
+ VERSION = "1.5.1"
5
5
  end
@@ -64,6 +64,14 @@ sheets.each do |path|
64
64
  errors << "#{relative}: #{depth} unclosed brace(s) — every rule after the " \
65
65
  "offending block is swallowed and silently stops applying"
66
66
  end
67
+
68
+ if cleaned.match?(/\{[ \t\r\n]*\}/)
69
+ errors << "#{relative}: empty ruleset (a block that matches nothing)"
70
+ end
71
+
72
+ if source.include?("home-profile-summary")
73
+ errors << "#{relative}: .home-profile-summary is unused"
74
+ end
67
75
  end
68
76
 
69
77
  fail!("CSS structure problems:\n - #{errors.join("\n - ")}") unless errors.empty?
@@ -3,6 +3,7 @@
3
3
  # Refs: PLT-0.3, PLT-AC-5
4
4
  require "pathname"
5
5
  require "open3"
6
+ require "fileutils"
6
7
 
7
8
  ROOT = Pathname.new(__dir__).join("../..").expand_path
8
9
  EXAMPLE = ROOT.join("examples/minimal")
@@ -36,4 +37,41 @@ unless err.include?("pandorga:")
36
37
  exit 1
37
38
  end
38
39
 
40
+ missing = ROOT.join("tmp/doctor-missing-pages")
41
+ FileUtils.rm_rf(missing)
42
+ missing.mkpath
43
+ missing.join("_config.yml").write(<<~YAML)
44
+ pandorga:
45
+ identity:
46
+ name: Ada Example
47
+ YAML
48
+ _out, err, st = run_doctor(missing)
49
+ unless st.success?
50
+ warn "FAIL test-doctor: missing pages should warn, not fail\n#{err}"
51
+ exit 1
52
+ end
53
+ unless err.include?("pandorga.pages is missing")
54
+ warn "FAIL test-doctor: expected a missing-pages warning\n#{err}"
55
+ exit 1
56
+ end
57
+
58
+ empty = ROOT.join("tmp/doctor-empty-pages")
59
+ FileUtils.rm_rf(empty)
60
+ empty.mkpath
61
+ empty.join("_config.yml").write(<<~YAML)
62
+ pandorga:
63
+ identity:
64
+ name: Ada Example
65
+ pages: []
66
+ YAML
67
+ _out, err, st = run_doctor(empty)
68
+ unless st.success?
69
+ warn "FAIL test-doctor: empty pages should warn, not fail\n#{err}"
70
+ exit 1
71
+ end
72
+ unless err.include?("pandorga.pages is empty")
73
+ warn "FAIL test-doctor: expected an empty-pages warning\n#{err}"
74
+ exit 1
75
+ end
76
+
39
77
  puts "PASS test-doctor"
@@ -21,6 +21,17 @@ def run_doctor(dir)
21
21
  Open3.capture3(env, "ruby", EXE.to_s, "doctor", dir.to_s)
22
22
  end
23
23
 
24
+ guide = ROOT.join("docs/getting-started.md").read
25
+ readme = ROOT.join("README.md").read
26
+ unless guide.include?('gem at `~> 1.3`')
27
+ warn "FAIL test-new: getting-started must document the scaffold pin ~> 1.3"
28
+ exit 1
29
+ end
30
+ if readme.include?("once 1.1 is on RubyGems")
31
+ warn "FAIL test-new: README still says the gem is unpublished at 1.1"
32
+ exit 1
33
+ end
34
+
24
35
  FileUtils.rm_rf(DEST)
25
36
 
26
37
  stdout, stderr, status = run_new(DEST.to_s)
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Shell accessibility (skip link and home-link name).
5
+ # The top bar and footer used site.author alone, so a site with no author
6
+ # exposed the accessible name " – Home" and hid the visible wordmark.
7
+
8
+ require "pathname"
9
+
10
+ ROOT = Pathname.new(__dir__).join("..", "..").expand_path
11
+ SHELL = ROOT.join("_layouts/shell.html").read
12
+ FOOTER = ROOT.join("_includes/page/site-footer.html").read
13
+ CSS = ROOT.join("assets/css/ledger/chrome.css").read
14
+
15
+ def fail!(message)
16
+ warn "FAIL test-shell-a11y: #{message}"
17
+ exit 1
18
+ end
19
+
20
+ fail!("missing skip link") unless SHELL.include?('class="skip-link"') && SHELL.include?('href="#page-content"')
21
+ fail!("missing skip target") unless SHELL.include?('id="page-content"')
22
+ fail!("skip link is not shown on focus") unless CSS.include?(".skip-link:focus")
23
+
24
+ bare = 'aria-label="{{ site.author }} – Home"'
25
+ fail!("shell home link still uses site.author alone") if SHELL.include?(bare)
26
+ fail!("footer home link still uses site.author alone") if FOOTER.include?(bare)
27
+ fail!("shell home link needs an identity.name fallback") unless SHELL.include?("site.pandorga.identity.name")
28
+ fail!("footer home link needs an identity.name fallback") unless FOOTER.include?("site.pandorga.identity.name")
29
+
30
+ puts "PASS test-shell-a11y"
@@ -46,6 +46,14 @@ TEMPLATES.each do |name|
46
46
  end
47
47
  end
48
48
 
49
+ %w[_includes/chord-tab.html _includes/transcription.html].each do |rel|
50
+ text = ROOT.join(rel).read
51
+ if text.include?("Exibe")
52
+ warn "FAIL test-template-packages: #{rel} still has a Portuguese comment"
53
+ failed = true
54
+ end
55
+ end
56
+
49
57
  exit 1 if failed
50
58
 
51
59
  puts "PASS test-template-packages"
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # A listed gate that is not on disk must fail the run. Skipping it lets a
5
+ # renamed test disappear from CI while validate.sh still exits 0.
6
+
7
+ require "pathname"
8
+
9
+ ROOT = Pathname.new(__dir__).join("..", "..").expand_path
10
+ SCRIPT = ROOT.join("scripts/validate.sh")
11
+
12
+ def fail!(message)
13
+ warn "FAIL test-validate-allowlist: #{message}"
14
+ exit 1
15
+ end
16
+
17
+ source = SCRIPT.read
18
+ block = source[/if \[\[ ! -f "\$test" \]\]; then.*?fi/m]
19
+ fail!("missing-file branch not found") unless block
20
+ fail!("a missing listed test must set failed=1") unless block.include?("failed=1")
21
+ fail!("a missing listed test must not be skipped") if block.include?("skip")
22
+
23
+ listed = source.scan(%r{scripts/test/test-[A-Za-z0-9_.-]+})
24
+ fail!("allowlist is empty") if listed.empty?
25
+
26
+ missing = listed.uniq.reject { |rel| ROOT.join(rel).file? }
27
+ fail!("listed tests are not on disk: #{missing.join(', ')}") unless missing.empty?
28
+
29
+ puts "PASS test-validate-allowlist"
data/scripts/validate.sh CHANGED
@@ -55,12 +55,15 @@ TESTS=(
55
55
  scripts/test/test-r2-json-sync.rb
56
56
  scripts/test/test-writing-slug-limits.rb
57
57
  scripts/test/test-examples-build.rb
58
+ scripts/test/test-validate-allowlist.rb
59
+ scripts/test/test-shell-a11y.rb
58
60
  )
59
61
 
60
62
  failed=0
61
63
  for test in "${TESTS[@]}"; do
62
64
  if [[ ! -f "$test" ]]; then
63
- echo "-- ${test} (missing, skip)"
65
+ echo "-- ${test} (missing)"
66
+ failed=1
64
67
  continue
65
68
  fi
66
69
  echo "-- ${test}"
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.5.0
4
+ version: 1.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Pandorga contributors
@@ -410,6 +410,7 @@ files:
410
410
  - scripts/test/test-r2-json-sync.rb
411
411
  - scripts/test/test-registry-home.rb
412
412
  - scripts/test/test-runtime-js-syntax.rb
413
+ - scripts/test/test-shell-a11y.rb
413
414
  - scripts/test/test-slim-writing-index.rb
414
415
  - scripts/test/test-studio-api-contract.rb
415
416
  - scripts/test/test-studio-content-files.rb
@@ -425,6 +426,7 @@ files:
425
426
  - scripts/test/test-text-excerpt.rb
426
427
  - scripts/test/test-unwrap-media-src.mjs
427
428
  - scripts/test/test-unwrap-media-src.rb
429
+ - scripts/test/test-validate-allowlist.rb
428
430
  - scripts/test/test-withdrawn-content-export.rb
429
431
  - scripts/test/test-writing-index-export-slugs.rb
430
432
  - scripts/test/test-writing-slug-limits.rb