pandorga 1.6.4 → 1.6.6
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 +39 -0
- data/README.md +6 -3
- data/_includes/content-runtime/00-config.html +1 -1
- data/_includes/theme/font-loader.html +14 -2
- data/_layouts/shell.html +25 -10
- data/lib/pandorga/version.rb +1 -1
- data/scripts/lighthouse-home.sh +42 -9
- data/scripts/lighthouse_server.py +74 -0
- data/scripts/test/test-lighthouse-policy.rb +42 -6
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ea34cfd7c17d2af28fcbd6a14c791f47b62fcf3a0c1c27b453f2467e6e4e101e
|
|
4
|
+
data.tar.gz: 7935fd040c610ffd52cab6587ecbcf31368a6097e21010f41b36ea92df013332
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 03e056b64de07a581a1b6293dd8a4db3aa40872219f170adfeaf25efe948317a62c04444db0cfe36cf67d8138ed003f9f832fc5c1150a0d84d174abc48232cdc
|
|
7
|
+
data.tar.gz: cd7dec364ba9a21e18c0ec05e60bd7eed94ca99a217b99a5cd2a67498c9778e51a78267ba4cad58bab5098020e7c75f8be2e8a5df3b84b4d23c37b07313ed16f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,44 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.6.6] — 2026-10-10
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
|
|
7
|
+
- The text faces and the flag stylesheet are requested after the load
|
|
8
|
+
event. A head link let a fast connection finish them before the largest
|
|
9
|
+
paint, and the simulator then counted those files as part of that paint.
|
|
10
|
+
The same templates scored 87 on the release run and 97 on the pull
|
|
11
|
+
request. `font-display: swap` stays.
|
|
12
|
+
- The markdown library loads with `defer`. The example home is already
|
|
13
|
+
HTML, so that script does not block the parser.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- A release below 90 does not publish. A bug-fix release whose notes
|
|
18
|
+
include `LIGHTHOUSE_BUGFIX=1` may still publish from 75 to 89.
|
|
19
|
+
|
|
20
|
+
No `pandorga:` config keys were added or renamed.
|
|
21
|
+
|
|
22
|
+
## [1.6.5] — 2026-10-10
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- The example home measured like the public site: compressed responses,
|
|
27
|
+
served concurrently. The stock one-thread HTTP/1.0 server was scoring
|
|
28
|
+
the same templates in the 70s while the live site on 1.6.3 scored 97.
|
|
29
|
+
- The Material Symbols face is about a megabyte. It is no longer linked
|
|
30
|
+
from the head. The shell adds that sheet after the load event, so the
|
|
31
|
+
simulator does not wait on it for the largest paint. The text font
|
|
32
|
+
sheet and the flag stylesheet use print media and apply on load.
|
|
33
|
+
- The icon box stays 1em.
|
|
34
|
+
|
|
35
|
+
### Changed
|
|
36
|
+
|
|
37
|
+
- Lighthouse mobile thresholds apply to releases. Pull requests and merges
|
|
38
|
+
to main only warn. The release build checks out the tag and fails below 75.
|
|
39
|
+
|
|
40
|
+
No `pandorga:` config keys were added or renamed.
|
|
41
|
+
|
|
3
42
|
## [1.6.4] — 2026-10-10
|
|
4
43
|
|
|
5
44
|
### Fixed
|
data/README.md
CHANGED
|
@@ -79,11 +79,14 @@ bundle exec pandorga serve
|
|
|
79
79
|
|
|
80
80
|
## Releases
|
|
81
81
|
|
|
82
|
-
Lighthouse mobile
|
|
82
|
+
Lighthouse mobile thresholds apply to releases. A stable release scores
|
|
83
83
|
90 or above. A score from 75 to 89 is acceptable only to ship a bug fix,
|
|
84
84
|
and an urgent performance campaign must then bring it back to 90 or above.
|
|
85
|
-
Below 75 is never acceptable.
|
|
86
|
-
|
|
85
|
+
Below 75 is never acceptable for a release. A pull request or a merge may
|
|
86
|
+
score lower when that is unavoidable to keep the work modular. The release
|
|
87
|
+
build publishes at 90 or above. Notes that include `LIGHTHOUSE_BUGFIX=1`
|
|
88
|
+
may publish a bug fix from 75 to 89. Pull requests and merges only warn.
|
|
89
|
+
The checklist is in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
87
90
|
|
|
88
91
|
## License
|
|
89
92
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<script src="https://cdn.jsdelivr.net/npm/marked@15.0.7/marked.min.js"></script>
|
|
1
|
+
<script defer src="https://cdn.jsdelivr.net/npm/marked@15.0.7/marked.min.js"></script>
|
|
2
2
|
<script>
|
|
3
3
|
window.ContentRuntimeConfig = {
|
|
4
4
|
contentBase: '{{ site.content_api_base_url | default: "" }}',
|
|
@@ -51,5 +51,17 @@
|
|
|
51
51
|
{% endunless %}
|
|
52
52
|
{% endif %}
|
|
53
53
|
{% assign fonts_href = fonts_href | append: "&display=swap" %}
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
{% comment %}
|
|
55
|
+
Not a head link. A preload or a print sheet is discovered immediately.
|
|
56
|
+
On a fast connection the faces finish before the largest paint, and the
|
|
57
|
+
simulator then waits on them. Add the sheet after load. display=swap stays.
|
|
58
|
+
{% endcomment %}
|
|
59
|
+
<script>
|
|
60
|
+
window.addEventListener('load', function () {
|
|
61
|
+
var link = document.createElement('link');
|
|
62
|
+
link.rel = 'stylesheet';
|
|
63
|
+
link.href = {{ fonts_href | jsonify }};
|
|
64
|
+
document.head.appendChild(link);
|
|
65
|
+
});
|
|
66
|
+
</script>
|
|
67
|
+
<noscript><link rel="stylesheet" href="{{ fonts_href }}" /></noscript>
|
data/_layouts/shell.html
CHANGED
|
@@ -59,10 +59,10 @@
|
|
|
59
59
|
<!-- Canonical URL -->
|
|
60
60
|
<link rel="canonical" href="{{ canonical_path | absolute_url }}" />
|
|
61
61
|
{%- comment -%}
|
|
62
|
-
Preconnect only.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
Preconnect only. The preload script below is parser-blocking. A
|
|
63
|
+
stylesheet before that script holds the parser until the font host
|
|
64
|
+
answers, so the ledger sheets and the hero cannot paint. The text-face
|
|
65
|
+
loader sits with the local sheets and adds its stylesheet after load.
|
|
66
66
|
{%- endcomment -%}
|
|
67
67
|
<link href="https://fonts.googleapis.com" rel="preconnect" />
|
|
68
68
|
<link crossorigin="" href="https://fonts.gstatic.com" rel="preconnect" />
|
|
@@ -117,15 +117,30 @@
|
|
|
117
117
|
{%- endfor -%}
|
|
118
118
|
{% include theme/font-loader.html %}
|
|
119
119
|
{%- comment -%}
|
|
120
|
-
Icons are not first paint.
|
|
121
|
-
|
|
122
|
-
|
|
120
|
+
Icons are not first paint. The face is about a megabyte. A link in the
|
|
121
|
+
head, even with print media, is discovered immediately and the simulator
|
|
122
|
+
then waits on that face for the largest paint. Add the sheet after load.
|
|
123
123
|
{%- endcomment -%}
|
|
124
124
|
{%- assign _symbols_href = "https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:wght,FILL@100..700,0..1&display=swap" -%}
|
|
125
|
-
<
|
|
126
|
-
|
|
125
|
+
<script>
|
|
126
|
+
window.addEventListener('load', function () {
|
|
127
|
+
var link = document.createElement('link');
|
|
128
|
+
link.rel = 'stylesheet';
|
|
129
|
+
link.href = {{ _symbols_href | jsonify }};
|
|
130
|
+
document.head.appendChild(link);
|
|
131
|
+
});
|
|
132
|
+
</script>
|
|
127
133
|
<noscript><link rel="stylesheet" href="{{ _symbols_href }}" /></noscript>
|
|
128
|
-
|
|
134
|
+
{%- assign _flags_href = "https://cdn.jsdelivr.net/gh/lipis/flag-icons@7.2.3/css/flag-icons.min.css" -%}
|
|
135
|
+
<script>
|
|
136
|
+
window.addEventListener('load', function () {
|
|
137
|
+
var link = document.createElement('link');
|
|
138
|
+
link.rel = 'stylesheet';
|
|
139
|
+
link.href = {{ _flags_href | jsonify }};
|
|
140
|
+
document.head.appendChild(link);
|
|
141
|
+
});
|
|
142
|
+
</script>
|
|
143
|
+
<noscript><link rel="stylesheet" href="{{ _flags_href }}" /></noscript>
|
|
129
144
|
<style>
|
|
130
145
|
:root { --drop-cap-lines: {{ site.drop_cap_lines | default: 2 }}; }
|
|
131
146
|
</style>
|
data/lib/pandorga/version.rb
CHANGED
data/scripts/lighthouse-home.sh
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# One Lighthouse mobile run against the built example home.
|
|
3
|
-
#
|
|
3
|
+
# Thresholds apply to releases. LIGHTHOUSE_MODE=enforce does not publish
|
|
4
|
+
# below 90 unless LIGHTHOUSE_BUGFIX=1, and that bug-fix release still
|
|
5
|
+
# fails below 75. LIGHTHOUSE_MODE=warn never fails the run. PLT-AC-24.
|
|
4
6
|
set -euo pipefail
|
|
5
7
|
|
|
6
8
|
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
@@ -9,6 +11,8 @@ PORT="${LIGHTHOUSE_PORT:-4173}"
|
|
|
9
11
|
OUT="${LIGHTHOUSE_REPORT:-/tmp/lighthouse-home.json}"
|
|
10
12
|
FAIL_BELOW=75
|
|
11
13
|
WARN_BELOW=90
|
|
14
|
+
MODE="${LIGHTHOUSE_MODE:-enforce}"
|
|
15
|
+
BUGFIX="${LIGHTHOUSE_BUGFIX:-}"
|
|
12
16
|
|
|
13
17
|
fail() {
|
|
14
18
|
echo "ERROR: $1" >&2
|
|
@@ -17,6 +21,10 @@ fail() {
|
|
|
17
21
|
|
|
18
22
|
step() { echo "==> $1"; }
|
|
19
23
|
|
|
24
|
+
if [[ "${MODE}" != "enforce" && "${MODE}" != "warn" ]]; then
|
|
25
|
+
fail "LIGHTHOUSE_MODE must be enforce or warn (got ${MODE})"
|
|
26
|
+
fi
|
|
27
|
+
|
|
20
28
|
[[ -f "${SITE}/index.html" ]] || fail "missing ${SITE}/index.html (run scripts/validate.sh first)"
|
|
21
29
|
|
|
22
30
|
if [[ -n "${CHROME_PATH:-}" && -x "${CHROME_PATH}" ]]; then
|
|
@@ -29,8 +37,8 @@ else
|
|
|
29
37
|
fail "Chrome is not installed"
|
|
30
38
|
fi
|
|
31
39
|
|
|
32
|
-
step "Serving ${SITE}"
|
|
33
|
-
python3
|
|
40
|
+
step "Serving ${SITE} (gzip, concurrent)"
|
|
41
|
+
python3 "${ROOT}/scripts/lighthouse_server.py" "${PORT}" "${SITE}" >/tmp/lighthouse-home-server.log 2>&1 &
|
|
34
42
|
SERVER_PID=$!
|
|
35
43
|
cleanup() {
|
|
36
44
|
kill "${SERVER_PID}" >/dev/null 2>&1 || true
|
|
@@ -59,11 +67,11 @@ npx --yes lighthouse@13.5.0 "http://127.0.0.1:${PORT}/" \
|
|
|
59
67
|
--chrome-path="${CHROME}" \
|
|
60
68
|
--chrome-flags="--headless=new --no-sandbox --disable-gpu"
|
|
61
69
|
|
|
62
|
-
python3 - "${OUT}" "${FAIL_BELOW}" "${WARN_BELOW}" <<'PY'
|
|
70
|
+
python3 - "${OUT}" "${FAIL_BELOW}" "${WARN_BELOW}" "${MODE}" "${BUGFIX}" <<'PY'
|
|
63
71
|
import json
|
|
64
72
|
import sys
|
|
65
73
|
|
|
66
|
-
path, fail_below, warn_below = sys.argv[1:]
|
|
74
|
+
path, fail_below, warn_below, mode, bugfix = sys.argv[1:]
|
|
67
75
|
fail_below = int(fail_below)
|
|
68
76
|
warn_below = int(warn_below)
|
|
69
77
|
report = json.load(open(path, encoding="utf-8"))
|
|
@@ -72,14 +80,39 @@ if raw is None:
|
|
|
72
80
|
print("ERROR: Lighthouse returned no performance score", file=sys.stderr)
|
|
73
81
|
sys.exit(1)
|
|
74
82
|
score = int(round(float(raw) * 100))
|
|
75
|
-
print(f"Lighthouse mobile performance: {score}")
|
|
76
|
-
|
|
83
|
+
print(f"Lighthouse mobile performance: {score} ({mode})")
|
|
84
|
+
audits = report.get("audits", {})
|
|
85
|
+
for key in (
|
|
86
|
+
"first-contentful-paint",
|
|
87
|
+
"largest-contentful-paint",
|
|
88
|
+
"speed-index",
|
|
89
|
+
"total-blocking-time",
|
|
90
|
+
"cumulative-layout-shift",
|
|
91
|
+
):
|
|
92
|
+
display = audits.get(key, {}).get("displayValue", "?")
|
|
93
|
+
print(f" {key}: {display}")
|
|
94
|
+
campaign = (
|
|
95
|
+
"A score from 75 to 89 is acceptable only to ship a bug fix. "
|
|
96
|
+
"An urgent performance campaign must bring it back to 90 or above."
|
|
97
|
+
)
|
|
98
|
+
if score < fail_below and mode == "enforce":
|
|
77
99
|
print(f"::error::Lighthouse mobile performance {score} is below {fail_below}")
|
|
78
100
|
sys.exit(1)
|
|
101
|
+
if mode == "enforce" and score < warn_below and bugfix != "1":
|
|
102
|
+
print(
|
|
103
|
+
f"::error::Lighthouse mobile performance {score} is below {warn_below}. "
|
|
104
|
+
+ campaign
|
|
105
|
+
+ " This release is not marked LIGHTHOUSE_BUGFIX=1, so it will not publish."
|
|
106
|
+
)
|
|
107
|
+
sys.exit(1)
|
|
108
|
+
if score < fail_below:
|
|
109
|
+
print(
|
|
110
|
+
f"::warning::Lighthouse mobile performance {score} is below {fail_below}. "
|
|
111
|
+
"Thresholds apply to releases. This run only warns."
|
|
112
|
+
)
|
|
79
113
|
if score < warn_below:
|
|
80
114
|
print(
|
|
81
115
|
f"::warning::Lighthouse mobile performance {score} is below {warn_below}. "
|
|
82
|
-
|
|
83
|
-
"An urgent performance campaign must bring it back to 90 or above."
|
|
116
|
+
+ campaign
|
|
84
117
|
)
|
|
85
118
|
PY
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Serve a built site the way the public host does.
|
|
3
|
+
|
|
4
|
+
Python's stock http.server speaks HTTP/1.0 on one thread and sends HTML
|
|
5
|
+
and CSS uncompressed. Lighthouse then scores the same templates far below
|
|
6
|
+
the live site, which compresses responses and serves them concurrently.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import gzip
|
|
10
|
+
import io
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
|
14
|
+
|
|
15
|
+
COMPRESSIBLE_EXACT = {
|
|
16
|
+
"application/javascript",
|
|
17
|
+
"application/json",
|
|
18
|
+
"application/xml",
|
|
19
|
+
"image/svg+xml",
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def compressible(ctype):
|
|
24
|
+
return ctype.startswith("text/") or ctype in COMPRESSIBLE_EXACT
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class Handler(SimpleHTTPRequestHandler):
|
|
28
|
+
protocol_version = "HTTP/1.1"
|
|
29
|
+
|
|
30
|
+
def send_head(self):
|
|
31
|
+
path = self.translate_path(self.path)
|
|
32
|
+
if os.path.isdir(path):
|
|
33
|
+
index = os.path.join(path, "index.html")
|
|
34
|
+
if os.path.isfile(index):
|
|
35
|
+
path = index
|
|
36
|
+
else:
|
|
37
|
+
return super().send_head()
|
|
38
|
+
|
|
39
|
+
ctype = self.guess_type(path)
|
|
40
|
+
accept = self.headers.get("Accept-Encoding", "")
|
|
41
|
+
if "gzip" not in accept or not compressible(ctype):
|
|
42
|
+
return super().send_head()
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
with open(path, "rb") as raw:
|
|
46
|
+
data = raw.read()
|
|
47
|
+
except OSError:
|
|
48
|
+
self.send_error(404, "File not found")
|
|
49
|
+
return None
|
|
50
|
+
|
|
51
|
+
body = gzip.compress(data, compresslevel=6)
|
|
52
|
+
self.send_response(200)
|
|
53
|
+
self.send_header("Content-Type", ctype)
|
|
54
|
+
self.send_header("Content-Encoding", "gzip")
|
|
55
|
+
self.send_header("Vary", "Accept-Encoding")
|
|
56
|
+
self.send_header("Content-Length", str(len(body)))
|
|
57
|
+
self.end_headers()
|
|
58
|
+
return io.BytesIO(body)
|
|
59
|
+
|
|
60
|
+
def log_message(self, fmt, *args):
|
|
61
|
+
return
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def main():
|
|
65
|
+
if len(sys.argv) != 3:
|
|
66
|
+
print("usage: lighthouse_server.py PORT DIRECTORY", file=sys.stderr)
|
|
67
|
+
sys.exit(2)
|
|
68
|
+
port = int(sys.argv[1])
|
|
69
|
+
os.chdir(sys.argv[2])
|
|
70
|
+
ThreadingHTTPServer(("127.0.0.1", port), Handler).serve_forever()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
if __name__ == "__main__":
|
|
74
|
+
main()
|
|
@@ -22,12 +22,17 @@ shell = ROOT.join("_layouts/shell.html").read
|
|
|
22
22
|
base = ROOT.join("assets/css/base.css").read
|
|
23
23
|
script = ROOT.join("scripts/lighthouse-home.sh").read
|
|
24
24
|
workflow = ROOT.join(".github/workflows/validate.yml").read
|
|
25
|
+
release = ROOT.join(".github/workflows/publish-gem.yml").read
|
|
25
26
|
|
|
26
27
|
docs.each do |name, text|
|
|
27
|
-
|
|
28
|
-
fail!("#{name} does not
|
|
29
|
-
fail!("#{name} does not
|
|
30
|
-
fail!("#{name} does not
|
|
28
|
+
flat = text.gsub(/\s+/, " ")
|
|
29
|
+
fail!("#{name} does not require 90 or above") unless flat.include?("90 or above")
|
|
30
|
+
fail!("#{name} does not limit 75 to 89 to a bug fix") unless flat.include?("only to ship a bug fix")
|
|
31
|
+
fail!("#{name} does not require the performance campaign") unless flat.include?("urgent performance campaign")
|
|
32
|
+
fail!("#{name} does not forbid a score below 75") unless flat.include?("Below 75 is never acceptable")
|
|
33
|
+
fail!("#{name} does not limit the floors to releases") unless flat.include?("apply to releases")
|
|
34
|
+
fail!("#{name} does not allow a lower pull-request score") unless flat.include?("may score lower")
|
|
35
|
+
fail!("#{name} does not allow modular work") unless flat.include?("modular")
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
spec = docs.fetch("spec")
|
|
@@ -37,15 +42,46 @@ fail!("spec dropped the slower-release reason") unless spec.include?("slower rel
|
|
|
37
42
|
fail!("contributing dropped the slower-release reason") unless contributing.include?("slower release is better than a broken one")
|
|
38
43
|
|
|
39
44
|
fail!("lighthouse script is not the CI check") unless workflow.include?("./scripts/lighthouse-home.sh")
|
|
45
|
+
fail!("pull requests still fail the lighthouse gate") unless workflow.include?("LIGHTHOUSE_MODE: warn")
|
|
46
|
+
fail!("release build does not enforce the score") unless release.include?("LIGHTHOUSE_MODE: enforce")
|
|
47
|
+
fail!("tag builds do not run the release gate") unless release.include?('tags: ["v*"]')
|
|
40
48
|
fail!("lighthouse script lost the fail floor") unless script.include?("FAIL_BELOW=75")
|
|
41
49
|
fail!("lighthouse script lost the warn floor") unless script.include?("WARN_BELOW=90")
|
|
50
|
+
fail!("lighthouse script lost enforce mode") unless script.include?('LIGHTHOUSE_MODE:-enforce')
|
|
51
|
+
fail!("warn mode still fails the run") unless script.include?('mode == "enforce"')
|
|
52
|
+
fail!("a non-bug-fix release can publish below 90") unless script.include?('bugfix != "1"')
|
|
53
|
+
fail!("release workflow cannot mark a bug fix") unless release.include?("LIGHTHOUSE_BUGFIX")
|
|
54
|
+
fail!("spec still publishes a feature below 90") unless spec.include?("LIGHTHOUSE_BUGFIX=1")
|
|
55
|
+
fail!("contributing still publishes a feature below 90") unless contributing.include?("LIGHTHOUSE_BUGFIX=1")
|
|
56
|
+
fail!("readme still publishes a feature below 90") unless docs.fetch("readme").include?("LIGHTHOUSE_BUGFIX=1")
|
|
42
57
|
fail!("lighthouse script is not a single mobile run") unless script.include?("--form-factor=mobile")
|
|
43
58
|
fail!("lighthouse script repeats runs") if script.include?("--repeat")
|
|
59
|
+
fail!("example server is still one-thread HTTP/1.0") if script.include?("python3 -m http.server")
|
|
60
|
+
server = ROOT.join("scripts/lighthouse_server.py").read
|
|
61
|
+
fail!("example server does not gzip") unless server.include?('Content-Encoding", "gzip"')
|
|
62
|
+
fail!("example server is not concurrent") unless server.include?("ThreadingHTTPServer")
|
|
63
|
+
fail!("icon face is preloaded") if shell.include?("rel=\"preload\" as=\"style\" href=\"{{ _symbols_href }}\"")
|
|
44
64
|
|
|
45
65
|
screen = shell.sub(%r{<noscript>.*?</noscript>}m, "")
|
|
46
66
|
fail!("Material Symbols sheet is missing") unless shell.include?("Material+Symbols+Outlined")
|
|
47
|
-
fail!("
|
|
48
|
-
fail!("screen still has a
|
|
67
|
+
fail!("icon sheet is not deferred until load") unless screen.include?("addEventListener('load'")
|
|
68
|
+
fail!("screen still has a Material Symbols stylesheet link") if screen.match?(/<link\b[^>]*Material\+Symbols/)
|
|
69
|
+
fail!("screen still has a flag stylesheet link") if screen.match?(/<link\b[^>]*flag-icons/)
|
|
70
|
+
fail!("flag sheet is not deferred until load") unless screen.include?("flag-icons@7.2.3")
|
|
71
|
+
|
|
72
|
+
fonts = ROOT.join("_includes/theme/font-loader.html").read
|
|
73
|
+
font_screen = fonts.sub(%r{<noscript>.*?</noscript>}m, "")
|
|
74
|
+
fail!("text faces are preloaded") if fonts.include?('rel="preload"')
|
|
75
|
+
fail!("text face sheet is not deferred until load") unless font_screen.include?("addEventListener('load'")
|
|
76
|
+
fail!("screen still has a text-face stylesheet link") if font_screen.match?(/<link\b/)
|
|
77
|
+
|
|
78
|
+
marked = ROOT.join("_includes/content-runtime/00-config.html").read
|
|
79
|
+
fail!("markdown library still blocks parsing") unless marked.include?("<script defer ")
|
|
80
|
+
fail!("markdown library source changed") unless marked.include?("marked@15.0.7/marked.min.js")
|
|
81
|
+
|
|
82
|
+
fail!("spec still discovers text faces from the head") unless spec.include?("text-face stylesheet is not a head link")
|
|
83
|
+
fail!("spec still lets the markdown library block parsing") unless spec.include?("markdown library loads with `defer`")
|
|
84
|
+
fail!("lighthouse script hides the metric breakdown") unless script.include?("largest-contentful-paint")
|
|
49
85
|
|
|
50
86
|
icon = base[/\.material-symbols-outlined\.material-symbols-outlined \{.*?\n\}/m]
|
|
51
87
|
fail!("icon rule missing") unless icon
|
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.6.
|
|
4
|
+
version: 1.6.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -323,6 +323,7 @@ files:
|
|
|
323
323
|
- scripts/lib/withdrawn_public_objects.rb
|
|
324
324
|
- scripts/lib/writing_index_contract.rb
|
|
325
325
|
- scripts/lighthouse-home.sh
|
|
326
|
+
- scripts/lighthouse_server.py
|
|
326
327
|
- scripts/pdf/md-to-pdf.mjs
|
|
327
328
|
- scripts/pdf/md-to-pdf.sh
|
|
328
329
|
- scripts/tailwind/build.sh
|