pandorga 1.4.6 → 1.4.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 +18 -0
- data/_layouts/home.html +53 -2
- data/assets/css/ledger/home.css +93 -56
- data/lib/pandorga/version.rb +1 -1
- data/scripts/test/render-parity/blocks/project-specimen.json +5 -3
- data/scripts/test/render-parity/blocks/system-card.json +8 -3
- data/scripts/test/test-studio-api-contract.rb +70 -0
- data/scripts/test/test-studio-pipeline-focus.mjs +308 -0
- data/scripts/validate.sh +5 -0
- data/studio/assets/{index-CMVzh8F1.js → index-BJyN-kB3.js} +98 -98
- data/studio/index.html +1 -1
- data/studio-app/src/main.js +126 -32
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: fdc6dcec6dea0007093b40500ca2ec287d17170029f68b3f4284090fe14236a1
|
|
4
|
+
data.tar.gz: be5ea215e27ebe6755ce5d09875c8ca175d16daf3d8328c94161255fba179531
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f2f5de4ed2c7737a20b33fe03018c49f8a2267a4903ed065c5af9f99bf1b36e708305186c3d022786152efc15ba39791c6f55c2cf9427d2bac4f97a61cda77a7
|
|
7
|
+
data.tar.gz: 43e93a55bd09913445387e511741522588d2fb51d37589dc51abc4d0d4e4145fa3fef32c7087a7b4d59fa841fe25b2e5cc799bc1c88c2efa3883e7dfb5d546d4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.4.8] — 2026-10-08
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- Home project bench: specimen and inventory share equal ~45.6% columns;
|
|
8
|
+
inventory thumbnails fill row height at 16:9; list titles, copy, and
|
|
9
|
+
resource marks retuned (neutral gray icons, tighter type)
|
|
10
|
+
- Specimen tagline flexes into spare card height and ellipsizes with a
|
|
11
|
+
proper "…" (CSS line-clamp was hard-clipping mid-glyph)
|
|
12
|
+
|
|
13
|
+
## [1.4.7] — 2026-10-07
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- Studio keeps the editor focused while the content-pipeline chip is spinning.
|
|
18
|
+
Status polls patch the toolbar chip instead of rebuilding the shell.
|
|
19
|
+
- Home draft cards use 16:9 thumbnails and are 20% shorter on desktop and mobile.
|
|
20
|
+
|
|
3
21
|
## [1.4.6] — 2026-10-07
|
|
4
22
|
|
|
5
23
|
### Fixed
|
data/_layouts/home.html
CHANGED
|
@@ -250,6 +250,43 @@ layout: shell
|
|
|
250
250
|
/* Lock height to the tallest project so swapping never moves the
|
|
251
251
|
inventory. Remeasure on resize when the specimen column width
|
|
252
252
|
changes (chip wrap / plate width). */
|
|
253
|
+
/* `-webkit-line-clamp` fails on the specimen card (mid-glyph crop,
|
|
254
|
+
no ellipsis). Copy flexes into spare card height; fit text here. */
|
|
255
|
+
function ellipsizeSpecimenCopy(root) {
|
|
256
|
+
var copy = root.querySelector('.ledger-card-copy');
|
|
257
|
+
if (!copy) return;
|
|
258
|
+
var full = copy.getAttribute('data-full-text') || copy.textContent;
|
|
259
|
+
copy.setAttribute('data-full-text', full);
|
|
260
|
+
copy.textContent = full;
|
|
261
|
+
if (copy.scrollHeight <= copy.clientHeight + 1) return;
|
|
262
|
+
|
|
263
|
+
function fitted(n) {
|
|
264
|
+
if (n >= full.length) {
|
|
265
|
+
copy.textContent = full;
|
|
266
|
+
return copy.scrollHeight <= copy.clientHeight + 1;
|
|
267
|
+
}
|
|
268
|
+
var slice = full.slice(0, n);
|
|
269
|
+
var sp = slice.lastIndexOf(' ');
|
|
270
|
+
if (sp > Math.floor(n * 0.5)) slice = slice.slice(0, sp);
|
|
271
|
+
copy.textContent = slice.replace(/[.,;:\s]+$/u, '') + '…';
|
|
272
|
+
return copy.scrollHeight <= copy.clientHeight + 1;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
var lo = 0;
|
|
276
|
+
var hi = full.length;
|
|
277
|
+
var best = 0;
|
|
278
|
+
while (lo <= hi) {
|
|
279
|
+
var mid = (lo + hi) >> 1;
|
|
280
|
+
if (fitted(mid)) {
|
|
281
|
+
best = mid;
|
|
282
|
+
lo = mid + 1;
|
|
283
|
+
} else {
|
|
284
|
+
hi = mid - 1;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
fitted(best);
|
|
288
|
+
}
|
|
289
|
+
|
|
253
290
|
function paintSpecimen(entry) {
|
|
254
291
|
specimenSlot.innerHTML = '';
|
|
255
292
|
specimenSlot.appendChild(runtime.renderProjectSpecimen(asItem(entry), {
|
|
@@ -258,6 +295,7 @@ layout: shell
|
|
|
258
295
|
folio: positionOf(entry.slug) + 1,
|
|
259
296
|
openLabel: 'Open project'
|
|
260
297
|
}));
|
|
298
|
+
ellipsizeSpecimenCopy(specimenSlot);
|
|
261
299
|
}
|
|
262
300
|
|
|
263
301
|
function measureTallestSpecimen() {
|
|
@@ -302,8 +340,21 @@ layout: shell
|
|
|
302
340
|
var bench = specimenSlot.closest('.home-projects-bench');
|
|
303
341
|
if (!bench) return;
|
|
304
342
|
var tallest = measureTallestSpecimen();
|
|
305
|
-
|
|
306
|
-
|
|
343
|
+
/* Floor at the CSS inventory minimum so six rows always clear
|
|
344
|
+
three stacked resource icons (see --home-inventory-min-height). */
|
|
345
|
+
var inventoryMin = 0;
|
|
346
|
+
var raw = window.getComputedStyle(bench)
|
|
347
|
+
.getPropertyValue('--home-inventory-min-height').trim();
|
|
348
|
+
if (raw) {
|
|
349
|
+
var probe = document.createElement('div');
|
|
350
|
+
probe.style.cssText = 'position:absolute;visibility:hidden;height:' + raw;
|
|
351
|
+
bench.appendChild(probe);
|
|
352
|
+
inventoryMin = Math.ceil(probe.getBoundingClientRect().height);
|
|
353
|
+
probe.remove();
|
|
354
|
+
}
|
|
355
|
+
var locked = Math.max(tallest, inventoryMin);
|
|
356
|
+
if (locked > 0) {
|
|
357
|
+
bench.style.setProperty('--home-specimen-height', locked + 'px');
|
|
307
358
|
}
|
|
308
359
|
}
|
|
309
360
|
|
data/assets/css/ledger/home.css
CHANGED
|
@@ -845,10 +845,9 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
845
845
|
border-color var(--motion-duration-fast) var(--motion-ease-default);
|
|
846
846
|
}
|
|
847
847
|
|
|
848
|
-
/*
|
|
849
|
-
keeps room for the excerpt (four-up columns were clipping copy to a sliver). */
|
|
848
|
+
/* Shared 16:9 plate. The previous 16/12.6 crop made these thumbs tall. */
|
|
850
849
|
.home-draft-card .ledger-poster {
|
|
851
|
-
aspect-ratio: 16 /
|
|
850
|
+
aspect-ratio: 16 / 9;
|
|
852
851
|
}
|
|
853
852
|
|
|
854
853
|
/* A handful of fixed degrees per grid position — not a JS random() — so the
|
|
@@ -875,8 +874,9 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
875
874
|
}
|
|
876
875
|
|
|
877
876
|
.home-draft-card .ledger-card-body {
|
|
878
|
-
|
|
879
|
-
|
|
877
|
+
/* 20% shorter stack than the previous dropped-sheet body, both breakpoints. */
|
|
878
|
+
padding: calc(var(--space-md) * 0.8);
|
|
879
|
+
gap: calc(var(--space-xs) * 0.8);
|
|
880
880
|
}
|
|
881
881
|
|
|
882
882
|
/* Up from 1rem. The four dropped sheets are the only place on the home page
|
|
@@ -903,19 +903,29 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
903
903
|
`flex: 1` gives the paragraph a definite block size from the flex
|
|
904
904
|
allocation, so line-clamp/overflow clip against that height instead of
|
|
905
905
|
growing past the ellipsis (the old flex:1 + clamp:2 bug that left text
|
|
906
|
-
after "…" and sliced mid-glyph at the card edge).
|
|
907
|
-
min-height ~40% above the old six-line band so short posters still leave
|
|
908
|
-
readable excerpt room. */
|
|
906
|
+
after "…" and sliced mid-glyph at the card edge). */
|
|
909
907
|
flex: 1 1 auto;
|
|
910
|
-
|
|
908
|
+
/* With the 16:9 plate, this band keeps the whole card about 20% shorter
|
|
909
|
+
than the old 16/12.6 poster and 8.4-line excerpt, on narrow and wide grids. */
|
|
910
|
+
min-height: calc(var(--type-subtitle) * var(--leading-body) * 5.33);
|
|
911
911
|
height: 0;
|
|
912
912
|
display: -webkit-box;
|
|
913
|
-
-webkit-line-clamp:
|
|
914
|
-
line-clamp:
|
|
913
|
+
-webkit-line-clamp: 5;
|
|
914
|
+
line-clamp: 5;
|
|
915
915
|
-webkit-box-orient: vertical;
|
|
916
916
|
overflow: hidden;
|
|
917
917
|
}
|
|
918
918
|
|
|
919
|
+
/* Four-up posters were the tall part of the old card. Give the excerpt a
|
|
920
|
+
little of that height back so the wide card is 20% shorter too, not more. */
|
|
921
|
+
@media (min-width: 1024px) {
|
|
922
|
+
.home-draft-card .ledger-card-copy {
|
|
923
|
+
min-height: calc(var(--type-subtitle) * var(--leading-body) * 6.05);
|
|
924
|
+
-webkit-line-clamp: 6;
|
|
925
|
+
line-clamp: 6;
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
919
929
|
.home-draft-card .ledger-card-foot .ledger-cta {
|
|
920
930
|
font-size: var(--type-cta);
|
|
921
931
|
}
|
|
@@ -947,12 +957,13 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
947
957
|
A specimen card beside a filing rack of project cards. Height is locked to
|
|
948
958
|
the tallest project (home.html measures once, then sets
|
|
949
959
|
`--home-specimen-height`), so swapping projects never resizes the band or
|
|
950
|
-
the inventory. Taglines
|
|
951
|
-
the projects index; spare height parks chips and the foot
|
|
952
|
-
Every plate is 16:9, the ratio the thumbnails are drawn at,
|
|
953
|
-
below it. From 900px the specimen
|
|
954
|
-
|
|
955
|
-
above the specimen, one column
|
|
960
|
+
the inventory. Taglines clamp to two lines with an ellipsis; chips wrap
|
|
961
|
+
whole pills like the projects index; spare height parks chips and the foot
|
|
962
|
+
on the floor. Every plate is 16:9, the ratio the thumbnails are drawn at,
|
|
963
|
+
with the title below it. From 900px the specimen and the rack share equal
|
|
964
|
+
columns (~45.6% each); rows reserve height for three resource icons.
|
|
965
|
+
Below 900px the rack is an icon strip above the specimen, one column
|
|
966
|
+
per project. */
|
|
956
967
|
.home-projects-bench {
|
|
957
968
|
--home-specimen-height: 32rem;
|
|
958
969
|
--home-icon-btn-size: 2.75rem;
|
|
@@ -1128,12 +1139,15 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1128
1139
|
white-space: nowrap;
|
|
1129
1140
|
}
|
|
1130
1141
|
|
|
1131
|
-
/*
|
|
1132
|
-
clamp
|
|
1133
|
-
|
|
1134
|
-
|
|
1142
|
+
/* Tagline fills spare height between the plate and the chips/foot.
|
|
1143
|
+
`-webkit-line-clamp` hard-clips mid-glyph on this card, so home.html
|
|
1144
|
+
ellipsizes against the flex-allocated box after paint (`height: 0` +
|
|
1145
|
+
`flex: 1` is the same definite-size trick as `.home-draft-card`). */
|
|
1135
1146
|
.home-project-specimen .ledger-card-copy {
|
|
1136
|
-
flex:
|
|
1147
|
+
flex: 1 1 auto;
|
|
1148
|
+
min-height: calc(var(--type-body) * var(--leading-body) * 2);
|
|
1149
|
+
height: 0;
|
|
1150
|
+
overflow: hidden;
|
|
1137
1151
|
font-size: var(--type-body);
|
|
1138
1152
|
line-height: var(--leading-body);
|
|
1139
1153
|
color: var(--color-on-surface-variant);
|
|
@@ -1143,14 +1157,14 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1143
1157
|
flex: 0 0 auto;
|
|
1144
1158
|
flex-wrap: wrap;
|
|
1145
1159
|
gap: var(--space-xs);
|
|
1146
|
-
margin:
|
|
1160
|
+
margin: 0;
|
|
1147
1161
|
}
|
|
1148
1162
|
|
|
1149
1163
|
.home-specimen-foot {
|
|
1150
1164
|
flex: 0 0 auto;
|
|
1151
1165
|
flex-wrap: wrap;
|
|
1152
1166
|
gap: var(--space-md);
|
|
1153
|
-
margin-top:
|
|
1167
|
+
margin-top: var(--space-sm);
|
|
1154
1168
|
padding-top: var(--space-md);
|
|
1155
1169
|
}
|
|
1156
1170
|
|
|
@@ -1271,11 +1285,25 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1271
1285
|
|
|
1272
1286
|
@media (min-width: 900px) {
|
|
1273
1287
|
|
|
1274
|
-
/* Desktop fallback before JS measures the tallest specimen.
|
|
1288
|
+
/* Desktop fallback before JS measures the tallest specimen.
|
|
1289
|
+
Specimen and inventory share equal columns (specimen was 38% then
|
|
1290
|
+
+20% → 45.6%; the list matches that width). Rows still reserve
|
|
1291
|
+
height for three stacked resource icons. */
|
|
1275
1292
|
.home-projects-bench {
|
|
1276
|
-
--home-
|
|
1293
|
+
--home-inventory-icon-size: 1.55rem;
|
|
1294
|
+
--home-inventory-icon-gap: 0.2rem;
|
|
1295
|
+
--home-inventory-resources-height: calc(
|
|
1296
|
+
3 * var(--home-inventory-icon-size) + 2 * var(--home-inventory-icon-gap)
|
|
1297
|
+
);
|
|
1298
|
+
--home-inventory-row-min: calc(
|
|
1299
|
+
var(--home-inventory-resources-height) + 2 * var(--space-sm)
|
|
1300
|
+
);
|
|
1301
|
+
--home-inventory-min-height: calc(
|
|
1302
|
+
6 * var(--home-inventory-row-min) + 5 * var(--space-sm) + 2 * var(--space-md)
|
|
1303
|
+
);
|
|
1304
|
+
--home-specimen-height: max(36rem, var(--home-inventory-min-height));
|
|
1277
1305
|
display: grid;
|
|
1278
|
-
grid-template-columns: minmax(0,
|
|
1306
|
+
grid-template-columns: minmax(0, 45.6%) minmax(0, 45.6%);
|
|
1279
1307
|
column-gap: var(--space-xl);
|
|
1280
1308
|
align-items: stretch;
|
|
1281
1309
|
}
|
|
@@ -1285,6 +1313,9 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1285
1313
|
display: flex;
|
|
1286
1314
|
flex-direction: column;
|
|
1287
1315
|
gap: var(--space-sm);
|
|
1316
|
+
box-sizing: border-box;
|
|
1317
|
+
width: 100%;
|
|
1318
|
+
min-width: 0;
|
|
1288
1319
|
min-height: 0;
|
|
1289
1320
|
overflow: hidden;
|
|
1290
1321
|
padding: var(--space-md);
|
|
@@ -1297,10 +1328,11 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1297
1328
|
|
|
1298
1329
|
.home-project-inventory-row {
|
|
1299
1330
|
flex: 1 1 0;
|
|
1331
|
+
align-items: flex-start;
|
|
1300
1332
|
justify-content: flex-start;
|
|
1301
1333
|
gap: var(--space-md);
|
|
1302
1334
|
height: auto;
|
|
1303
|
-
min-height:
|
|
1335
|
+
min-height: var(--home-inventory-row-min);
|
|
1304
1336
|
padding: var(--space-sm) var(--space-md);
|
|
1305
1337
|
border: 1px solid var(--border-gentle-divider);
|
|
1306
1338
|
background: var(--color-surface-card);
|
|
@@ -1319,10 +1351,14 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1319
1351
|
box-shadow: inset 3px 0 0 var(--color-primary);
|
|
1320
1352
|
}
|
|
1321
1353
|
|
|
1354
|
+
/* Plate fills the row’s content height; width follows 16:9. Stretch keeps
|
|
1355
|
+
it tall while title/copy/icons stay top-aligned with its top edge. */
|
|
1322
1356
|
.home-project-inventory-media {
|
|
1323
1357
|
display: block;
|
|
1324
1358
|
flex: 0 0 auto;
|
|
1325
|
-
|
|
1359
|
+
align-self: stretch;
|
|
1360
|
+
width: auto;
|
|
1361
|
+
height: auto;
|
|
1326
1362
|
aspect-ratio: 16 / 9;
|
|
1327
1363
|
overflow: hidden;
|
|
1328
1364
|
background: var(--color-surface-high);
|
|
@@ -1354,12 +1390,12 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1354
1390
|
}
|
|
1355
1391
|
|
|
1356
1392
|
.home-project-inventory-mark .material-symbols-outlined {
|
|
1357
|
-
font-size:
|
|
1393
|
+
font-size: 2rem;
|
|
1358
1394
|
}
|
|
1359
1395
|
|
|
1360
1396
|
.home-project-inventory-mark--initial {
|
|
1361
1397
|
font-family: var(--font-content-title);
|
|
1362
|
-
font-size: var(--type-card);
|
|
1398
|
+
font-size: var(--type-card-lg);
|
|
1363
1399
|
font-weight: var(--weight-title);
|
|
1364
1400
|
line-height: 1;
|
|
1365
1401
|
color: var(--color-on-surface);
|
|
@@ -1368,10 +1404,12 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1368
1404
|
.home-project-inventory-body {
|
|
1369
1405
|
display: flex;
|
|
1370
1406
|
flex-direction: column;
|
|
1371
|
-
justify-content:
|
|
1372
|
-
|
|
1407
|
+
justify-content: flex-start;
|
|
1408
|
+
align-self: flex-start;
|
|
1409
|
+
gap: 0.2rem;
|
|
1373
1410
|
flex: 1 1 0;
|
|
1374
1411
|
min-width: 0;
|
|
1412
|
+
padding-top: 0;
|
|
1375
1413
|
}
|
|
1376
1414
|
|
|
1377
1415
|
.home-project-inventory-resources {
|
|
@@ -1379,45 +1417,44 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1379
1417
|
flex-direction: column;
|
|
1380
1418
|
justify-content: flex-start;
|
|
1381
1419
|
align-items: center;
|
|
1382
|
-
align-self:
|
|
1420
|
+
align-self: flex-start;
|
|
1383
1421
|
flex: 0 0 auto;
|
|
1384
|
-
gap:
|
|
1385
|
-
|
|
1422
|
+
gap: var(--home-inventory-icon-gap);
|
|
1423
|
+
width: var(--home-inventory-icon-size);
|
|
1424
|
+
min-height: var(--home-inventory-resources-height);
|
|
1386
1425
|
position: relative;
|
|
1387
1426
|
z-index: 1;
|
|
1388
1427
|
}
|
|
1389
1428
|
|
|
1429
|
+
/* Neutral marks — same voice as list descriptions, not primary CTAs. */
|
|
1390
1430
|
.home-project-inventory-resource {
|
|
1391
1431
|
display: inline-flex;
|
|
1392
1432
|
align-items: center;
|
|
1393
1433
|
justify-content: center;
|
|
1394
|
-
width:
|
|
1395
|
-
height:
|
|
1434
|
+
width: var(--home-inventory-icon-size);
|
|
1435
|
+
height: var(--home-inventory-icon-size);
|
|
1396
1436
|
flex: 0 0 auto;
|
|
1397
|
-
background:
|
|
1398
|
-
color: var(--color-
|
|
1399
|
-
border:
|
|
1400
|
-
}
|
|
1401
|
-
|
|
1402
|
-
.home-band--contrast .home-project-inventory-resource {
|
|
1403
|
-
background: var(--color-surface-card-contrast);
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
.home-project-inventory-row.is-selected .home-project-inventory-resource,
|
|
1407
|
-
.home-band--contrast .home-project-inventory-row.is-selected .home-project-inventory-resource {
|
|
1408
|
-
background: var(--color-surface-card);
|
|
1437
|
+
background: transparent;
|
|
1438
|
+
color: var(--color-on-surface-variant);
|
|
1439
|
+
border: 0;
|
|
1409
1440
|
}
|
|
1410
1441
|
|
|
1411
1442
|
.home-project-inventory-resource .material-symbols-outlined {
|
|
1412
1443
|
font-size: 1rem;
|
|
1413
1444
|
line-height: 1;
|
|
1414
|
-
font-variation-settings: "FILL" 0, "wght"
|
|
1445
|
+
font-variation-settings: "FILL" 0, "wght" 400, "GRAD" 0, "opsz" 20;
|
|
1415
1446
|
}
|
|
1416
1447
|
|
|
1417
|
-
.home-project-inventory-
|
|
1418
|
-
margin: 0;
|
|
1448
|
+
.home-project-inventory-code .ledger-meta {
|
|
1419
1449
|
font-size: var(--type-label-lg);
|
|
1420
|
-
|
|
1450
|
+
}
|
|
1451
|
+
|
|
1452
|
+
.home-project-inventory-title {
|
|
1453
|
+
margin: 0.2rem 0 0;
|
|
1454
|
+
font-family: var(--font-content-title);
|
|
1455
|
+
font-size: calc(var(--type-card) - 2pt);
|
|
1456
|
+
font-weight: var(--weight-title);
|
|
1457
|
+
line-height: 1.2;
|
|
1421
1458
|
color: var(--color-on-surface);
|
|
1422
1459
|
overflow: hidden;
|
|
1423
1460
|
text-overflow: ellipsis;
|
|
@@ -1432,9 +1469,9 @@ html[data-theme="light"] .home-hero-plate {
|
|
|
1432
1469
|
|
|
1433
1470
|
.home-project-inventory-copy {
|
|
1434
1471
|
margin: 0;
|
|
1435
|
-
font-size: var(--type-
|
|
1472
|
+
font-size: var(--type-label-lg);
|
|
1436
1473
|
font-weight: var(--weight-body);
|
|
1437
|
-
line-height: 1.
|
|
1474
|
+
line-height: 1.35;
|
|
1438
1475
|
color: var(--color-on-surface-variant);
|
|
1439
1476
|
overflow: hidden;
|
|
1440
1477
|
text-overflow: ellipsis;
|
data/lib/pandorga/version.rb
CHANGED
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"article.home-project-specimen",
|
|
33
33
|
"div.home-specimen-strip",
|
|
34
34
|
"div.ledger-meta",
|
|
35
|
-
"span.ledger-status",
|
|
36
35
|
"div.home-specimen-figure",
|
|
37
36
|
"div.ledger-poster",
|
|
38
37
|
"img",
|
|
@@ -45,13 +44,16 @@
|
|
|
45
44
|
"span.home-specimen-open"
|
|
46
45
|
],
|
|
47
46
|
"forbidden": [
|
|
48
|
-
"projects-plate"
|
|
47
|
+
"projects-plate",
|
|
48
|
+
"span.ledger-status"
|
|
49
|
+
],
|
|
50
|
+
"excludes": [
|
|
51
|
+
">Ongoing<"
|
|
49
52
|
],
|
|
50
53
|
"contains": [
|
|
51
54
|
">#01<",
|
|
52
55
|
">Simulation<",
|
|
53
56
|
">2024<",
|
|
54
|
-
">Ongoing<",
|
|
55
57
|
">ARCO<",
|
|
56
58
|
">Repository<",
|
|
57
59
|
">Article<",
|
|
@@ -27,22 +27,27 @@
|
|
|
27
27
|
"div.ledger-poster",
|
|
28
28
|
"img",
|
|
29
29
|
"div.ledger-meta",
|
|
30
|
-
"span.ledger-status",
|
|
31
30
|
"h3.ledger-card-title",
|
|
32
31
|
"a.ledger-card-stretch",
|
|
33
32
|
"p.ledger-card-copy",
|
|
34
33
|
"div.ledger-chip-row",
|
|
35
34
|
"div.ledger-card-links"
|
|
36
35
|
],
|
|
36
|
+
"forbidden": [
|
|
37
|
+
"span.ledger-status"
|
|
38
|
+
],
|
|
39
|
+
"excludes": [
|
|
40
|
+
">Ongoing<"
|
|
41
|
+
],
|
|
37
42
|
"contains": [
|
|
38
43
|
">Repository<",
|
|
39
44
|
">Article<",
|
|
40
45
|
">Visit<",
|
|
41
46
|
">ARCO<",
|
|
42
|
-
">Simulation"
|
|
47
|
+
">Simulation<"
|
|
43
48
|
],
|
|
44
49
|
"counts": {
|
|
45
|
-
"ledger-meta-sep":
|
|
50
|
+
"ledger-meta-sep": 0,
|
|
46
51
|
"ledger-cta": 3
|
|
47
52
|
}
|
|
48
53
|
}
|
|
@@ -45,6 +45,76 @@ check!(REPO_ROOT.join("studio-app/src/main.js").read.include?("armPipelineWatch"
|
|
|
45
45
|
"SPA must watch the content pipeline after save")
|
|
46
46
|
check!(REPO_ROOT.join("studio-app/src/main.js").read.include?("refreshPipelineStatus"),
|
|
47
47
|
"SPA must hydrate pipeline status on boot")
|
|
48
|
+
|
|
49
|
+
# Pipeline polls used to call renderShell(), which wipes #app and remounts
|
|
50
|
+
# TipTap. That drops editor focus for the whole run.
|
|
51
|
+
def function_source(source, name)
|
|
52
|
+
re = /(?:async\s+)?function\s+#{Regexp.escape(name)}\s*\(/
|
|
53
|
+
m = source.match(re)
|
|
54
|
+
raise "missing function #{name}" unless m
|
|
55
|
+
i = m.end(0)
|
|
56
|
+
paren = 1
|
|
57
|
+
while i < source.length && paren.positive?
|
|
58
|
+
c = source[i]
|
|
59
|
+
if c == "'" || c == '"' || c == "`"
|
|
60
|
+
q = c
|
|
61
|
+
i += 1
|
|
62
|
+
while i < source.length && source[i] != q
|
|
63
|
+
i += source[i] == "\\" ? 2 : 1
|
|
64
|
+
end
|
|
65
|
+
i += 1
|
|
66
|
+
elsif c == "/" && source[i + 1] == "/"
|
|
67
|
+
nl = source.index("\n", i)
|
|
68
|
+
i = nl ? nl + 1 : source.length
|
|
69
|
+
else
|
|
70
|
+
paren += 1 if c == "("
|
|
71
|
+
paren -= 1 if c == ")"
|
|
72
|
+
i += 1
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
i += 1 while i < source.length && source[i] != "{"
|
|
76
|
+
raise "missing body #{name}" if i >= source.length
|
|
77
|
+
depth = 0
|
|
78
|
+
start = i
|
|
79
|
+
while i < source.length
|
|
80
|
+
c = source[i]
|
|
81
|
+
if c == "{"
|
|
82
|
+
depth += 1
|
|
83
|
+
i += 1
|
|
84
|
+
elsif c == "}"
|
|
85
|
+
depth -= 1
|
|
86
|
+
return source[start..i] if depth == 0
|
|
87
|
+
i += 1
|
|
88
|
+
elsif c == "'" || c == '"' || c == "`"
|
|
89
|
+
q = c
|
|
90
|
+
i += 1
|
|
91
|
+
while i < source.length && source[i] != q
|
|
92
|
+
i += source[i] == "\\" ? 2 : 1
|
|
93
|
+
end
|
|
94
|
+
i += 1
|
|
95
|
+
elsif c == "/" && source[i + 1] == "/"
|
|
96
|
+
nl = source.index("\n", i)
|
|
97
|
+
i = nl ? nl + 1 : source.length
|
|
98
|
+
else
|
|
99
|
+
i += 1
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
raise "unclosed function #{name}"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
studio_main = REPO_ROOT.join("studio-app/src/main.js").read
|
|
106
|
+
%w[pollPipelineStatus refreshPipelineStatus armPipelineWatch].each do |fn|
|
|
107
|
+
body = function_source(studio_main, fn)
|
|
108
|
+
check!(!body.include?("renderShell"),
|
|
109
|
+
"#{fn} must not rebuild the shell (that drops editor focus while the chip spins)")
|
|
110
|
+
check!(body.include?("syncPipelineChip"),
|
|
111
|
+
"#{fn} must patch the pipeline chip in place")
|
|
112
|
+
end
|
|
113
|
+
reexport = function_source(studio_main, "reexportLocalContent")
|
|
114
|
+
check!(!reexport.include?("renderShell"),
|
|
115
|
+
"local export must not rebuild the shell while the button spins")
|
|
116
|
+
check!(reexport.include?("syncLocalExportButton"),
|
|
117
|
+
"local export must patch the export button in place")
|
|
48
118
|
check!(!REPO_ROOT.join("studio-app/src/main.js").read.match?(/action:\s*"delete"/),
|
|
49
119
|
"toolbar must not include a Delete action")
|
|
50
120
|
|