pandorga 1.8.4 → 1.9.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: 120307b06e8e2a6083eb4684bef760944c0fa334155262ea202be58493e0cdd6
4
- data.tar.gz: e17010ea2587987f38dc6236944c99c4790a380d87fcd994cc1462f5d184bee0
3
+ metadata.gz: a5c4864b0ecb92d3a9cceac946312495c0371449bbb2bc42077606bff30f704f
4
+ data.tar.gz: cb0dbfac5fb52318dafb2d07f9f8621d480220cd38bcef92d1d15eceac6b5784
5
5
  SHA512:
6
- metadata.gz: ef13097e5f083e7741ecfddbce6b994b84697f1a5bc593e43cdce93bd41bab6b94da9864555a12908a419d4e4ff0836b2230085f495f30d155810bac87f0ef0b
7
- data.tar.gz: 1c0e9c4a2e1f8d3cc6fdf3cd58103261f6271e445629e5f4e661f5d402f3525cc36fe717f1b86204640a0ffaeb25cb5171086645df15bab958781226f5fb2e75
6
+ metadata.gz: ccf07024fda631b0a2ee24a9a51f6dbf865cd93e8f9b141e6593d3512b478f119e8b2e43e7ed2a20730247c5752f2a4ffcdd4a4de58248b4bdb5c79cc8b5bc74
7
+ data.tar.gz: 9106591a4826bd84bbaa006dae1a6bec544313956e9775830363a1e356ec5a986ef9e173a93495dc9704c55f7ba862ef45dad2f81a1cd399a227979aab05c5a1
data/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.9.1] — 2026-10-14
4
+
5
+ ### Fixed
6
+
7
+ - The article description under the detail title uses `--type-prose`, the
8
+ same size as the body text. Family, weight, color, and spacing stay as
9
+ they were
10
+ - Bordered and boxed read-more pills do not underline the label.
11
+ Plain text read-more links stay underlined. Focus still shows the
12
+ outline
13
+
14
+ ## [1.9.0] — 2026-10-13
15
+
16
+ ### Added
17
+
18
+ - Optional `pandorga.home.hero_landscape` (home front matter
19
+ `hero_landscape` overrides it): a 16:9 image for viewports at or below
20
+ 767px, via `<picture>`, shown whole in a 16:9 plate
21
+
22
+ ### Changed
23
+
24
+ - Without that key the phone hero plate stays 3:4. It no longer cover-crops
25
+ the portrait into a 4:3 band
26
+ - The hero image keeps `fetchpriority="high"`. A configured landscape file
27
+ is preloaded on narrow viewports. The portrait probe sets `fetchPriority`
28
+ to `high`, applies `srcset` before `src`, and the plate draw starts with
29
+ the other home fetches
30
+ - Home links `tailwind.css` before the icon scripts so that sheet is not
31
+ held behind parser-blocking script
32
+
33
+ Text faces still load after the first paint with `display=swap` and the
34
+ metric-matched fallbacks from 1.8.4. One listing shell still serves every
35
+ detail URL.
36
+
37
+ ## [1.8.5] — 2026-10-13
38
+
39
+ ### Fixed
40
+
41
+ - Home hero `sizes` nudged above the plate width so 1.75–2× DPR picks a
42
+ sharp 3:4 variant; document that hero variants must be portrait fills
43
+
3
44
  ## [1.8.4] — 2026-10-12
4
45
 
5
46
  ### Fixed
@@ -578,10 +578,13 @@
578
578
  }
