openvibers/openvibe.domains Commits
Fix the home page folds' summary names (#137)
Changes
@@@ -294,13 +294,13 @@ html[data-ov-motion=off] .dm-bar span{transform: none !important}.hm-fold-block > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 44px; cursor: pointer; list-style: none; }.hm-fold-block > summary::-webkit-details-marker { display: none; }.hm-fold-block > summary h2 { margin: 0; font: 700 clamp(19px, 2.2vw, 26px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); }--.hm-fold-block > summary span { color: var(--text-muted, #7386a3); font-weight: 600; font-size: .86rem; white-space: nowrap; }++.hm-fold-block > summary .hm-fold-n { color: var(--text-muted, #7386a3); font-weight: 600; font-size: .86rem; white-space: nowrap; }.hm-fold-block > summary:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: 2px; }@media (min-width: 641px) {.hm-fold-block { border: 0; background: none; border-radius: 0; margin: 56px auto 0; padding: 0; }.hm-fold-block > summary { display: block; min-height: 0; }.hm-fold-block > summary h2 { margin: 0 0 6px; font: 700 clamp(22px, 2.6vw, 30px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); }-- .hm-fold-block > summary span { display: none; }++ .hm-fold-block > summary .hm-fold-n { display: none; }.hm-fold-block .hm-sec, .hm-fold-block .sc-sec { margin: 0; max-width: none; padding: 0; }}@media (max-width: 640px) { .hm-fold-block { margin-top: 24px; } .hm-fold-block > summary h2 { font-size: 1.05rem; } }@@@ -63,7 +63,7 @@ function foldMeta(body, cls = '') {* foldBlock({ id, head, html })*/function foldBlock({ id, head, html }) {-- return `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(html)}</summary>${html}</details>${foldScript(id)}`;++ return `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(html, 'hm-fold-n')}</summary>${html}</details>${foldScript(id)}`;}/** The script a fold carries: closed on a phone unless the reader opened it before, and it remembers that. */@@@ -93,7 +93,7 @@ function foldSection(html, needle, id) {// The lede under the heading goes with it: the fold's heading says enough on a phone.const lede = /<p class="sc-lede"[^>]*>[\s\S]*?<\/p>/.exec(inner);if (lede) inner = inner.slice(0, lede.index) + inner.slice(lede.index + lede[0].length);-- const fold = `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(inner.trim())}</summary>${inner.trim()}</details>${foldScript(id)}`;++ const fold = `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(inner.trim(), 'hm-fold-n')}</summary>${inner.trim()}</details>${foldScript(id)}`;return html.slice(0, start) + openTag + fold + html.slice(close);}@@@ -25,6 +25,28 @@ const { boot, check, done } = require('./helpers');assert.ok(r.text.includes('<section class="sc-sec" id="faq"') || r.text.includes('aria-labelledby="sc-questions"'), 'the questions keep their section');});++ await check('each fold summary says what it holds, and only its count is hidden on a wide screen', async () => {++ const r = await t.get('/');++ const folds = [...r.text.matchAll(/<details class="hm-fold hm-fold-block" id="([^"]+)"[^>]*>([\s\S]*?)<\/details>/g)];++ assert.ok(folds.length >= 2, 'the home has the questions and API folds');++ for (const [, id, inner] of folds) {++ const summary = /<summary>([\s\S]*?)<\/summary>/.exec(inner);++ assert.ok(summary, `${id} has a summary`);++ assert.match(summary[1], /<span class="hm-fold-n">/, `${id} marks its count, so the stylesheet can hide only the count`);++ const words = summary[1]++ .replace(/<span class="hm-fold-n">[\s\S]*?<\/span>/g, '')++ .replace(/<span[^>]*aria-hidden="true"[^>]*>[\s\S]*?<\/span>/g, '')++ .replace(/<[^>]+>/g, ' ')++ .replace(/&[^;]+;/g, ' ')++ .replace(/\s+/g, ' ').trim();++ assert.ok(words.length > 2, `${id} names what it holds in words ("${words}")`);++ }++ // The wide-screen rule hides the count only; a rule for every span would hide the heading's own words.++ const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'domains.css'), 'utf8');++ assert.ok(!/\.hm-fold-block > summary span\s*\{[^}]*display:\s*none/.test(css), 'no rule hides every span in a fold summary');++ assert.match(css, /\.hm-fold-block > summary \.hm-fold-n\s*\{[^}]*display:\s*none/, 'the wide-screen rule hides the count');++ });++await check('the hero is one name priced, not sc.room\'s default motif (MOTION-1)', async () => {const r = await t.get('/');assert.match(r.text, /<div class="dm-motif" aria-hidden="true">/);
@@ -294,13 +294,13 @@ html[data-ov-motion=off] .dm-bar span{transform: none !important}
@@ -294,13 +294,13 @@ html[data-ov-motion=off] .dm-bar span{transform: none !important}
.hm-fold-block > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 44px; cursor: pointer; list-style: none; }
.hm-fold-block > summary { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 44px; cursor: pointer; list-style: none; }
.hm-fold-block > summary::-webkit-details-marker { display: none; }
.hm-fold-block > summary::-webkit-details-marker { display: none; }
.hm-fold-block > summary h2 { margin: 0; font: 700 clamp(19px, 2.2vw, 26px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); }
.hm-fold-block > summary h2 { margin: 0; font: 700 clamp(19px, 2.2vw, 26px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); }
-.hm-fold-block > summary span { color: var(--text-muted, #7386a3); font-weight: 600; font-size: .86rem; white-space: nowrap; }
+.hm-fold-block > summary .hm-fold-n { color: var(--text-muted, #7386a3); font-weight: 600; font-size: .86rem; white-space: nowrap; }
.hm-fold-block > summary:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: 2px; }
.hm-fold-block > summary:focus-visible { outline: 2px solid var(--accent, #3b82f6); outline-offset: 2px; }
@media (min-width: 641px) {
@media (min-width: 641px) {
.hm-fold-block { border: 0; background: none; border-radius: 0; margin: 56px auto 0; padding: 0; }
.hm-fold-block { border: 0; background: none; border-radius: 0; margin: 56px auto 0; padding: 0; }
.hm-fold-block > summary { display: block; min-height: 0; }
.hm-fold-block > summary { display: block; min-height: 0; }
.hm-fold-block > summary h2 { margin: 0 0 6px; font: 700 clamp(22px, 2.6vw, 30px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); }
.hm-fold-block > summary h2 { margin: 0 0 6px; font: 700 clamp(22px, 2.6vw, 30px)/1.2 var(--ov-font, 'Inter', system-ui, sans-serif); }
- .hm-fold-block > summary span { display: none; }
+ .hm-fold-block > summary .hm-fold-n { display: none; }
.hm-fold-block .hm-sec, .hm-fold-block .sc-sec { margin: 0; max-width: none; padding: 0; }
.hm-fold-block .hm-sec, .hm-fold-block .sc-sec { margin: 0; max-width: none; padding: 0; }
}
}
@media (max-width: 640px) { .hm-fold-block { margin-top: 24px; } .hm-fold-block > summary h2 { font-size: 1.05rem; } }
@media (max-width: 640px) { .hm-fold-block { margin-top: 24px; } .hm-fold-block > summary h2 { font-size: 1.05rem; } }
@@ -63,7 +63,7 @@ function foldMeta(body, cls = '') {
@@ -63,7 +63,7 @@ function foldMeta(body, cls = '') {
* foldBlock({ id, head, html })
* foldBlock({ id, head, html })
*/
*/
function foldBlock({ id, head, html }) {
function foldBlock({ id, head, html }) {
- return `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(html)}</summary>${html}</details>${foldScript(id)}`;
+ return `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(html, 'hm-fold-n')}</summary>${html}</details>${foldScript(id)}`;
}
}
/** The script a fold carries: closed on a phone unless the reader opened it before, and it remembers that. */
/** The script a fold carries: closed on a phone unless the reader opened it before, and it remembers that. */
@@ -93,7 +93,7 @@ function foldSection(html, needle, id) {
@@ -93,7 +93,7 @@ function foldSection(html, needle, id) {
// The lede under the heading goes with it: the fold's heading says enough on a phone.
// The lede under the heading goes with it: the fold's heading says enough on a phone.
const lede = /<p class="sc-lede"[^>]*>[\s\S]*?<\/p>/.exec(inner);
const lede = /<p class="sc-lede"[^>]*>[\s\S]*?<\/p>/.exec(inner);
if (lede) inner = inner.slice(0, lede.index) + inner.slice(lede.index + lede[0].length);
if (lede) inner = inner.slice(0, lede.index) + inner.slice(lede.index + lede[0].length);
- const fold = `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(inner.trim())}</summary>${inner.trim()}</details>${foldScript(id)}`;
+ const fold = `<details class="hm-fold hm-fold-block" id="${esc(id)}" open><summary>${head}${foldMeta(inner.trim(), 'hm-fold-n')}</summary>${inner.trim()}</details>${foldScript(id)}`;
return html.slice(0, start) + openTag + fold + html.slice(close);
return html.slice(0, start) + openTag + fold + html.slice(close);
}
}
@@ -25,6 +25,28 @@ const { boot, check, done } = require('./helpers');
@@ -25,6 +25,28 @@ const { boot, check, done } = require('./helpers');
assert.ok(r.text.includes('<section class="sc-sec" id="faq"') || r.text.includes('aria-labelledby="sc-questions"'), 'the questions keep their section');
assert.ok(r.text.includes('<section class="sc-sec" id="faq"') || r.text.includes('aria-labelledby="sc-questions"'), 'the questions keep their section');
});
});
+ await check('each fold summary says what it holds, and only its count is hidden on a wide screen', async () => {
+ const r = await t.get('/');
+ const folds = [...r.text.matchAll(/<details class="hm-fold hm-fold-block" id="([^"]+)"[^>]*>([\s\S]*?)<\/details>/g)];
+ assert.ok(folds.length >= 2, 'the home has the questions and API folds');
+ for (const [, id, inner] of folds) {
+ const summary = /<summary>([\s\S]*?)<\/summary>/.exec(inner);
+ assert.ok(summary, `${id} has a summary`);
+ assert.match(summary[1], /<span class="hm-fold-n">/, `${id} marks its count, so the stylesheet can hide only the count`);
+ const words = summary[1]
+ .replace(/<span class="hm-fold-n">[\s\S]*?<\/span>/g, '')
+ .replace(/<span[^>]*aria-hidden="true"[^>]*>[\s\S]*?<\/span>/g, '')
+ .replace(/<[^>]+>/g, ' ')
+ .replace(/&[^;]+;/g, ' ')
+ .replace(/\s+/g, ' ').trim();
+ assert.ok(words.length > 2, `${id} names what it holds in words ("${words}")`);
+ }
+ // The wide-screen rule hides the count only; a rule for every span would hide the heading's own words.
+ const css = fs.readFileSync(path.join(__dirname, '..', 'public', 'css', 'domains.css'), 'utf8');
+ assert.ok(!/\.hm-fold-block > summary span\s*\{[^}]*display:\s*none/.test(css), 'no rule hides every span in a fold summary');
+ assert.match(css, /\.hm-fold-block > summary \.hm-fold-n\s*\{[^}]*display:\s*none/, 'the wide-screen rule hides the count');
+ });
+
await check('the hero is one name priced, not sc.room\'s default motif (MOTION-1)', async () => {
await check('the hero is one name priced, not sc.room\'s default motif (MOTION-1)', async () => {
const r = await t.get('/');
const r = await t.get('/');
assert.match(r.text, /<div class="dm-motif" aria-hidden="true">/);
assert.match(r.text, /<div class="dm-motif" aria-hidden="true">/);