pandorga 1.6.7 → 1.6.8
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 +34 -0
- data/README.md +3 -2
- data/_includes/page/content-runtime.html +3 -0
- data/_includes/page/network-graph.html +5 -2
- data/_includes/page/timeline-section.html +13 -1
- data/_includes/theme/favicons.html +3 -1
- data/_layouts/articles.html +5 -2
- data/_layouts/bibliography.html +5 -2
- data/_layouts/blog.html +5 -2
- data/_layouts/cv.html +5 -2
- data/_layouts/home.html +10 -3
- data/_layouts/projects.html +5 -2
- data/_layouts/resources.html +5 -2
- data/_layouts/shell.html +6 -1
- data/assets/css/ledger/home.css +20 -0
- data/assets/css/ledger/rascunhos.css +40 -2
- data/assets/icons/apple-touch-icon.png +0 -0
- data/assets/icons/favicon-32.png +0 -0
- data/assets/icons/favicon.ico +0 -0
- data/assets/icons/favicon.svg +23 -0
- data/assets/icons/icon-192.png +0 -0
- data/assets/icons/icon-32.png +0 -0
- data/assets/icons/icon-512.png +0 -0
- data/assets/icons/icon-maskable-192.png +0 -0
- data/assets/icons/icon-maskable-512.png +0 -0
- data/assets/icons/studio-apple-touch-icon.png +0 -0
- data/assets/icons/studio-icon-192.png +0 -0
- data/assets/icons/studio-icon-512.png +0 -0
- data/assets/icons/studio-logo-32.png +0 -0
- data/assets/icons/studio-logo.ico +0 -0
- data/assets/icons/studio-logo.svg +25 -5
- data/assets/icons/studio-maskable-192.png +0 -0
- data/assets/icons/studio-maskable-512.png +0 -0
- data/lib/pandorga/jekyll/plugins/web_manifest.rb +81 -0
- data/lib/pandorga/version.rb +1 -1
- data/scripts/check_home_lists.mjs +209 -0
- data/scripts/lighthouse-home.sh +6 -0
- data/scripts/render-pwa-icons.py +141 -0
- data/scripts/test/test-home-articles.rb +30 -0
- data/scripts/test/test-home-lists.rb +74 -0
- data/scripts/test/test-pwa-icons.rb +280 -0
- data/scripts/test/test-rascunhos-licence.rb +43 -0
- data/scripts/validate.sh +4 -0
- data/studio/index.html +4 -1
- data/studio-app/index.html +4 -1
- metadata +24 -1
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# PLT-AC-28. The site and Studio launchers share the site stamp. Studio adds
|
|
5
|
+
# one badge. Manifests name maskable icons, and those icons keep their art
|
|
6
|
+
# inside the center 80% circle.
|
|
7
|
+
|
|
8
|
+
require "jekyll"
|
|
9
|
+
require "json"
|
|
10
|
+
require "pathname"
|
|
11
|
+
require "tmpdir"
|
|
12
|
+
require "zlib"
|
|
13
|
+
|
|
14
|
+
ROOT = Pathname.new(__dir__).join("..", "..").expand_path
|
|
15
|
+
|
|
16
|
+
def fail!(message)
|
|
17
|
+
warn "FAIL test-pwa-icons: #{message}"
|
|
18
|
+
exit 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
PLATE = [0x5e, 0x5d, 0x59].freeze
|
|
22
|
+
BADGE = [0xb8, 0xb7, 0xae].freeze
|
|
23
|
+
PRIMARY = [0xa4, 0xc8, 0xda].freeze
|
|
24
|
+
|
|
25
|
+
def read_png(path)
|
|
26
|
+
data = File.binread(path)
|
|
27
|
+
fail!("#{path} is not a PNG") unless data.start_with?("\x89PNG\r\n\x1a\n".b)
|
|
28
|
+
|
|
29
|
+
pos = 8
|
|
30
|
+
width = height = nil
|
|
31
|
+
idat = +"".b
|
|
32
|
+
while pos + 12 <= data.bytesize
|
|
33
|
+
length = data[pos, 4].unpack1("N")
|
|
34
|
+
type = data[pos + 4, 4]
|
|
35
|
+
chunk = data[pos + 8, length]
|
|
36
|
+
pos += 12 + length
|
|
37
|
+
case type
|
|
38
|
+
when "IHDR"
|
|
39
|
+
width, height, bit, color, _comp, _filter, interlace = chunk.unpack("NNCCCCC")
|
|
40
|
+
fail!("#{path} is not 8-bit RGB") unless bit == 8 && color == 2 && interlace == 0
|
|
41
|
+
when "IDAT"
|
|
42
|
+
idat << chunk
|
|
43
|
+
when "IEND"
|
|
44
|
+
break
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
fail!("#{path} has no image") unless width && height && !idat.empty?
|
|
48
|
+
|
|
49
|
+
raw = Zlib::Inflate.inflate(idat)
|
|
50
|
+
stride = width * 3
|
|
51
|
+
row_start = 0
|
|
52
|
+
prev = Array.new(stride, 0)
|
|
53
|
+
pixels = []
|
|
54
|
+
height.times do
|
|
55
|
+
filter = raw.getbyte(row_start)
|
|
56
|
+
row = raw.byteslice(row_start + 1, stride).bytes
|
|
57
|
+
row_start += stride + 1
|
|
58
|
+
out = Array.new(stride, 0)
|
|
59
|
+
stride.times do |i|
|
|
60
|
+
left = i >= 3 ? out[i - 3] : 0
|
|
61
|
+
up = prev[i]
|
|
62
|
+
up_left = i >= 3 ? prev[i - 3] : 0
|
|
63
|
+
value = row[i]
|
|
64
|
+
out[i] = case filter
|
|
65
|
+
when 0 then value
|
|
66
|
+
when 1 then (value + left) & 255
|
|
67
|
+
when 2 then (value + up) & 255
|
|
68
|
+
when 3 then (value + ((left + up) / 2)) & 255
|
|
69
|
+
when 4
|
|
70
|
+
estimate = left + up - up_left
|
|
71
|
+
nearest = [[estimate - left, left], [estimate - up, up], [estimate - up_left, up_left]]
|
|
72
|
+
nearest.map! { |distance, sample| [distance.abs, sample] }
|
|
73
|
+
(value + nearest.min_by(&:first).last) & 255
|
|
74
|
+
else
|
|
75
|
+
fail!("#{path} uses PNG filter #{filter}")
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
prev = out
|
|
79
|
+
width.times { |x| pixels << out[x * 3, 3] }
|
|
80
|
+
end
|
|
81
|
+
[width, height, pixels]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def pixel(image, x, y)
|
|
85
|
+
width, _height, pixels = image
|
|
86
|
+
pixels[(y * width) + x]
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def assert_margin(path, image)
|
|
90
|
+
width, height, = image
|
|
91
|
+
band = (width * 0.10).floor
|
|
92
|
+
samples = [
|
|
93
|
+
[0, 0],
|
|
94
|
+
[width - 1, 0],
|
|
95
|
+
[0, height - 1],
|
|
96
|
+
[width - 1, height - 1],
|
|
97
|
+
[band - 1, height / 2],
|
|
98
|
+
[width - band, height / 2],
|
|
99
|
+
[width / 2, band - 1],
|
|
100
|
+
[width / 2, height - band]
|
|
101
|
+
]
|
|
102
|
+
samples.each do |x, y|
|
|
103
|
+
got = pixel(image, x, y)
|
|
104
|
+
fail!("#{path} pixel #{x},#{y} is #{got.inspect}, outside the safe zone") unless got == PLATE
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
logo = ROOT.join("_includes/theme/site-logo.html").read
|
|
109
|
+
site_svg = ROOT.join("assets/icons/favicon.svg").read
|
|
110
|
+
studio_svg = ROOT.join("assets/icons/studio-logo.svg").read
|
|
111
|
+
%w[0,0 23,0 15,17 0,20 23,0 32,0 32,32 17,21 15,17 0,20 15,17 17,21 32,32 0,32].each do |point|
|
|
112
|
+
fail!("site stamp lost the point #{point}") unless logo.include?(point) && site_svg.include?(point) && studio_svg.include?(point)
|
|
113
|
+
end
|
|
114
|
+
fail!("Studio icon is still the hexagon") if studio_svg.include?("16,1") || studio_svg.include?("30,9")
|
|
115
|
+
fail!("site icon carries the Studio badge") if site_svg.include?("badge")
|
|
116
|
+
fail!("Studio icon has no badge") unless studio_svg.include?('class="badge"') && studio_svg.include?('x="20.32"')
|
|
117
|
+
fail!("favicon names the owner") if site_svg.match?(/Heinen|Alexandre/i)
|
|
118
|
+
|
|
119
|
+
shell = ROOT.join("_includes/theme/favicons.html").read
|
|
120
|
+
fail!("shell does not link the site manifest") unless shell.include?('href="/site.webmanifest"')
|
|
121
|
+
studio = ROOT.join("studio/index.html").read
|
|
122
|
+
studio_app = ROOT.join("studio-app/index.html").read
|
|
123
|
+
def ink_bounds(image)
|
|
124
|
+
width, height, pixels = image
|
|
125
|
+
min_x, min_y = width, height
|
|
126
|
+
max_x, max_y = -1, -1
|
|
127
|
+
height.times do |y|
|
|
128
|
+
width.times do |x|
|
|
129
|
+
next if pixels[(y * width) + x] == PLATE
|
|
130
|
+
|
|
131
|
+
min_x = x if x < min_x
|
|
132
|
+
min_y = y if y < min_y
|
|
133
|
+
max_x = x if x > max_x
|
|
134
|
+
max_y = y if y > max_y
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
[min_x, min_y, max_x, max_y]
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def ico_sizes(path)
|
|
141
|
+
data = File.binread(path)
|
|
142
|
+
fail!("#{path} is not an ICO") unless data.bytesize >= 6 && data.getbyte(2) == 1
|
|
143
|
+
|
|
144
|
+
count = data[4, 2].unpack1("v")
|
|
145
|
+
count.times.map do |index|
|
|
146
|
+
entry = data[6 + (index * 16), 2]
|
|
147
|
+
width = entry.getbyte(0)
|
|
148
|
+
height = entry.getbyte(1)
|
|
149
|
+
width = 256 if width.zero?
|
|
150
|
+
height = 256 if height.zero?
|
|
151
|
+
[width, height]
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
fail!("site and Studio SVGs use different stamp scales") unless site_svg.include?("translate(7.68 7.68) scale(0.52)") &&
|
|
156
|
+
studio_svg.include?("translate(7.68 7.68) scale(0.52)")
|
|
157
|
+
|
|
158
|
+
[studio, studio_app].each do |html|
|
|
159
|
+
fail!("Studio favicon link is missing") unless html.include?('href="/assets/icons/studio-logo.ico"')
|
|
160
|
+
fail!("Studio does not link its manifest") unless html.include?('href="/studio.webmanifest"')
|
|
161
|
+
fail!("Studio apple touch icon is the 32px file") if html.include?('apple-touch-icon" href="/assets/icons/studio-logo-32.png"')
|
|
162
|
+
fail!("Studio apple touch icon is missing") unless html.include?("/assets/icons/studio-apple-touch-icon.png")
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def build_manifests(config_yaml)
|
|
166
|
+
Dir.mktmpdir do |dir|
|
|
167
|
+
File.write(File.join(dir, "_config.yml"), config_yaml)
|
|
168
|
+
File.write(File.join(dir, "index.html"), "hello\n")
|
|
169
|
+
config = Jekyll.configuration(
|
|
170
|
+
"source" => dir,
|
|
171
|
+
"destination" => File.join(dir, "_site"),
|
|
172
|
+
"quiet" => true,
|
|
173
|
+
"safe" => false
|
|
174
|
+
)
|
|
175
|
+
site = Jekyll::Site.new(config)
|
|
176
|
+
site.reset
|
|
177
|
+
site.read
|
|
178
|
+
Pandorga::Jekyll::WebManifestGenerator.new.generate(site)
|
|
179
|
+
site.pages.select { |page| page.name.end_with?(".webmanifest") }.to_h do |page|
|
|
180
|
+
fail!("#{page.name} would enter the sitemap") unless page.data["sitemap"] == false
|
|
181
|
+
[page.name, JSON.parse(page.content)]
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
require_relative "../../lib/pandorga/jekyll/plugins/web_manifest"
|
|
187
|
+
|
|
188
|
+
named = build_manifests(<<~YAML)
|
|
189
|
+
title: Fallback Title
|
|
190
|
+
pandorga:
|
|
191
|
+
identity:
|
|
192
|
+
name: Example Person
|
|
193
|
+
short_name: Example
|
|
194
|
+
YAML
|
|
195
|
+
site = named["site.webmanifest"]
|
|
196
|
+
studio_manifest = named["studio.webmanifest"]
|
|
197
|
+
fail!("manifests were not written") unless site && studio_manifest
|
|
198
|
+
fail!("site name ignored identity") unless site["name"] == "Example Person" && site["short_name"] == "Example"
|
|
199
|
+
fail!("site scope is not the origin root") unless site["id"] == "/" && site["scope"] == "/" && site["start_url"] == "/"
|
|
200
|
+
fail!("Studio is not its own app") unless studio_manifest["id"] == "/studio/" && studio_manifest["scope"] == "/studio/"
|
|
201
|
+
fail!("Studio name changed") unless studio_manifest["name"] == "Studio" && studio_manifest["start_url"] == "/studio/"
|
|
202
|
+
fail!("launcher plate changed") unless site["background_color"] == "#5e5d59" && site["theme_color"] == "#5e5d59"
|
|
203
|
+
|
|
204
|
+
{
|
|
205
|
+
"site.webmanifest" => [
|
|
206
|
+
["/assets/icons/icon-512.png", "512x512", "any"],
|
|
207
|
+
["/assets/icons/icon-maskable-512.png", "512x512", "maskable"],
|
|
208
|
+
["/assets/icons/icon-192.png", "192x192", "any"],
|
|
209
|
+
["/assets/icons/icon-maskable-192.png", "192x192", "maskable"]
|
|
210
|
+
],
|
|
211
|
+
"studio.webmanifest" => [
|
|
212
|
+
["/assets/icons/studio-icon-512.png", "512x512", "any"],
|
|
213
|
+
["/assets/icons/studio-maskable-512.png", "512x512", "maskable"],
|
|
214
|
+
["/assets/icons/studio-icon-192.png", "192x192", "any"],
|
|
215
|
+
["/assets/icons/studio-maskable-192.png", "192x192", "maskable"]
|
|
216
|
+
]
|
|
217
|
+
}.each do |name, expected|
|
|
218
|
+
got = named.fetch(name).fetch("icons").map { |icon| [icon["src"], icon["sizes"], icon["purpose"]] }
|
|
219
|
+
fail!("#{name} icons are #{got.inspect}") unless got == expected
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
fallback = build_manifests("title: \"\"\n")
|
|
223
|
+
fail!("empty identity must still name the app") unless fallback["site.webmanifest"]["name"] == "Site"
|
|
224
|
+
|
|
225
|
+
[
|
|
226
|
+
["assets/icons/icon-512.png", "assets/icons/studio-icon-512.png", 512],
|
|
227
|
+
["assets/icons/icon-maskable-512.png", "assets/icons/studio-maskable-512.png", 512],
|
|
228
|
+
["assets/icons/icon-192.png", "assets/icons/studio-icon-192.png", 192],
|
|
229
|
+
["assets/icons/icon-maskable-192.png", "assets/icons/studio-maskable-192.png", 192],
|
|
230
|
+
["assets/icons/apple-touch-icon.png", "assets/icons/studio-apple-touch-icon.png", 180],
|
|
231
|
+
["assets/icons/favicon-32.png", "assets/icons/studio-logo-32.png", 32],
|
|
232
|
+
["assets/icons/icon-32.png", "assets/icons/studio-logo-32.png", 32]
|
|
233
|
+
].each do |site_rel, studio_rel, size|
|
|
234
|
+
site_image = read_png(ROOT.join(site_rel))
|
|
235
|
+
studio_image = read_png(ROOT.join(studio_rel))
|
|
236
|
+
fail!("#{site_rel} is #{site_image[0]}x#{site_image[1]}") unless site_image[0] == size && site_image[1] == size
|
|
237
|
+
fail!("#{studio_rel} canvas is #{studio_image[0]}x#{studio_image[1]}") unless studio_image[0] == size && studio_image[1] == size
|
|
238
|
+
|
|
239
|
+
site_ink = ink_bounds(site_image)
|
|
240
|
+
studio_ink = ink_bounds(studio_image)
|
|
241
|
+
fail!("#{studio_rel} art bounds #{studio_ink.inspect} differ from #{site_ink.inspect}") unless site_ink == studio_ink
|
|
242
|
+
|
|
243
|
+
min_x, min_y, max_x, max_y = site_ink
|
|
244
|
+
pad_right = size - 1 - max_x
|
|
245
|
+
pad_bottom = size - 1 - max_y
|
|
246
|
+
fail!("#{site_rel} padding is uneven #{site_ink.inspect}") unless min_x == min_y && pad_right == min_x && pad_bottom == min_y
|
|
247
|
+
|
|
248
|
+
radius = size * 0.40
|
|
249
|
+
center = size / 2.0
|
|
250
|
+
corner = Math.hypot((max_x + 1) - center, (max_y + 1) - center)
|
|
251
|
+
fail!("#{site_rel} art leaves the safe zone (#{corner} > #{radius})") if corner > radius
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
site_ico = ico_sizes(ROOT.join("assets/icons/favicon.ico"))
|
|
255
|
+
studio_ico = ico_sizes(ROOT.join("assets/icons/studio-logo.ico"))
|
|
256
|
+
fail!("favicon canvases differ: #{site_ico.inspect} vs #{studio_ico.inspect}") unless site_ico == studio_ico && site_ico == [[16, 16], [32, 32]]
|
|
257
|
+
|
|
258
|
+
[512, 192].each do |size|
|
|
259
|
+
site_path = ROOT.join("assets/icons/icon-maskable-#{size}.png")
|
|
260
|
+
studio_path = ROOT.join("assets/icons/studio-maskable-#{size}.png")
|
|
261
|
+
site_image = read_png(site_path)
|
|
262
|
+
studio_image = read_png(studio_path)
|
|
263
|
+
fail!("site maskable is #{site_image[0]} square") unless site_image[0] == size && site_image[1] == size
|
|
264
|
+
fail!("Studio maskable is #{studio_image[0]} square") unless studio_image[0] == size && studio_image[1] == size
|
|
265
|
+
assert_margin(site_path, site_image)
|
|
266
|
+
assert_margin(studio_path, studio_image)
|
|
267
|
+
|
|
268
|
+
mark = (size * 0.24).round + (2.0 / 32 * size * 0.52).round
|
|
269
|
+
fail!("site stamp is not the pastel triad") unless pixel(site_image, mark, mark) == PRIMARY
|
|
270
|
+
fail!("Studio stamp is not the pastel triad") unless pixel(studio_image, mark, mark) == PRIMARY
|
|
271
|
+
|
|
272
|
+
badge_at = (size * 0.68).round
|
|
273
|
+
fail!("site icon has the Studio badge") if pixel(site_image, badge_at, badge_at) == BADGE
|
|
274
|
+
fail!("Studio badge is missing") unless pixel(studio_image, badge_at, badge_at) == BADGE
|
|
275
|
+
|
|
276
|
+
differ = site_image[2].zip(studio_image[2]).count { |left, right| left != right }
|
|
277
|
+
fail!("Studio icon is a different picture (#{differ} pixels)") unless differ.positive? && differ < (size * size * 0.03)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
puts "PASS test-pwa-icons"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# PLT-AC-27. Below 1024px the Rascunhos licence follows the entries.
|
|
5
|
+
# writing.css had this order. The per-page sheet split stopped loading that
|
|
6
|
+
# file on the blog layout, and `.rascunhos-body { display: block }` put the
|
|
7
|
+
# licence back above the texts. The winning rule lives in rascunhos.css.
|
|
8
|
+
|
|
9
|
+
require "pathname"
|
|
10
|
+
|
|
11
|
+
ROOT = Pathname.new(__dir__).join("..", "..").expand_path
|
|
12
|
+
|
|
13
|
+
def fail!(message)
|
|
14
|
+
warn "FAIL test-rascunhos-licence: #{message}"
|
|
15
|
+
exit 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
shell = ROOT.join("_layouts/shell.html").read
|
|
19
|
+
blog = shell[/when "blog".*?assign _ledger = "([^"]+)"/m, 1]
|
|
20
|
+
fail!("blog layout has no ledger list") unless blog
|
|
21
|
+
sheets = blog.split("|")
|
|
22
|
+
rascunhos_at = sheets.index("rascunhos")
|
|
23
|
+
writing_at = sheets.index("writing")
|
|
24
|
+
fail!("blog layout does not load rascunhos.css") unless rascunhos_at
|
|
25
|
+
fail!("blog layout does not load writing.css after rascunhos.css") unless writing_at && writing_at > rascunhos_at
|
|
26
|
+
|
|
27
|
+
css = ROOT.join("assets/css/ledger/rascunhos.css").read
|
|
28
|
+
block_at = css.index(".rascunhos-body {\n display: block;")
|
|
29
|
+
rule_at = css.index(".rascunhos-main .rascunhos-body {\n display: flex;")
|
|
30
|
+
licence_at = css.index(".rascunhos-main .writing-rail-licence {")
|
|
31
|
+
ledger_at = css.index(".rascunhos-main .rascunhos-body>.rascunhos-ledger {")
|
|
32
|
+
hidden_at = css.index(".rascunhos-main .rascunhos-body.hidden {\n display: none;")
|
|
33
|
+
|
|
34
|
+
fail!("rascunhos body is no longer display:block at rest") unless block_at
|
|
35
|
+
fail!("mobile column is missing from rascunhos.css") unless rule_at && rule_at > block_at
|
|
36
|
+
fail!("mobile column is not limited to the disclosure width") unless css.index("@media (max-width: 1023px)")&.< rule_at
|
|
37
|
+
fail!("licence has no colophon order") unless licence_at && css[licence_at, 180].include?("order: 2")
|
|
38
|
+
fail!("ledger is not ordered ahead of the licence") unless ledger_at && ledger_at < licence_at && css[ledger_at, 120].include?("order: 1")
|
|
39
|
+
fail!("detail view can no longer hide the listing") unless hidden_at && hidden_at > rule_at
|
|
40
|
+
fail!("rail no longer dissolves so the licence can leave it") unless css.include?(".rascunhos-main .rascunhos-body>.writing-rail:not([hidden])") &&
|
|
41
|
+
css.include?("display: contents")
|
|
42
|
+
|
|
43
|
+
puts "PASS test-rascunhos-licence"
|
data/scripts/validate.sh
CHANGED
|
@@ -60,6 +60,10 @@ TESTS=(
|
|
|
60
60
|
scripts/test/test-hydrate-reserve.rb
|
|
61
61
|
scripts/test/test-hero-summary.rb
|
|
62
62
|
scripts/test/test-lighthouse-policy.rb
|
|
63
|
+
scripts/test/test-home-lists.rb
|
|
64
|
+
scripts/test/test-home-articles.rb
|
|
65
|
+
scripts/test/test-rascunhos-licence.rb
|
|
66
|
+
scripts/test/test-pwa-icons.rb
|
|
63
67
|
scripts/test/test-css-delivery.rb
|
|
64
68
|
scripts/test/test-discovery.rb
|
|
65
69
|
)
|
data/studio/index.html
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
<meta name="robots" content="noindex" />
|
|
7
7
|
<link rel="icon" href="/assets/icons/studio-logo.svg" type="image/svg+xml" sizes="any" />
|
|
8
8
|
<link rel="icon" href="/assets/icons/studio-logo-32.png" type="image/png" sizes="32x32" />
|
|
9
|
-
<link rel="apple-touch-icon" href="/assets/icons/studio-
|
|
9
|
+
<link rel="apple-touch-icon" href="/assets/icons/studio-apple-touch-icon.png" sizes="180x180" />
|
|
10
|
+
<link rel="icon" href="/assets/icons/studio-logo.ico" sizes="16x16 32x32" />
|
|
11
|
+
<link rel="manifest" href="/studio.webmanifest" />
|
|
12
|
+
<meta name="theme-color" content="#5e5d59" />
|
|
10
13
|
<title>Studio</title>
|
|
11
14
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
12
15
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
data/studio-app/index.html
CHANGED
|
@@ -6,7 +6,10 @@
|
|
|
6
6
|
<meta name="robots" content="noindex" />
|
|
7
7
|
<link rel="icon" href="/assets/icons/studio-logo.svg" type="image/svg+xml" sizes="any" />
|
|
8
8
|
<link rel="icon" href="/assets/icons/studio-logo-32.png" type="image/png" sizes="32x32" />
|
|
9
|
-
<link rel="apple-touch-icon" href="/assets/icons/studio-
|
|
9
|
+
<link rel="apple-touch-icon" href="/assets/icons/studio-apple-touch-icon.png" sizes="180x180" />
|
|
10
|
+
<link rel="icon" href="/assets/icons/studio-logo.ico" sizes="16x16 32x32" />
|
|
11
|
+
<link rel="manifest" href="/studio.webmanifest" />
|
|
12
|
+
<meta name="theme-color" content="#5e5d59" />
|
|
10
13
|
<title>Studio</title>
|
|
11
14
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
12
15
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
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.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Pandorga contributors
|
|
@@ -227,7 +227,23 @@ files:
|
|
|
227
227
|
- assets/css/ledger/sources.css
|
|
228
228
|
- assets/css/ledger/writing.css
|
|
229
229
|
- assets/css/tailwind.css
|
|
230
|
+
- assets/icons/apple-touch-icon.png
|
|
231
|
+
- assets/icons/favicon-32.png
|
|
232
|
+
- assets/icons/favicon.ico
|
|
233
|
+
- assets/icons/favicon.svg
|
|
234
|
+
- assets/icons/icon-192.png
|
|
235
|
+
- assets/icons/icon-32.png
|
|
236
|
+
- assets/icons/icon-512.png
|
|
237
|
+
- assets/icons/icon-maskable-192.png
|
|
238
|
+
- assets/icons/icon-maskable-512.png
|
|
239
|
+
- assets/icons/studio-apple-touch-icon.png
|
|
240
|
+
- assets/icons/studio-icon-192.png
|
|
241
|
+
- assets/icons/studio-icon-512.png
|
|
242
|
+
- assets/icons/studio-logo-32.png
|
|
243
|
+
- assets/icons/studio-logo.ico
|
|
230
244
|
- assets/icons/studio-logo.svg
|
|
245
|
+
- assets/icons/studio-maskable-192.png
|
|
246
|
+
- assets/icons/studio-maskable-512.png
|
|
231
247
|
- assets/tailwind-play.js
|
|
232
248
|
- examples/full/Gemfile
|
|
233
249
|
- examples/full/_config.yml
|
|
@@ -300,12 +316,14 @@ files:
|
|
|
300
316
|
- lib/pandorga/jekyll/plugins/lib/writing_entry.rb
|
|
301
317
|
- lib/pandorga/jekyll/plugins/local_detail_rewrites.rb
|
|
302
318
|
- lib/pandorga/jekyll/plugins/timeline.rb
|
|
319
|
+
- lib/pandorga/jekyll/plugins/web_manifest.rb
|
|
303
320
|
- lib/pandorga/jekyll/plugins/writing_slug_limits.rb
|
|
304
321
|
- lib/pandorga/object_store_env.rb
|
|
305
322
|
- lib/pandorga/registry.rb
|
|
306
323
|
- lib/pandorga/registry/schema.yml
|
|
307
324
|
- lib/pandorga/version.rb
|
|
308
325
|
- scripts/cdn-allowlist.json
|
|
326
|
+
- scripts/check_home_lists.mjs
|
|
309
327
|
- scripts/content/backfill-content-keys.rb
|
|
310
328
|
- scripts/content/band_art.rb
|
|
311
329
|
- scripts/content/export-content-json.rb
|
|
@@ -326,6 +344,7 @@ files:
|
|
|
326
344
|
- scripts/lighthouse_server.py
|
|
327
345
|
- scripts/pdf/md-to-pdf.mjs
|
|
328
346
|
- scripts/pdf/md-to-pdf.sh
|
|
347
|
+
- scripts/render-pwa-icons.py
|
|
329
348
|
- scripts/tailwind/build.sh
|
|
330
349
|
- scripts/tailwind/input.css
|
|
331
350
|
- scripts/tailwind/tailwind.config.js
|
|
@@ -409,7 +428,9 @@ files:
|
|
|
409
428
|
- scripts/test/test-hero-portraits.mjs
|
|
410
429
|
- scripts/test/test-hero-portraits.rb
|
|
411
430
|
- scripts/test/test-hero-summary.rb
|
|
431
|
+
- scripts/test/test-home-articles.rb
|
|
412
432
|
- scripts/test/test-home-band-art.rb
|
|
433
|
+
- scripts/test/test-home-lists.rb
|
|
413
434
|
- scripts/test/test-hydrate-reserve.rb
|
|
414
435
|
- scripts/test/test-install-functions.rb
|
|
415
436
|
- scripts/test/test-language-export.rb
|
|
@@ -422,8 +443,10 @@ files:
|
|
|
422
443
|
- scripts/test/test-no-personal-data.rb
|
|
423
444
|
- scripts/test/test-public-cv-export.rb
|
|
424
445
|
- scripts/test/test-publish-site-root.rb
|
|
446
|
+
- scripts/test/test-pwa-icons.rb
|
|
425
447
|
- scripts/test/test-r2-config-consistency.rb
|
|
426
448
|
- scripts/test/test-r2-json-sync.rb
|
|
449
|
+
- scripts/test/test-rascunhos-licence.rb
|
|
427
450
|
- scripts/test/test-registry-home.rb
|
|
428
451
|
- scripts/test/test-runtime-js-syntax.rb
|
|
429
452
|
- scripts/test/test-shell-a11y.rb
|