579
579
  return new Promise(function (resolve) {
580
580
  var probe = new Image();
581
+ probe.fetchPriority = 'high';
582
+ applyHeroPortraitSources(probe, chosen);
581
583
  probe.onload = function () {
582
- img.src = nextSrc;
583
584
  img.alt = nextAlt;
584
585
  applyHeroPortraitSources(img, chosen);
586
+ img.fetchPriority = 'high';
587
+ img.src = nextSrc;
585
588
  img.classList.add('is-shown');
586
589
  resolve(true);
587
590
  };
@@ -610,9 +613,44 @@
610
613
  return next();
611
614
  }
612
615
 
616
+ function heroLandscapeActive(img) {
617
+ var url = img && img.getAttribute('data-hero-landscape');
618
+ if (!url || !String(url).trim() || !window.matchMedia) return false;
619
+ return window.matchMedia('(max-width: 767px)').matches;
620
+ }
621
+
622
+ function clearHeroSources(img) {
623
+ img.removeAttribute('src');
624
+ img.removeAttribute('srcset');
625
+ img.removeAttribute('sizes');
626
+ img.alt = '';
627
+ }
628
+
629
+ function watchHeroFrame(img) {
630
+ var url = img.getAttribute('data-hero-landscape');
631
+ if (!url || !String(url).trim() || !window.matchMedia) return;
632
+ var mq = window.matchMedia('(max-width: 767px)');
633
+ if (!mq.addEventListener) return;
634
+ mq.addEventListener('change', function () {
635
+ if (mq.matches) {
636
+ clearHeroSources(img);
637
+ img.classList.add('is-shown');
638
+ return;
639
+ }
640
+ img.classList.remove('is-shown');
641
+ loadJson('pages/home/portraits.json').then(function (data) {
642
+ return showHeroPortrait(img, heroPortraitEntries(data));
643
+ }).catch(function (error) {
644
+ console.error(error);
645
+ });
646
+ });
647
+ }
648
+
613
649
  function hydrateHeroPortrait() {
614
650
  var img = document.querySelector('[data-content-hero-portrait]');
615
651
  if (!img) return Promise.resolve();
652
+ watchHeroFrame(img);
653
+ if (heroLandscapeActive(img)) return Promise.resolve();
616
654
  return loadJson('pages/home/portraits.json').then(function (data) {
617
655
  return showHeroPortrait(img, heroPortraitEntries(data));
618
656
  }).catch(function (error) {
@@ -621,6 +659,7 @@
621
659
  }
622
660
 
623
661
  function hydratePageFragments() {
662
+ hydrateHeroPortrait();
624
663
  var headers = Array.prototype.slice.call(document.querySelectorAll('[data-content-page-header]'));
625
664
  var chain = Promise.resolve();
626
665
  headers.forEach(function (el) {
@@ -644,7 +683,6 @@
644
683
  hydrateHomeSections();
645
684
  hydrateBandArt();
646
685
  hydrateContacts();
647
- hydrateHeroPortrait();
648
686
  });
649
687
  }
650
688
 
data/_layouts/home.html CHANGED
@@ -17,6 +17,7 @@ layout: shell
17
17
  {%- assign _hero_name = site.pandorga.identity | pandorga_hero_name: site.author, site.title -%}
18
18
  {%- assign _cv_page = site.pages | where: "key", "cv" | first -%}
19
19
  {%- assign _hero_art = site.pandorga.home.hero_art | default: "page/hero-default.html" -%}
20
+ {%- assign _hero_landscape = page.hero_landscape | default: site.pandorga.home.hero_landscape | default: "" | strip -%}
20
21
  {%- assign _home_bands = site.data.pandorga_home_bands -%}
21
22
 
22
23
  <main class="home-ledger">
@@ -53,8 +54,15 @@ layout: shell
53
54
  <span class="shard-accent home-hero-shard" aria-hidden="true"></span>
54
55
  <div class="home-hero-plate-wrap">
55
56
  <span class="ledger-frame-crosshairs" aria-hidden="true"></span>
56
- <figure class="home-hero-plate">
57
- <img alt="" width="1200" height="800" fetchpriority="high" data-content-hero-portrait />
57
+ <figure class="home-hero-plate{% if _hero_landscape != blank %} home-hero-plate--landscape{% endif %}">
58
+ {%- if _hero_landscape != blank -%}
59
+ <picture>
60
+ <source media="(max-width: 767px)" srcset="{{ _hero_landscape | escape }}" />
61
+ <img alt="" width="1600" height="900" fetchpriority="high" decoding="sync" data-content-hero-portrait data-hero-landscape="{{ _hero_landscape | escape }}" />
62
+ </picture>
63
+ {%- else -%}
64
+ <img alt="" width="960" height="1280" fetchpriority="high" decoding="sync" data-content-hero-portrait />
65
+ {%- endif -%}
58
66
  <span class="ledger-frame-corners" aria-hidden="true"></span>
59
67
  </figure>
60
68
  </div>
data/_layouts/shell.html CHANGED
@@ -66,6 +66,10 @@
66
66
  {%- endcomment -%}
67
67
  <link href="https://fonts.googleapis.com" rel="preconnect" />
68
68
  <link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect" />
69
+ {%- assign _hero_landscape = page.hero_landscape | default: site.pandorga.home.hero_landscape | default: "" | strip -%}
70
+ {%- if page.layout == "home" and _hero_landscape != blank -%}
71
+ <link rel="preload" as="image" href="{{ _hero_landscape | escape }}" fetchpriority="high" media="(max-width: 767px)" />
72
+ {%- endif -%}
69
73
  {% include theme/critical-preload.html %}
70
74
  <link rel="stylesheet" href="/assets/css/base.css" />
71
75
  <link rel="stylesheet" href="/assets/css/global-link.css" />
@@ -120,6 +124,11 @@
120
124
  {%- for _sheet in _ledger -%}
121
125
  <link rel="stylesheet" href="/assets/css/ledger/{{ _sheet }}.css" />
122
126
  {%- endfor -%}
127
+ {%- comment -%}
128
+ Utilities before the icon scripts. Those scripts are parser-blocking,
129
+ so a sheet after them waits until they finish before the scanner sees it.
130
+ {%- endcomment -%}
131
+ <link rel="stylesheet" href="/assets/css/tailwind.css" />
123
132
  {% include theme/font-loader.html %}
124
133
  {%- comment -%}
125
134
  Named icons only. The full variable face is about a megabyte, and a
@@ -194,7 +203,6 @@
194
203
  <style>
195
204
  :root { --drop-cap-lines: {{ site.drop_cap_lines | default: 2 }}; }
196
205
  </style>
197
- <link rel="stylesheet" href="/assets/css/tailwind.css" />
198
206
  </head>
199
207
 
200
208
  <body class="bg-background text-on-surface">
@@ -745,7 +745,7 @@ body.figure-lightbox-open {
745
745
 
746
746
  .article-sidebar-description {
747
747
  font-family: var(--font-body);
748
- font-size: var(--type-body);
748
+ font-size: var(--type-prose);
749
749
  font-weight: var(--weight-body);
750
750
  line-height: var(--leading-body);
751
751
  letter-spacing: normal;
data/assets/css/base.css CHANGED
@@ -1026,6 +1026,16 @@ a.ledger-chip:hover {
1026
1026
  text-decoration-color: color-mix(in srgb, var(--color-link-hover) 75%, transparent);
1027
1027
  }
1028
1028
 
1029
+ /* Pill read-more only. The box is the affordance, so the label line would
1030
+ cross the border. Plain text read-more keeps the underline above.
1031
+ Focus keeps the outline. */
1032
+ :is(.ledger-cta--emphasis, .ledger-cta--emphasis-alt):is(:link, :visited, :hover, :focus, :focus-visible, :active),
1033
+ :is(.home-featured-foot, .writing-lead-foot) :is(.home-featured-cta, .writing-lead-cta):is(:link, :visited, :hover, :focus, :focus-visible, :active),
1034
+ :is(.ledger-cta--emphasis, .ledger-cta--emphasis-alt):is(:link, :visited, :hover, :focus, :focus-visible, :active)>span:not(.ledger-cta-arrow):not(.ledger-cta-icon),
1035
+ :is(.home-featured-foot, .writing-lead-foot) :is(.home-featured-cta, .writing-lead-cta).ledger-cta:is(:link, :visited, :hover, :focus, :focus-visible, :active)>span:not(.ledger-cta-arrow):not(.ledger-cta-icon) {
1036
+ text-decoration: none;
1037
+ }
1038
+
1029
1039
  .ledger-cta-arrow {
1030
1040
  transition: transform var(--motion-duration-fast) var(--motion-ease-default);
1031
1041
  }
@@ -464,12 +464,11 @@ aside:has(> .text-detail-sidebar) {
464
464
  }
465
465
 
466
466
  /* Lead thesis. `description` is the article's own one-sentence claim — body
467
- face and body size, in legend ink so it sits under the H1 without matching
468
- the reading column. */
467
+ face at the prose size, in legend ink so it sits under the H1. */
469
468
  .text-detail-sidebar .article-sidebar-description {
470
469
  font-family: var(--font-body);
471
470
  font-style: normal;
472
- font-size: var(--type-body);
471
+ font-size: var(--type-prose);
473
472
  font-weight: var(--weight-body);
474
473
  line-height: var(--leading-body);
475
474
  color: var(--color-legend);
@@ -370,8 +370,10 @@
370
370
 
371
371
  /* ── Portrait plate ──
372
372
  Beside the copy on a wide page the plate is portrait (3:4): its height
373
- matches the left column and the width is W = 3/4 × H. Edge-to-edge on a
374
- phone it is landscape (4:3) from the band width. */
373
+ matches the left column and the width is W = 3/4 × H. On a phone it stays
374
+ 3:4. A wider box would cover-crop that portrait a second time. When
375
+ hero_landscape is set, the phone plate is 16:9 and the picture source is
376
+ that file. */
375
377
  .home-hero-plate {
376
378
  position: relative;
377
379
  z-index: 1;
@@ -389,12 +391,6 @@
389
391
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-on-surface) 10%, transparent);
390
392
  }
391
393
 
392
- @media (max-width: 767px) {
393
- .home-hero-plate {
394
- aspect-ratio: 4 / 3;
395
- }
396
- }
397
-
398
394
  :root:not([data-theme="dark"]) .home-hero-plate,
399
395
  html[data-theme="light"] .home-hero-plate {
400
396
  border-width: 1px;
@@ -451,6 +447,13 @@ html[data-theme="light"] .home-hero-plate {
451
447
  }
452
448
  }
453
449
 
450
+ .home-hero-plate picture {
451
+ display: block;
452
+ width: 100%;
453
+ height: 100%;
454
+ margin: 0;
455
+ }
456
+
454
457
  .home-hero-plate img {
455
458
  width: 100%;
456
459
  height: 100%;
@@ -469,6 +472,21 @@ html[data-theme="light"] .home-hero-plate {
469
472
  opacity: 1;
470
473
  }
471
474
 
475
+ /* 16:9 file in a 16:9 plate. contain shows the whole frame. The image is
476
+ visible without waiting for the portrait runtime, so it can be the LCP. */
477
+ @media (max-width: 767px) {
478
+ .home-hero-plate--landscape {
479
+ aspect-ratio: 16 / 9;
480
+ }
481
+
482
+ .home-hero-plate--landscape img {
483
+ object-fit: contain;
484
+ object-position: center center;
485
+ opacity: 1;
486
+ transition: none;
487
+ }
488
+ }
489
+
472
490
  .home-hero-plate:hover img {
473
491
  transform: scale(1.02);
474
492
  }
@@ -1933,8 +1951,9 @@ html[data-theme="light"] .home-featured .ledger-poster {
1933
1951
  ends flush with the viewport and adds no scrollable width; this must stay
1934
1952
  below 768px, which is where .home-band-inner swaps that token for --gutter.
1935
1953
  The side hairlines go with it: a border pinned to the screen edge reads as a
1936
- frame cut off rather than as the plate's edge. Orientation still owns the
1937
- crop; object-fit: cover re-crops the image inside the wider box. */
1954
+ frame cut off rather than as the plate's edge. The plate stays 3:4, the
1955
+ same frame as the portrait file, so cover does not crop it again. A
1956
+ configured hero_landscape switches this query to 16:9 and contain. */
1938
1957
  @media (max-width: 767px) {
1939
1958
  .home-hero-portrait {
1940
1959
  max-width: none;
@@ -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.8.4"
27
+ # GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.9.1"
28
28
  gem "csv"
29
29
  gem "base64"
30
30
  RUBY
@@ -49,6 +49,9 @@ home:
49
49
  hero_art:
50
50
  type: string
51
51
  notes: Include path for hero decoration (default `page/hero-default.html`)
52
+ hero_landscape:
53
+ type: string
54
+ notes: Optional URL of a 16:9 image used at or below 767px. Home front matter `hero_landscape` overrides this key. Omitted, the phone plate stays 3:4
52
55
 
53
56
  fonts:
54
57
  title: "`pandorga.fonts`"
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pandorga
4
- VERSION = "1.8.4"
4
+ VERSION = "1.9.1"
5
5
  end
@@ -4,13 +4,20 @@
4
4
  # paths to pages/home/portraits.json. The author uploads a photograph under
5
5
  # content/media/images/hero/ and does not keep a second list.
6
6
  # Optional width variants live under variants/ so they are not extra draws.
7
+ # Variants should be 3:4 portrait fills (not landscape width-only resizes):
8
+ # the plate is object-fit cover at 3:4, including on a phone, so a 480×270
9
+ # landscape candidate is too short and looks soft. A separate 16:9 file for
10
+ # narrow viewports is pandorga.home.hero_landscape, not a pool variant.
7
11
 
8
12
  require "pathname"
9
13
 
10
14
  module HeroPortraits
11
15
  IMAGE_EXTENSIONS = %w[.jpg .jpeg .png .webp .gif].freeze
12
16
  WIDTHS = [480, 960, 1440].freeze
13
- SIZES = "(max-width: 767px) 100vw, (max-width: 1023px) 14rem, 16rem"
17
+ # Slightly above the plate CSS width (14/16rem at html 110%) so 1.75–2×
18
+ # DPR picks the next 3:4 variant instead of a soft 480w. Variants must be
19
+ # portrait fills; landscape width-only resizes are too short under cover.
20
+ SIZES = "(max-width: 767px) 100vw, (max-width: 1023px) 18rem, 20rem"
14
21
 
15
22
  module_function
16
23
 
@@ -23,6 +23,7 @@ require_relative "../content/hero_portraits"
23
23
  ROOT = Pathname.new(__dir__).join("..", "..").expand_path
24
24
  EXPORT = ROOT.join("scripts/content/export-content-json.rb")
25
25
  LAYOUT = ROOT.join("_layouts/home.html")
26
+ SHELL = ROOT.join("_layouts/shell.html")
26
27
  HOME_CSS = ROOT.join("assets/css/ledger/home.css")
27
28
  RUNTIME = ROOT.join("_includes/content-runtime/60-fragments.html")
28
29
  SCHEMA = ROOT.join("studio/schema.yml")
@@ -96,9 +97,28 @@ check!(!layout.include?("profile-monologue"),
96
97
  "the deleted shell photograph must not be referenced")
97
98
  check!(!ROOT.join("assets/images/profile-monologue.JPG").exist?,
98
99
  "profile-monologue.JPG must not exist")
99
- hero_img = layout[/<img[^>]*data-content-hero-portrait[^>]*>/m]
100
- check!(hero_img && !hero_img.include?("src=") && hero_img.include?('alt=""'),
101
- "the plate starts without a photographic src and keeps an empty alt, got #{hero_img.inspect}")
100
+ hero_imgs = layout.scan(/<img[^>]*data-content-hero-portrait[^>]*>/m)
101
+ check!(hero_imgs.any?, "the plate image is missing")
102
+ hero_imgs.each do |hero_img|
103
+ check!(!hero_img.include?("src=") && hero_img.include?('alt=""'),
104
+ "the plate starts without a photographic src and keeps an empty alt, got #{hero_img.inspect}")
105
+ check!(hero_img.include?('fetchpriority="high"'),
106
+ "the hero image must request fetchpriority high, got #{hero_img.inspect}")
107
+ end
108
+ check!(layout.include?("page.hero_landscape") && layout.include?("site.pandorga.home.hero_landscape"),
109
+ "narrow hero reads front matter and pandorga.home.hero_landscape")
110
+ check!(layout.include?('media="(max-width: 767px)"') && layout.include?("<picture>"),
111
+ "a configured landscape file is a picture source for narrow viewports")
112
+ check!(layout.include?("data-hero-landscape"),
113
+ "the image carries the landscape URL for the runtime")
114
+ shell = SHELL.read
115
+ check!(shell.include?('rel="preload" as="image"') && shell.include?('fetchpriority="high"') &&
116
+ shell.include?('media="(max-width: 767px)"') && shell.include?("hero_landscape"),
117
+ "the shell preloads a configured landscape image on narrow viewports")
118
+ tailwind_at = shell.index('href="/assets/css/tailwind.css"')
119
+ icons_at = shell.index("window.__pandorgaIconsHref")
120
+ check!(tailwind_at && icons_at && tailwind_at < icons_at,
121
+ "tailwind must be linked before the icon scripts")
102
122
 
103
123
  home_css = HOME_CSS.read
104
124
  check!(home_css.include?("background: black"),
@@ -109,6 +129,14 @@ check!(plate_img&.match?(/opacity:\s*0/) && plate_img.match?(/transition:[^;]*op
109
129
  shown = home_css[/^\.home-hero-plate img\.is-shown \{.*?\n\}/m]
110
130
  check!(shown&.match?(/opacity:\s*1/),
111
131
  "a ready photograph fades to full opacity, got #{shown.inspect}")
132
+ check!(!home_css.include?("aspect-ratio: 4 / 3"),
133
+ "the phone plate must not cover-crop the portrait into 4:3")
134
+ landscape_plate = home_css[/@media \(max-width: 767px\) \{\s*\.home-hero-plate--landscape \{[^}]*\}/m]
135
+ check!(landscape_plate&.include?("aspect-ratio: 16 / 9"),
136
+ "a landscape plate is 16:9 on a phone, got #{landscape_plate.inspect}")
137
+ landscape_img = home_css[/\.home-hero-plate--landscape img \{[^}]*\}/m]
138
+ check!(landscape_img&.include?("object-fit: contain") && landscape_img.include?("opacity: 1"),
139
+ "the 16:9 file is shown whole and can paint without the portrait fade, got #{landscape_img.inspect}")
112
140
 
113
141
  runtime = RUNTIME.read
114
142
  start = runtime.index("function heroPortraitEntries")
@@ -125,6 +153,20 @@ onload = body[/probe\.onload = function \(\) \{.*?\n \};/m]
125
153
  check!(onload&.include?("img.src = nextSrc") && onload.include?("img.alt = nextAlt") &&
126
154
  onload.include?("img.classList.add('is-shown')"),
127
155
  "src, alt, and the fade-in must be applied together after load, got #{onload.inspect}")
156
+ check!(onload && onload.index("applyHeroPortraitSources") && onload.index("img.src = nextSrc") &&
157
+ onload.index("applyHeroPortraitSources") < onload.index("img.src = nextSrc"),
158
+ "srcset must be applied before src so the full file is not the first request")
159
+ check!(body.include?("probe.fetchPriority = 'high'"),
160
+ "the portrait probe must use fetchPriority high")
161
+ check!(body.include?("heroLandscapeActive") && body.include?("data-hero-landscape"),
162
+ "a narrow viewport with hero_landscape must not swap in a portrait")
163
+ check!(runtime.include?("hydrateHeroPortrait();"),
164
+ "hydratePageFragments must draw the plate before the later fragment chain")
165
+ plate_call = runtime.index("function hydratePageFragments")
166
+ later = runtime.index("hydrateHomeSections();", plate_call || 0)
167
+ check!(plate_call && runtime.index("hydrateHeroPortrait();", plate_call) &&
168
+ runtime.index("hydrateHeroPortrait();", plate_call) < later,
169
+ "the plate draw must start at the beginning of hydratePageFragments")
128
170
  onerror = body[/probe\.onerror = function \(\) \{.*?\n \};/m]
129
171
  check!(onerror && !onerror.include?("img.src") && !onerror.include?("is-shown"),
130
172
  "a failed image load must leave the plate black, got #{onerror.inspect}")
data/scripts/validate.sh CHANGED
@@ -68,6 +68,7 @@ TESTS=(
68
68
  scripts/test/test-fonts.rb
69
69
  scripts/test/test-css-delivery.rb
70
70
  scripts/test/test-discovery.rb
71
+ scripts/test/test-hero-portraits.rb
71
72
  )
72
73
 
73
74
  failed=0
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.8.4
4
+ version: 1.9.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - The Pandorga contributors