openvibers/openvibe.network Commits
One site filter on /updates: the no-JS links sit inside the shipped mount, which shipped.js replaces with its own bar; Bot is a site (#60)
Changes
@@@ -69,7 +69,7 @@ function createUpdatesRoutes({ blogUrl = 'http://127.0.0.1:4810', fetchImpl = glreturn { router: r, feed, queryOf };}--const SITES = ['live', 'network', 'tools', 'media', 'community', 'chat', 'games', 'blog', 'wiki', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes', 'host', 'ai', 'search', 'sources', 'events', 'billing', 'tips', 'vip', 'openre', 'sites'];++const SITES = ['live', 'network', 'tools', 'media', 'community', 'chat', 'games', 'blog', 'wiki', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes', 'host', 'ai', 'search', 'sources', 'events', 'billing', 'tips', 'vip', 'openre', 'bot', 'sites'];const NAMES = { ai: 'AI', vip: 'VIP', openre: 'OpenRe' };const nameOf = (id) => NAMES[id] || (id ? id.charAt(0).toUpperCase() + id.slice(1) : '');@@@ -97,6 +97,8 @@ function renderPage({ site, filtered, body }) {}const dayHtml = days.map((g) => `<section class="ov-shipped-day"><h3>${esc(g.day)}</h3><div class="ov-shipped-entries">${g.list.map((e) => `<div class="ov-shipped-entry">${/^https:\/\//.test(e.url || '') ? `<a class="ov-shipped-hash" href="${esc(e.url)}" rel="noopener">${esc(e.short || String(e.sha || '').slice(0, 7))}</a>` : ''}${site ? '' : `<span class="ov-shipped-site">${esc(nameOf(e.service))}</span>`}<span class="ov-shipped-text">${esc(e.subject)}</span><span class="ov-shipped-meta">${esc(e.author ? `${e.author} · ` : '')}${esc(String(e.deployed_at || '').slice(11, 16))} UTC</span></div>`).join('')}</div></section>`).join('\n');const postsHtml = posts.length ? `<aside class="ov-shipped-posts"><h3>Patch notes</h3><ul>${posts.map((p) => `<li><a href="${esc(p.url)}">${esc(p.title || 'Patch notes')}</a>${p.published_at ? ` <small>${esc(String(p.published_at).slice(0, 10))}</small>` : ''}</li>`).join('')}</ul></aside>` : '';++ // The no-JS site filter (links): inside the shipped mount, so shipped.js's own filter bar replaces it rather than++ // adding a second row.const chips = `<nav class="up-sites" aria-label="Sites"><a href="/updates"${site ? '' : ' aria-current="page"'}>Everything</a>${SITES.filter((s) => s !== 'sites').map((s) => `<a href="/updates?site=${s}"${site === s ? ' aria-current="page"' : ''}>${esc(nameOf(s))}</a>`).join('')}</nav>`;return `<!DOCTYPE html><html lang="en">@@@ -132,8 +134,8 @@ ${require('openvibe-shared/frame').noscriptNav({ name: 'OpenVibe.Network', links<main class="up" id="main"><h1>${esc(title)}</h1><p class="lede">Every change deployed to OpenVibe, newest first. Each line is a commit from the OpenVibers repositories, linked to the change itself. When enough have gathered, or a large feature lands, they are written up as <a href="https://openvibe.blog/@openvibe">Patch notes on openvibe.blog</a>. JSON: <a href="/api/v1/changelog"><code>/api/v1/changelog</code></a>.</p>--${chips}<div data-ov-shipped="log" data-service="${esc(site || '')}" data-limit="50">++${chips}${postsHtml}${dayHtml || '<p class="ov-shipped-empty">The update history could not be loaded just now.</p>'}</div>@@@ -39,6 +39,12 @@ const publicCors = require('../server/public-cors');assert.ok(page.includes('Fix <script>x</script> in pages') && !page.includes('<script>x</script>'), 'commit text escaped in the SSR log');assert.ok(page.includes('https://openvibe.blog/@openvibe/x'), 'patch notes listed');assert.ok(page.includes('<link rel="canonical" href="https://openvibe.network/updates">'));++ // One filter row: the no-JS site links sit inside the shipped mount, which shipped.js empties and refills with its own bar.++ const mount = page.indexOf('data-ov-shipped="log"'), nav = page.indexOf('<nav class="up-sites"');++ assert.ok(nav > mount && page.indexOf('</div>', mount) > nav, 'the site links are inside the shipped mount');++ assert.strictEqual(page.split('class="up-sites"').length - 1, 1, 'one site filter');++ assert.ok(page.includes('<a href="/updates?site=bot">Bot</a>'), 'Bot is a site');++ assert.strictEqual(serviceFor('bot'), 'bot');const one = await fetch(`${base}/updates?site=openvibe.wiki`);assert.strictEqual(one.headers.get('x-robots-tag'), 'noindex, follow');assert.ok((await one.text()).includes('What shipped on OpenVibe.Wiki'));
@@ -69,7 +69,7 @@ function createUpdatesRoutes({ blogUrl = 'http://127.0.0.1:4810', fetchImpl = gl
@@ -69,7 +69,7 @@ function createUpdatesRoutes({ blogUrl = 'http://127.0.0.1:4810', fetchImpl = gl
return { router: r, feed, queryOf };
return { router: r, feed, queryOf };
}
}
-const SITES = ['live', 'network', 'tools', 'media', 'community', 'chat', 'games', 'blog', 'wiki', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes', 'host', 'ai', 'search', 'sources', 'events', 'billing', 'tips', 'vip', 'openre', 'sites'];
+const SITES = ['live', 'network', 'tools', 'media', 'community', 'chat', 'games', 'blog', 'wiki', 'news', 'reviews', 'deals', 'coupons', 'trade', 'codes', 'host', 'ai', 'search', 'sources', 'events', 'billing', 'tips', 'vip', 'openre', 'bot', 'sites'];
const NAMES = { ai: 'AI', vip: 'VIP', openre: 'OpenRe' };
const NAMES = { ai: 'AI', vip: 'VIP', openre: 'OpenRe' };
const nameOf = (id) => NAMES[id] || (id ? id.charAt(0).toUpperCase() + id.slice(1) : '');
const nameOf = (id) => NAMES[id] || (id ? id.charAt(0).toUpperCase() + id.slice(1) : '');
@@ -97,6 +97,8 @@ function renderPage({ site, filtered, body }) {
@@ -97,6 +97,8 @@ function renderPage({ site, filtered, body }) {
}
}
const dayHtml = days.map((g) => `<section class="ov-shipped-day"><h3>${esc(g.day)}</h3><div class="ov-shipped-entries">${g.list.map((e) => `<div class="ov-shipped-entry">${/^https:\/\//.test(e.url || '') ? `<a class="ov-shipped-hash" href="${esc(e.url)}" rel="noopener">${esc(e.short || String(e.sha || '').slice(0, 7))}</a>` : ''}${site ? '' : `<span class="ov-shipped-site">${esc(nameOf(e.service))}</span>`}<span class="ov-shipped-text">${esc(e.subject)}</span><span class="ov-shipped-meta">${esc(e.author ? `${e.author} · ` : '')}${esc(String(e.deployed_at || '').slice(11, 16))} UTC</span></div>`).join('')}</div></section>`).join('\n');
const dayHtml = days.map((g) => `<section class="ov-shipped-day"><h3>${esc(g.day)}</h3><div class="ov-shipped-entries">${g.list.map((e) => `<div class="ov-shipped-entry">${/^https:\/\//.test(e.url || '') ? `<a class="ov-shipped-hash" href="${esc(e.url)}" rel="noopener">${esc(e.short || String(e.sha || '').slice(0, 7))}</a>` : ''}${site ? '' : `<span class="ov-shipped-site">${esc(nameOf(e.service))}</span>`}<span class="ov-shipped-text">${esc(e.subject)}</span><span class="ov-shipped-meta">${esc(e.author ? `${e.author} · ` : '')}${esc(String(e.deployed_at || '').slice(11, 16))} UTC</span></div>`).join('')}</div></section>`).join('\n');
const postsHtml = posts.length ? `<aside class="ov-shipped-posts"><h3>Patch notes</h3><ul>${posts.map((p) => `<li><a href="${esc(p.url)}">${esc(p.title || 'Patch notes')}</a>${p.published_at ? ` <small>${esc(String(p.published_at).slice(0, 10))}</small>` : ''}</li>`).join('')}</ul></aside>` : '';
const postsHtml = posts.length ? `<aside class="ov-shipped-posts"><h3>Patch notes</h3><ul>${posts.map((p) => `<li><a href="${esc(p.url)}">${esc(p.title || 'Patch notes')}</a>${p.published_at ? ` <small>${esc(String(p.published_at).slice(0, 10))}</small>` : ''}</li>`).join('')}</ul></aside>` : '';
+ // The no-JS site filter (links): inside the shipped mount, so shipped.js's own filter bar replaces it rather than
+ // adding a second row.
const chips = `<nav class="up-sites" aria-label="Sites"><a href="/updates"${site ? '' : ' aria-current="page"'}>Everything</a>${SITES.filter((s) => s !== 'sites').map((s) => `<a href="/updates?site=${s}"${site === s ? ' aria-current="page"' : ''}>${esc(nameOf(s))}</a>`).join('')}</nav>`;
const chips = `<nav class="up-sites" aria-label="Sites"><a href="/updates"${site ? '' : ' aria-current="page"'}>Everything</a>${SITES.filter((s) => s !== 'sites').map((s) => `<a href="/updates?site=${s}"${site === s ? ' aria-current="page"' : ''}>${esc(nameOf(s))}</a>`).join('')}</nav>`;
return `<!DOCTYPE html>
return `<!DOCTYPE html>
<html lang="en">
<html lang="en">
@@ -132,8 +134,8 @@ ${require('openvibe-shared/frame').noscriptNav({ name: 'OpenVibe.Network', links
@@ -132,8 +134,8 @@ ${require('openvibe-shared/frame').noscriptNav({ name: 'OpenVibe.Network', links
<main class="up" id="main">
<main class="up" id="main">
<h1>${esc(title)}</h1>
<h1>${esc(title)}</h1>
<p class="lede">Every change deployed to OpenVibe, newest first. Each line is a commit from the OpenVibers repositories, linked to the change itself. When enough have gathered, or a large feature lands, they are written up as <a href="https://openvibe.blog/@openvibe">Patch notes on openvibe.blog</a>. JSON: <a href="/api/v1/changelog"><code>/api/v1/changelog</code></a>.</p>
<p class="lede">Every change deployed to OpenVibe, newest first. Each line is a commit from the OpenVibers repositories, linked to the change itself. When enough have gathered, or a large feature lands, they are written up as <a href="https://openvibe.blog/@openvibe">Patch notes on openvibe.blog</a>. JSON: <a href="/api/v1/changelog"><code>/api/v1/changelog</code></a>.</p>
-${chips}
<div data-ov-shipped="log" data-service="${esc(site || '')}" data-limit="50">
<div data-ov-shipped="log" data-service="${esc(site || '')}" data-limit="50">
+${chips}
${postsHtml}
${postsHtml}
${dayHtml || '<p class="ov-shipped-empty">The update history could not be loaded just now.</p>'}
${dayHtml || '<p class="ov-shipped-empty">The update history could not be loaded just now.</p>'}
</div>
</div>
@@ -39,6 +39,12 @@ const publicCors = require('../server/public-cors');
@@ -39,6 +39,12 @@ const publicCors = require('../server/public-cors');
assert.ok(page.includes('Fix <script>x</script> in pages') && !page.includes('<script>x</script>'), 'commit text escaped in the SSR log');
assert.ok(page.includes('Fix <script>x</script> in pages') && !page.includes('<script>x</script>'), 'commit text escaped in the SSR log');
assert.ok(page.includes('https://openvibe.blog/@openvibe/x'), 'patch notes listed');
assert.ok(page.includes('https://openvibe.blog/@openvibe/x'), 'patch notes listed');
assert.ok(page.includes('<link rel="canonical" href="https://openvibe.network/updates">'));
assert.ok(page.includes('<link rel="canonical" href="https://openvibe.network/updates">'));
+ // One filter row: the no-JS site links sit inside the shipped mount, which shipped.js empties and refills with its own bar.
+ const mount = page.indexOf('data-ov-shipped="log"'), nav = page.indexOf('<nav class="up-sites"');
+ assert.ok(nav > mount && page.indexOf('</div>', mount) > nav, 'the site links are inside the shipped mount');
+ assert.strictEqual(page.split('class="up-sites"').length - 1, 1, 'one site filter');
+ assert.ok(page.includes('<a href="/updates?site=bot">Bot</a>'), 'Bot is a site');
+ assert.strictEqual(serviceFor('bot'), 'bot');
const one = await fetch(`${base}/updates?site=openvibe.wiki`);
const one = await fetch(`${base}/updates?site=openvibe.wiki`);
assert.strictEqual(one.headers.get('x-robots-tag'), 'noindex, follow');
assert.strictEqual(one.headers.get('x-robots-tag'), 'noindex, follow');
assert.ok((await one.text()).includes('What shipped on OpenVibe.Wiki'));
assert.ok((await one.text()).includes('What shipped on OpenVibe.Wiki'));