pandorga 1.5.0 → 1.6.0
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 +51 -0
- data/README.md +1 -1
- data/_includes/chord-tab.html +7 -7
- data/_includes/content-runtime/41-listing-helpers.html +7 -0
- data/_includes/content-runtime/43-blocks.html +4 -3
- data/_includes/content-runtime/60-fragments.html +77 -11
- data/_includes/page/site-footer.html +3 -2
- data/_includes/theme/critical-preload.html +35 -0
- data/_includes/theme/json-ld.html +35 -0
- data/_includes/transcription.html +5 -5
- data/_layouts/articles.html +8 -2
- data/_layouts/cv.html +20 -14
- data/_layouts/home.html +23 -3
- data/_layouts/shell.html +53 -12
- data/assets/css/ledger/chrome.css +23 -0
- data/assets/css/ledger/cv.css +13 -0
- data/assets/css/ledger/home.css +27 -20
- data/assets/css/ledger/writing.css +27 -3
- data/assets/css/tailwind.css +3 -0
- data/assets/tailwind-play.js +2 -1
- data/lib/pandorga/commands/doctor.rb +3 -1
- data/lib/pandorga/commands/new.rb +1 -1
- data/lib/pandorga/discovery.rb +78 -0
- data/lib/pandorga/jekyll/plugins/discovery.rb +32 -0
- data/lib/pandorga/version.rb +1 -1
- data/scripts/cdn-allowlist.json +2 -5
- data/scripts/tailwind/build.sh +19 -0
- data/scripts/tailwind/input.css +12 -0
- data/scripts/tailwind/tailwind.config.js +102 -0
- data/scripts/test/render-parity/blocks/project-inventory-row.json +3 -2
- data/scripts/test/test-css-delivery.rb +32 -0
- data/scripts/test/test-css-structure.rb +8 -0
- data/scripts/test/test-discovery.rb +46 -0
- data/scripts/test/test-doctor.rb +38 -0
- data/scripts/test/test-examples-build.rb +15 -0
- data/scripts/test/test-hero-portraits.mjs +1 -1
- data/scripts/test/test-hydrate-reserve.rb +64 -0
- data/scripts/test/test-new.rb +11 -0
- data/scripts/test/test-shell-a11y.rb +30 -0
- data/scripts/test/test-template-packages.rb +8 -0
- data/scripts/test/test-validate-allowlist.rb +29 -0
- data/scripts/validate.sh +7 -1
- metadata +14 -2
- data/assets/css/cv.css +0 -13
data/_layouts/shell.html
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
{% assign canonical_path = page.canonical_url | default: page.url %}
|
|
14
14
|
<title>{{ meta_title | strip | escape_once }}</title>
|
|
15
15
|
<meta name="description" content="{{ meta_description | escape_once }}" />
|
|
16
|
+
{% include theme/json-ld.html %}
|
|
16
17
|
<!-- Open Graph / Social Sharing -->
|
|
17
18
|
{% assign og_type = page.og_type | default: "website" %}
|
|
18
19
|
<meta property="og:type" content="{{ og_type }}" />
|
|
@@ -57,17 +58,54 @@
|
|
|
57
58
|
<meta name="twitter:image" content="{{ og_image_url }}" />
|
|
58
59
|
<!-- Canonical URL -->
|
|
59
60
|
<link rel="canonical" href="{{ canonical_path | absolute_url }}" />
|
|
61
|
+
{% include theme/critical-preload.html %}
|
|
60
62
|
<link rel="stylesheet" href="/assets/css/base.css" />
|
|
61
|
-
<link rel="stylesheet" href="/assets/css/article.css" />
|
|
62
|
-
{% include theme/theme-vars.html %}
|
|
63
|
-
<link rel="stylesheet" href="/assets/css/cv.css" />
|
|
64
63
|
<link rel="stylesheet" href="/assets/css/global-link.css" />
|
|
65
|
-
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
{% include theme/theme-vars.html %}
|
|
65
|
+
<link rel="stylesheet" href="/assets/css/ledger/chrome.css" />
|
|
66
|
+
<link rel="stylesheet" href="/assets/css/ledger/footer.css" />
|
|
67
|
+
{%- comment -%}
|
|
68
|
+
Ledger sheets stay with the layout that uses them. article.css is the
|
|
69
|
+
reading column, so only detail-capable layouts load it. An unknown
|
|
70
|
+
layout still receives every sheet.
|
|
71
|
+
{%- endcomment -%}
|
|
72
|
+
{%- case page.layout -%}
|
|
73
|
+
{%- when "home" -%}
|
|
74
|
+
{%- assign _ledger = "home" | split: "|" -%}
|
|
75
|
+
{%- assign _article_css = false -%}
|
|
76
|
+
{%- when "articles" -%}
|
|
77
|
+
{%- assign _ledger = "writing|detail" | split: "|" -%}
|
|
78
|
+
{%- assign _article_css = true -%}
|
|
79
|
+
{%- when "blog" -%}
|
|
80
|
+
{%- assign _ledger = "rascunhos|detail" | split: "|" -%}
|
|
81
|
+
{%- assign _article_css = true -%}
|
|
82
|
+
{%- when "cv" -%}
|
|
83
|
+
{%- assign _ledger = "cv|detail" | split: "|" -%}
|
|
84
|
+
{%- assign _article_css = true -%}
|
|
85
|
+
{%- when "projects" -%}
|
|
86
|
+
{%- assign _ledger = "projects|detail" | split: "|" -%}
|
|
87
|
+
{%- assign _article_css = true -%}
|
|
88
|
+
{%- when "resources" -%}
|
|
89
|
+
{%- assign _ledger = "sources" | split: "|" -%}
|
|
90
|
+
{%- assign _article_css = false -%}
|
|
91
|
+
{%- when "network" -%}
|
|
92
|
+
{%- assign _ledger = "network" | split: "|" -%}
|
|
93
|
+
{%- assign _article_css = false -%}
|
|
94
|
+
{%- when "bibliography" -%}
|
|
95
|
+
{%- assign _ledger = "bibliography" | split: "|" -%}
|
|
96
|
+
{%- assign _article_css = false -%}
|
|
97
|
+
{%- when "text" -%}
|
|
98
|
+
{%- assign _ledger = "detail" | split: "|" -%}
|
|
99
|
+
{%- assign _article_css = true -%}
|
|
100
|
+
{%- else -%}
|
|
101
|
+
{%- assign _ledger = "home|writing|detail|projects|rascunhos|bibliography|network|sources|cv" | split: "|" -%}
|
|
102
|
+
{%- assign _article_css = true -%}
|
|
103
|
+
{%- endcase -%}
|
|
104
|
+
{%- if _article_css -%}
|
|
105
|
+
<link rel="stylesheet" href="/assets/css/article.css" />
|
|
106
|
+
{%- endif -%}
|
|
107
|
+
{%- for _sheet in _ledger -%}
|
|
108
|
+
<link rel="stylesheet" href="/assets/css/ledger/{{ _sheet }}.css" />
|
|
71
109
|
{%- endfor -%}
|
|
72
110
|
<link href="https://fonts.googleapis.com" rel="preconnect" />
|
|
73
111
|
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect" />
|
|
@@ -78,13 +116,14 @@
|
|
|
78
116
|
<style>
|
|
79
117
|
:root { --drop-cap-lines: {{ site.drop_cap_lines | default: 2 }}; }
|
|
80
118
|
</style>
|
|
81
|
-
<
|
|
82
|
-
<script src="/assets/tailwind-play.js"></script>
|
|
119
|
+
<link rel="stylesheet" href="/assets/css/tailwind.css" />
|
|
83
120
|
</head>
|
|
84
121
|
|
|
85
122
|
<body class="bg-background text-on-surface">
|
|
123
|
+
<a class="skip-link" href="#page-content">Skip to content</a>
|
|
86
124
|
|
|
87
125
|
{% assign _nav_name = site.pandorga.identity | pandorga_hero_name: site.author, site.title %}
|
|
126
|
+
{% assign _home_label = site.author | default: site.pandorga.identity.name | default: _nav_name.wordmark %}
|
|
88
127
|
{% assign nav_active = nil %}
|
|
89
128
|
{% if page.collection == "articles" %}{% assign nav_active = "articles" %}{% endif %}
|
|
90
129
|
{% if page.collection == "posts" %}{% assign nav_active = "blog" %}{% endif %}
|
|
@@ -98,7 +137,7 @@
|
|
|
98
137
|
<nav class="sticky top-0 z-50 bg-surface">
|
|
99
138
|
<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
139
|
<div class="flex items-center gap-3 sm:gap-4 min-w-0">
|
|
101
|
-
<a href="/" aria-label="{{
|
|
140
|
+
<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
141
|
{% include theme/site-logo.html %}
|
|
103
142
|
<span class="site-wordmark">{{ _nav_name.wordmark }}</span>
|
|
104
143
|
</a>
|
|
@@ -190,7 +229,9 @@
|
|
|
190
229
|
|
|
191
230
|
{% include page/content-runtime.html %}
|
|
192
231
|
|
|
232
|
+
<div id="page-content" tabindex="-1">
|
|
193
233
|
{{ content }}
|
|
234
|
+
</div>
|
|
194
235
|
|
|
195
236
|
{% include page/figure-lightbox.html %}
|
|
196
237
|
|
|
@@ -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;
|
data/assets/css/ledger/cv.css
CHANGED
|
@@ -419,6 +419,19 @@ html[data-theme="light"] .cv-product {
|
|
|
419
419
|
padding: var(--space-xl);
|
|
420
420
|
}
|
|
421
421
|
|
|
422
|
+
.cv-summary:empty,
|
|
423
|
+
.cv-dossier-note:empty {
|
|
424
|
+
min-height: calc(var(--type-body) * var(--leading-body) * 4);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.cv-reserve-card {
|
|
428
|
+
display: block;
|
|
429
|
+
min-height: 6.5rem;
|
|
430
|
+
border: 1.5px solid var(--border-ink);
|
|
431
|
+
border-radius: var(--radius-card);
|
|
432
|
+
background: var(--color-surface-card);
|
|
433
|
+
}
|
|
434
|
+
|
|
422
435
|
.cv-summary p {
|
|
423
436
|
margin: 0 0 1em;
|
|
424
437
|
}
|
data/assets/css/ledger/home.css
CHANGED
|
@@ -239,6 +239,10 @@
|
|
|
239
239
|
margin: 0;
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
+
.home-hero-tagline:empty {
|
|
243
|
+
min-height: calc(var(--type-body) * 1.35);
|
|
244
|
+
}
|
|
245
|
+
|
|
242
246
|
/* Name spans the copy column (container query on .home-hero-copy). The floor
|
|
243
247
|
is the band-title step — Articles, Rascunhos, Projects — so a phone does
|
|
244
248
|
not drop the name to the card size to keep it on one line. From 640px the
|
|
@@ -308,6 +312,12 @@
|
|
|
308
312
|
line-height: var(--leading-body);
|
|
309
313
|
}
|
|
310
314
|
|
|
315
|
+
/* Hold the summary's box until the fragment paints, so the CTA under it
|
|
316
|
+
does not jump when the paragraph arrives. */
|
|
317
|
+
.home-hero-summary:empty {
|
|
318
|
+
min-height: calc(var(--type-body) * var(--leading-body) * 6);
|
|
319
|
+
}
|
|
320
|
+
|
|
311
321
|
.home-hero-summary p {
|
|
312
322
|
margin: 0 0 var(--space-md);
|
|
313
323
|
}
|
|
@@ -781,6 +791,16 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
781
791
|
}
|
|
782
792
|
|
|
783
793
|
/* ── Writing cards ── */
|
|
794
|
+
.home-card-grid:empty,
|
|
795
|
+
.home-draft-list:empty,
|
|
796
|
+
[data-home-featured-slot]:empty {
|
|
797
|
+
min-height: 16rem;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.home-project-inventory:empty {
|
|
801
|
+
min-height: 8rem;
|
|
802
|
+
}
|
|
803
|
+
|
|
784
804
|
.home-card-grid {
|
|
785
805
|
display: grid;
|
|
786
806
|
grid-template-columns: minmax(0, 1fr);
|
|
@@ -1232,6 +1252,13 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1232
1252
|
padding: 0;
|
|
1233
1253
|
}
|
|
1234
1254
|
|
|
1255
|
+
button.home-project-inventory-row {
|
|
1256
|
+
font: inherit;
|
|
1257
|
+
color: inherit;
|
|
1258
|
+
text-align: start;
|
|
1259
|
+
width: 100%;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1235
1262
|
.home-project-inventory-row {
|
|
1236
1263
|
position: relative;
|
|
1237
1264
|
display: flex;
|
|
@@ -1498,26 +1525,6 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1498
1525
|
}
|
|
1499
1526
|
}
|
|
1500
1527
|
|
|
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
1528
|
/* ── Reference band: Sources + Network of Ideas ──────────────────────────
|
|
1522
1529
|
Two destinations in one band, each a card whose poster is a plate drawn
|
|
1523
1530
|
from that section's own content by the export and fetched at runtime.
|
|
@@ -272,10 +272,34 @@ html[data-theme="light"] .writing-index .writing-lead-media .ledger-poster {
|
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
274
|
|
|
275
|
-
/* The revision date is the quieter half of the ledger line
|
|
276
|
-
|
|
275
|
+
/* The revision date is the quieter half of the ledger line. It uses the
|
|
276
|
+
variant ink solid: a 78% mix with transparent measured 3.69 and 3.90
|
|
277
|
+
against the light paper, under the 4.5:1 text floor. */
|
|
277
278
|
.writing-index .writing-revised {
|
|
278
|
-
color:
|
|
279
|
+
color: var(--color-on-surface-variant);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
.writing-index .writing-archive-reserve {
|
|
283
|
+
display: flex;
|
|
284
|
+
flex-direction: column;
|
|
285
|
+
gap: var(--space-md);
|
|
286
|
+
max-width: none;
|
|
287
|
+
padding: 0;
|
|
288
|
+
background: transparent;
|
|
289
|
+
border: 0;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.writing-index .writing-reserve-row {
|
|
293
|
+
display: block;
|
|
294
|
+
min-height: 7.25rem;
|
|
295
|
+
border: 1.5px solid var(--border-ink);
|
|
296
|
+
border-radius: var(--radius-card);
|
|
297
|
+
background: var(--color-surface-card);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
#articles-lead:empty {
|
|
301
|
+
min-height: 16rem;
|
|
302
|
+
margin-bottom: var(--space-xl);
|
|
279
303
|
}
|
|
280
304
|
|
|
281
305
|
/* ══ Archive and rail ══
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
/* Compiled Tailwind utilities (3.4.17, forms plugin). Replaces the Play CDN.
|
|
2
|
+
Regenerate with scripts/tailwind/build.sh after adding a utility class. */
|
|
3
|
+
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.17 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-body),sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:var(--font-mono);font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}[multiple],[type=date],[type=datetime-local],[type=email],[type=month],[type=number],[type=password],[type=search],[type=tel],[type=text],[type=time],[type=url],[type=week],input:where(:not([type])),select,textarea{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow:0 0 #0000}[multiple]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=email]:focus,[type=month]:focus,[type=number]:focus,[type=password]:focus,[type=search]:focus,[type=tel]:focus,[type=text]:focus,[type=time]:focus,[type=url]:focus,[type=week]:focus,input:where(:not([type])):focus,select:focus,textarea:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-meridiem-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-year-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3E%3C/svg%3E");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple],[size]:where(select:not([size="1"])){background-image:none;background-position:0 0;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow:0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset:var(--tw-empty,/*!*/ /*!*/);--tw-ring-offset-width:2px;--tw-ring-offset-color:#fff;--tw-ring-color:#2563eb;--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Cpath d='M12.207 4.793a1 1 0 0 1 0 1.414l-5 5a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L6.5 9.086l4.293-4.293a1 1 0 0 1 1.414 0'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=checkbox]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=radio]:checked{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='%23fff' viewBox='0 0 16 16'%3E%3Ccircle cx='8' cy='8' r='3'/%3E%3C/svg%3E")}@media (forced-colors:active) {[type=radio]:checked{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:checked:focus,[type=checkbox]:checked:hover,[type=radio]:checked:focus,[type=radio]:checked:hover{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath stroke='%23fff' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3E%3C/svg%3E");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:50%;background-repeat:no-repeat}@media (forced-colors:active) {[type=checkbox]:indeterminate{-webkit-appearance:auto;-moz-appearance:auto;appearance:auto}}[type=checkbox]:indeterminate:focus,[type=checkbox]:indeterminate:hover{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.\!visible{visibility:visible!important}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.left-0{left:0}.right-0{right:0}.top-0{top:0}.top-full{top:100%}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.col-span-full{grid-column:1/-1}.m-0{margin:0}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1\.5{margin-top:.375rem;margin-bottom:.375rem}.my-8{margin-top:2rem;margin-bottom:2rem}.my-\[1\.55em\]{margin-top:1.55em;margin-bottom:1.55em}.mb-10{margin-bottom:2.5rem}.mb-16{margin-bottom:4rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mb-\[0\.35rem\]{margin-bottom:.35rem}.ml-2{margin-left:.5rem}.mt-1{margin-top:.25rem}.mt-16{margin-top:4rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.\!grid{display:grid!important}.grid{display:grid}.contents{display:contents}.\!hidden{display:none!important}.hidden{display:none}.h-12{height:3rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-\[12vw\]{height:12vw}.h-\[1px\]{height:1px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.min-h-screen{min-height:100vh}.w-12{width:3rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[14rem\]{min-width:14rem}.min-w-\[3\.5rem\]{min-width:3.5rem}.min-w-\[9\.5rem\]{min-width:9.5rem}.max-w-7xl{max-width:80rem}.max-w-full{max-width:100%}.max-w-xs{max-width:20rem}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.grow{flex-grow:1}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.resize{resize:both}.scroll-mt-28{scroll-margin-top:7rem}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-end{align-items:flex-end}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.gap-x-2{-moz-column-gap:.5rem;column-gap:.5rem}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem*var(--tw-space-y-reverse))}.overflow-x-auto{overflow-x:auto}.truncate{overflow:hidden;text-overflow:ellipsis}.truncate,.whitespace-nowrap{white-space:nowrap}.whitespace-pre{white-space:pre}.rounded{border-radius:.125rem}.rounded-\[9999px\]{border-radius:9999px}.border{border-width:1px}.border-0{border-width:0}.border-t{border-top-width:1px}.border-gentle{border-color:var(--border-gentle)}.border-gentle-divider{border-color:var(--border-gentle-divider)}.border-gentle-subtle{border-color:var(--border-gentle-subtle)}.bg-background{background-color:var(--color-background)}.bg-surface{background-color:var(--color-surface)}.bg-surface-container-highest{background-color:var(--color-surface-container-highest)}.bg-surface-container-low{background-color:var(--color-surface-container-low)}.bg-transparent{background-color:transparent}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0{padding:0}.p-1{padding:.25rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.pb-16{padding-bottom:4rem}.pb-3\.5{padding-bottom:.875rem}.pt-10{padding-top:2.5rem}.pt-5{padding-top:1.25rem}.text-left{text-align:left}.text-center{text-align:center}.align-top{vertical-align:top}.font-body{font-family:var(--font-body),sans-serif}.font-label{font-family:var(--font-label),serif}.font-mono{font-family:var(--font-mono)}.font-title{font-family:var(--font-title)}.text-5xl{font-size:3rem;line-height:1}.text-\[0\.8em\]{font-size:.8em}.text-\[0\.9em\]{font-size:.9em}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-light{font-weight:300}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.ordinal{--tw-ordinal:ordinal}.ordinal,.tabular-nums{font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.tabular-nums{--tw-numeric-spacing:tabular-nums}.leading-\[1\.55\]{line-height:1.55}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.tracking-widest{letter-spacing:.1em}.text-on-surface{color:var(--color-on-surface)}.text-on-surface-variant{color:var(--color-on-surface-variant)}.text-outline{color:var(--color-outline)}.text-primary{color:var(--color-primary)}.text-secondary{color:var(--color-secondary)}.text-tertiary{color:var(--color-tertiary)}.underline{text-decoration-line:underline}.no-underline{text-decoration-line:none}.opacity-0{opacity:0}.opacity-30{opacity:.3}.opacity-40{opacity:.4}.opacity-60{opacity:.6}.shadow{--tw-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px -1px rgba(0,0,0,.1);--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color)}.shadow,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 rgba(0,0,0,.05);--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px)}.blur,.drop-shadow{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.drop-shadow{--tw-drop-shadow:drop-shadow(0 1px 2px rgba(0,0,0,.1)) drop-shadow(0 1px 1px rgba(0,0,0,.06))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter,-webkit-backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-300{transition-duration:.3s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.bg-outline-variant\/30{background-color:color-mix(in srgb,var(--color-outline-variant) 30%,transparent)}.border-tertiary\/40{border-color:color-mix(in srgb,var(--color-tertiary) 40%,transparent)}.hover\:border-primary:hover{border-color:var(--color-primary)}.hover\:border-tertiary:hover{border-color:var(--color-tertiary)}.hover\:bg-surface-container-low:hover{background-color:var(--color-surface-container-low)}.hover\:text-primary:hover{color:var(--color-primary)}.hover\:underline:hover{text-decoration-line:underline}.group:hover .group-hover\:bg-primary-container{background-color:var(--color-primary-container)}.group:hover .group-hover\:text-on-primary-container{color:var(--color-on-primary-container)}@media (min-width:640px){.sm\:gap-4{gap:1rem}.sm\:gap-5{gap:1.25rem}.sm\:px-8{padding-left:2rem;padding-right:2rem}}@media (min-width:768px){.md\:sticky{position:sticky}.md\:top-32{top:8rem}.md\:mb-12{margin-bottom:3rem}.md\:px-10{padding-left:2.5rem;padding-right:2.5rem}.md\:px-16{padding-left:4rem;padding-right:4rem}.md\:text-6xl{font-size:3.75rem;line-height:1}}@media (min-width:1024px){.lg\:sticky{position:sticky}.lg\:top-32{top:8rem}.lg\:gap-12{gap:3rem}}
|
data/assets/tailwind-play.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
#
|
|
2
|
+
# Kept as the readable theme binding. The shell does not load this file.
|
|
3
|
+
# Utilities are compiled to assets/css/tailwind.css (scripts/tailwind/build.sh).
|
|
3
4
|
# Named *-play.js so the Tailwind IntelliSense extension does not treat it as
|
|
4
5
|
# tailwind.config.js and fail with "tailwind is not defined" / _site duplicates.
|
|
5
6
|
---
|
|
@@ -30,7 +30,9 @@ module Pandorga
|
|
|
30
30
|
end
|
|
31
31
|
pages = pandorga["pages"]
|
|
32
32
|
if pages.nil?
|
|
33
|
-
warnings << "pandorga.pages is
|
|
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.
|
|
27
|
+
# GitHub tag: gem "pandorga", github: "alexandrelheinen/pandorga", tag: "v1.5.0"
|
|
28
28
|
gem "csv"
|
|
29
29
|
gem "base64"
|
|
30
30
|
RUBY
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Pandorga
|
|
4
|
+
# Sitemap and robots text. No Jekyll dependency, so the gate can call it
|
|
5
|
+
# without building a site.
|
|
6
|
+
module Discovery
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
def origin(config)
|
|
10
|
+
config = {} unless config.is_a?(Hash)
|
|
11
|
+
pandorga = config["pandorga"]
|
|
12
|
+
pandorga = {} unless pandorga.is_a?(Hash)
|
|
13
|
+
identity = pandorga["identity"]
|
|
14
|
+
identity = {} unless identity.is_a?(Hash)
|
|
15
|
+
url = identity["url"].to_s.strip
|
|
16
|
+
url = config["url"].to_s.strip if url.empty?
|
|
17
|
+
url.sub(%r{/\z}, "")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def absolute(origin, path)
|
|
21
|
+
path = path.to_s
|
|
22
|
+
return path if path.match?(%r{\Ahttps?://}i)
|
|
23
|
+
|
|
24
|
+
path = "/#{path}" unless path.start_with?("/")
|
|
25
|
+
path = "/" if path.empty?
|
|
26
|
+
base = origin.to_s.sub(%r{/\z}, "")
|
|
27
|
+
return path if base.empty?
|
|
28
|
+
|
|
29
|
+
"#{base}#{path}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def public_paths(pages)
|
|
33
|
+
Array(pages).filter_map do |page|
|
|
34
|
+
data = page_data(page)
|
|
35
|
+
next if data["sitemap"] == false
|
|
36
|
+
|
|
37
|
+
url = page.respond_to?(:url) ? page.url.to_s : page["url"].to_s
|
|
38
|
+
next if url.empty?
|
|
39
|
+
next if File.extname(url).match?(/\A\.(xml|txt|json)\z/i)
|
|
40
|
+
|
|
41
|
+
url
|
|
42
|
+
end.uniq
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def sitemap_xml(origin, paths)
|
|
46
|
+
locs = Array(paths).map { |path| absolute(origin, path) }.uniq
|
|
47
|
+
body = locs.map { |loc| " <url><loc>#{xml_escape(loc)}</loc></url>" }.join("\n")
|
|
48
|
+
<<~XML
|
|
49
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
50
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
51
|
+
#{body}
|
|
52
|
+
</urlset>
|
|
53
|
+
XML
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def robots_txt(sitemap_url)
|
|
57
|
+
<<~TXT
|
|
58
|
+
User-agent: *
|
|
59
|
+
Allow: /
|
|
60
|
+
Disallow: /studio/
|
|
61
|
+
|
|
62
|
+
Sitemap: #{sitemap_url}
|
|
63
|
+
TXT
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def xml_escape(value)
|
|
67
|
+
value.to_s.gsub("&", "&").gsub("<", "<").gsub(">", ">").gsub('"', """)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def page_data(page)
|
|
71
|
+
return page.data if page.respond_to?(:data) && page.data.is_a?(Hash)
|
|
72
|
+
|
|
73
|
+
data = page["data"]
|
|
74
|
+
data.is_a?(Hash) ? data : {}
|
|
75
|
+
end
|
|
76
|
+
private_class_method :page_data
|
|
77
|
+
end
|
|
78
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "jekyll"
|
|
4
|
+
require_relative "../../discovery"
|
|
5
|
+
|
|
6
|
+
module Pandorga
|
|
7
|
+
module Jekyll
|
|
8
|
+
# Writes /sitemap.xml and /robots.txt from the pages already generated.
|
|
9
|
+
class DiscoveryGenerator < ::Jekyll::Generator
|
|
10
|
+
safe true
|
|
11
|
+
priority :lowest
|
|
12
|
+
|
|
13
|
+
def generate(site)
|
|
14
|
+
origin = Pandorga::Discovery.origin(site.config)
|
|
15
|
+
paths = Pandorga::Discovery.public_paths(site.pages)
|
|
16
|
+
sitemap = Pandorga::Discovery.absolute(origin, "/sitemap.xml")
|
|
17
|
+
emit(site, "sitemap.xml", Pandorga::Discovery.sitemap_xml(origin, paths))
|
|
18
|
+
emit(site, "robots.txt", Pandorga::Discovery.robots_txt(sitemap))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def emit(site, name, content)
|
|
24
|
+
page = ::Jekyll::PageWithoutAFile.new(site, site.source, "", name)
|
|
25
|
+
page.data["layout"] = nil
|
|
26
|
+
page.data["sitemap"] = false
|
|
27
|
+
page.content = content
|
|
28
|
+
site.pages << page
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/pandorga/version.rb
CHANGED
data/scripts/cdn-allowlist.json
CHANGED
|
@@ -5,15 +5,12 @@
|
|
|
5
5
|
"https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-mml-chtml.js",
|
|
6
6
|
"https://cdn.jsdelivr.net/npm/d3@7.9.0/dist/d3.min.js",
|
|
7
7
|
"https://cdn.jsdelivr.net/npm/plotly.js-dist-min@3.1.0/plotly.min.js",
|
|
8
|
-
"https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.2.3/css/flag-icons.min.css"
|
|
9
|
-
"https://cdn.tailwindcss.com?plugins=forms,container-queries"
|
|
8
|
+
"https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.2.3/css/flag-icons.min.css"
|
|
10
9
|
],
|
|
11
10
|
"scan_globs": [
|
|
12
11
|
"_layouts",
|
|
13
12
|
"_includes",
|
|
14
13
|
"content/media/plots"
|
|
15
14
|
],
|
|
16
|
-
"exceptions": {
|
|
17
|
-
"tailwind_play_cdn": "Tailwind play CDN cannot be SRI-pinned; URL must match exactly."
|
|
18
|
-
}
|
|
15
|
+
"exceptions": {}
|
|
19
16
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Rebuild assets/css/tailwind.css. Not part of the site build or validate.sh.
|
|
3
|
+
# Requires tailwindcss 3.4 and @tailwindcss/forms on NODE_PATH or via npx.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
|
|
7
|
+
cd "$ROOT"
|
|
8
|
+
|
|
9
|
+
npx --yes tailwindcss@3.4.17 -c scripts/tailwind/tailwind.config.js \
|
|
10
|
+
-i scripts/tailwind/input.css \
|
|
11
|
+
-o assets/css/tailwind.css \
|
|
12
|
+
--minify
|
|
13
|
+
|
|
14
|
+
HEADER='/* Compiled Tailwind utilities (3.4.17, forms plugin). Replaces the Play CDN.
|
|
15
|
+
Regenerate with scripts/tailwind/build.sh after adding a utility class. */
|
|
16
|
+
'
|
|
17
|
+
TMP="$(mktemp)"
|
|
18
|
+
printf '%s' "$HEADER" | cat - assets/css/tailwind.css > "$TMP"
|
|
19
|
+
mv "$TMP" assets/css/tailwind.css
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
/* Opacity modifiers do not apply to colors stored as var(--token). */
|
|
6
|
+
.bg-outline-variant\/30 {
|
|
7
|
+
background-color: color-mix(in srgb, var(--color-outline-variant) 30%, transparent);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.border-tertiary\/40 {
|
|
11
|
+
border-color: color-mix(in srgb, var(--color-tertiary) 40%, transparent);
|
|
12
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const forms = require("@tailwindcss/forms");
|
|
3
|
+
|
|
4
|
+
const root = path.join(__dirname, "..", "..");
|
|
5
|
+
|
|
6
|
+
module.exports = {
|
|
7
|
+
content: [
|
|
8
|
+
path.join(root, "_layouts/**/*.{html,liquid}"),
|
|
9
|
+
path.join(root, "_includes/**/*.{html,liquid,js}"),
|
|
10
|
+
path.join(root, "assets/**/*.{js,html,liquid}"),
|
|
11
|
+
],
|
|
12
|
+
darkMode: ["selector", '[data-theme="dark"]'],
|
|
13
|
+
theme: {
|
|
14
|
+
extend: {
|
|
15
|
+
colors: {
|
|
16
|
+
primary: "var(--color-primary)",
|
|
17
|
+
secondary: "var(--color-secondary)",
|
|
18
|
+
tertiary: "var(--color-tertiary)",
|
|
19
|
+
"primary-container": "var(--color-primary-container)",
|
|
20
|
+
"secondary-container": "var(--color-secondary-container)",
|
|
21
|
+
"tertiary-container": "var(--color-tertiary-container)",
|
|
22
|
+
"on-primary": "var(--color-on-primary)",
|
|
23
|
+
"on-secondary": "var(--color-on-secondary)",
|
|
24
|
+
"on-tertiary": "var(--color-on-tertiary)",
|
|
25
|
+
"on-primary-container": "var(--color-on-primary-container)",
|
|
26
|
+
"on-secondary-container": "var(--color-on-secondary-container)",
|
|
27
|
+
"on-tertiary-container": "var(--color-on-tertiary-container)",
|
|
28
|
+
"on-surface": "var(--color-on-surface)",
|
|
29
|
+
"on-surface-variant": "var(--color-on-surface-variant)",
|
|
30
|
+
"on-background": "var(--color-on-background)",
|
|
31
|
+
outline: "var(--color-outline)",
|
|
32
|
+
"outline-variant": "var(--color-outline-variant)",
|
|
33
|
+
"gentle-faint": "var(--border-gentle-faint)",
|
|
34
|
+
"gentle-subtle": "var(--border-gentle-subtle)",
|
|
35
|
+
"gentle-divider": "var(--border-gentle-divider)",
|
|
36
|
+
gentle: "var(--border-gentle)",
|
|
37
|
+
"gentle-hover": "var(--border-gentle-hover)",
|
|
38
|
+
background: "var(--color-background)",
|
|
39
|
+
"background-secondary": "var(--color-background-secondary)",
|
|
40
|
+
surface: "var(--color-surface)",
|
|
41
|
+
"surface-bright": "var(--color-surface-bright)",
|
|
42
|
+
"surface-container-lowest": "var(--color-surface-container-lowest)",
|
|
43
|
+
"surface-container-low": "var(--color-surface-container-low)",
|
|
44
|
+
"surface-container": "var(--color-surface-container)",
|
|
45
|
+
"surface-container-high": "var(--color-surface-container-high)",
|
|
46
|
+
"surface-container-highest": "var(--color-surface-container-highest)",
|
|
47
|
+
"surface-variant": "var(--color-surface-variant)",
|
|
48
|
+
"surface-dim": "var(--color-surface-dim)",
|
|
49
|
+
"panel-contrast": "var(--color-panel-contrast)",
|
|
50
|
+
"surface-card": "var(--color-surface-card)",
|
|
51
|
+
"surface-card-contrast": "var(--color-surface-card-contrast)",
|
|
52
|
+
"surface-high": "var(--color-surface-high)",
|
|
53
|
+
"surface-high-contrast": "var(--color-surface-high-contrast)",
|
|
54
|
+
"surface-tint": "var(--color-surface-tint)",
|
|
55
|
+
"inverse-primary": "var(--color-inverse-primary)",
|
|
56
|
+
"inverse-surface": "var(--color-inverse-surface)",
|
|
57
|
+
"inverse-on-surface": "var(--color-inverse-on-surface)",
|
|
58
|
+
"primary-fixed": "var(--color-primary-fixed)",
|
|
59
|
+
"primary-fixed-dim": "var(--color-primary-fixed-dim)",
|
|
60
|
+
"secondary-fixed": "var(--color-secondary-fixed)",
|
|
61
|
+
"secondary-fixed-dim": "var(--color-secondary-fixed-dim)",
|
|
62
|
+
"tertiary-fixed": "var(--color-tertiary-fixed)",
|
|
63
|
+
"tertiary-fixed-dim": "var(--color-tertiary-fixed-dim)",
|
|
64
|
+
"on-primary-fixed": "var(--color-on-primary-fixed)",
|
|
65
|
+
"on-primary-fixed-variant": "var(--color-on-primary-fixed-variant)",
|
|
66
|
+
"on-secondary-fixed": "var(--color-on-secondary-fixed)",
|
|
67
|
+
"on-secondary-fixed-variant": "var(--color-on-secondary-fixed-variant)",
|
|
68
|
+
"on-tertiary-fixed": "var(--color-on-tertiary-fixed)",
|
|
69
|
+
"on-tertiary-fixed-variant": "var(--color-on-tertiary-fixed-variant)",
|
|
70
|
+
error: "var(--color-error)",
|
|
71
|
+
"on-error": "var(--color-on-error)",
|
|
72
|
+
"error-container": "var(--color-error-container)",
|
|
73
|
+
"on-error-container": "var(--color-on-error-container)",
|
|
74
|
+
"res-youtube": "var(--color-res-youtube)",
|
|
75
|
+
"res-podcast": "var(--color-res-podcast)",
|
|
76
|
+
"res-doc": "var(--color-res-doc)",
|
|
77
|
+
link: "var(--color-link)",
|
|
78
|
+
"link-hover": "var(--color-link-hover)",
|
|
79
|
+
},
|
|
80
|
+
fontFamily: {
|
|
81
|
+
title: ["var(--font-title)"],
|
|
82
|
+
subtitle: ["var(--font-subtitle)", "serif"],
|
|
83
|
+
label: ["var(--font-label)", "serif"],
|
|
84
|
+
body: ["var(--font-body)", "sans-serif"],
|
|
85
|
+
headline: ["var(--font-title)"],
|
|
86
|
+
editorial: ["var(--font-title)"],
|
|
87
|
+
serif: ["var(--font-title)"],
|
|
88
|
+
sans: ["var(--font-body)", "sans-serif"],
|
|
89
|
+
mono: ["var(--font-mono)"],
|
|
90
|
+
code: ["var(--font-code)"],
|
|
91
|
+
},
|
|
92
|
+
borderRadius: {
|
|
93
|
+
DEFAULT: "0.125rem",
|
|
94
|
+
lg: "0.25rem",
|
|
95
|
+
xl: "0.5rem",
|
|
96
|
+
full: "0.75rem",
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
safelist: ["text-primary", "text-secondary", "text-tertiary", "text-outline"],
|
|
101
|
+
plugins: [forms],
|
|
102
|
+
};
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
}
|
|
24
24
|
],
|
|
25
25
|
"selectors": [
|
|
26
|
-
"
|
|
26
|
+
"button.home-project-inventory-row",
|
|
27
27
|
"div.home-project-inventory-media",
|
|
28
28
|
"div.ledger-poster",
|
|
29
29
|
"div.home-project-inventory-code",
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
"span.home-project-inventory-resource"
|
|
36
36
|
],
|
|
37
37
|
"forbidden": [
|
|
38
|
-
"ledger-card-stretch"
|
|
38
|
+
"ledger-card-stretch",
|
|
39
|
+
"role=\"button\""
|
|
39
40
|
],
|
|
40
41
|
"contains": [
|
|
41
42
|
">02<",
|