openvibers/openvibe.events Commits
Events' page list names its home and the GitHub guide for what they are (#315)
Changes
@@@ -51,7 +51,14 @@ function createApp({ config, store, auth, keys, worker, realtime, metrics, dnsLo// Terms, Privacy and DMCA in this site's own words (openvibe-shared/legal, profile 'service'; 11-03: the footer's// legal links answered 404 here). The facts must match the code: change both together.const legal = require('openvibe-shared/legal');-- app.get(legal.PATHS, legal.handler({++ // Shared's legal template starts the navbar without links, so /terms and /privacy showed its fallback++ // (Home, My Account, Themes) instead of Events' own pages. Add Events' list to that init call.++ const navLinks = JSON.stringify(require('./home').NAV_LINKS);++ app.get(legal.PATHS, (req, res, next) => {++ const send = res.send.bind(res);++ res.send = (body) => send(String(body).replace('try{OpenVibeNavbar.init({service:', `try{OpenVibeNavbar.init({links:${navLinks},service:`));++ next();++ }, legal.handler({"host": "openvibe.events","name": "OpenVibe.Events","id": "events",@@@ -26,6 +26,8 @@ const ovIcons = require('openvibe-shared/ov-icons');const SITE_NAME = 'OpenVibe.Events';const NETWORK_URL = 'https://openvibe.network';const SOURCE = 'https://github.com/OpenVibers/OpenVibe.Events';++// The site's own places, the same on every page. The guide lives on GitHub, so its row is named for where it goes.++const NAV_LINKS = [{ label: 'Events', href: '/' }, { label: 'GitHub', href: `${SOURCE}#readme` }];const DESCRIPTION = 'The OpenVibe network\'s event bus: publish once and every subscriber gets it signed, retried and replayable, '+ 'by webhook, pull or realtime stream.';@@@ -457,7 +459,7 @@ const UPDATES_FONT = "<style>:where(body){font-family:var(--ov-font,'Inter',-app/** /updates: what shipped on this site, the network's shared update log (openvibe-shared/frame updatesBody). */function renderUpdates({ siteUrl }) {-- const links = [{ label: 'Guide', href: `${SOURCE}#readme` }];++ const links = NAV_LINKS;return shell.page({name: SITE_NAME, service: 'events', lang: 'en',title: `What shipped on ${SITE_NAME}`,@@@ -483,7 +485,7 @@ function renderHome({ siteUrl, apiUrl, stats = null }) {const nav = {service: 'events',apiBase: NETWORK_URL, sessionUrl: '/auth/me', loginUrl: '/auth/login?next={path}', logoutUrl: '/auth/logout?next={url}', silentLogin: '/auth/login?silent=1&next={url}',-- links: [{ label: 'Guide', href: `${SOURCE}#readme` }],++ links: NAV_LINKS,history: { type: 'page', title: SITE_NAME },};const footer = FOOTER;@@@ -507,7 +509,7 @@ function renderHome({ siteUrl, apiUrl, stats = null }) {// The publisher the site's own WebSite node names by @id, so the reference resolves on the page.seo.jsonLd.organization(),]),-- navbar: nav, footer, home: '/', navLinks: [{ label: 'Guide', href: `${SOURCE}#readme` }],++ navbar: nav, footer, home: '/', navLinks: NAV_LINKS,head: [appIcon.headTags({ site: 'events' }),`<link rel="stylesheet" href="${ovServe.url('kit.css')}"><script src="${ovServe.url('kit-web.js')}" defer></script>`,@@@ -527,7 +529,7 @@ ${sections({ apiUrl, stats })}*/function renderNotFound({ siteUrl = 'https://openvibe.events' } = {}) {const host = String(siteUrl).replace(/^https?:\/\//, '').replace(/\/.*$/, '');-- const links = [{ label: 'Guide', href: `${SOURCE}#readme` }];++ const links = NAV_LINKS;return shell.page({name: SITE_NAME, service: 'events', lang: 'en',title: `Page not found · ${SITE_NAME}`,@@@ -553,4 +555,4 @@ ${kit.pageHead({ title: `Page not found`, icon: 'live', back: { href: '/', label});}--module.exports = { renderHome, renderUpdates, renderNotFound, HOME_CSP, DESCRIPTION, sections };++module.exports = { renderHome, renderUpdates, renderNotFound, HOME_CSP, DESCRIPTION, sections, NAV_LINKS };nnew file mode 100644@@@ -0,0 +1,40 @@++'use strict';++// Every page of openvibe.events gives the shared navbar the site's own page list (the owner, 2026-11-12): the home,++// /updates, /terms, /privacy and /dmca all send Events / GitHub, and the GitHub row is named for where it goes.++const assert = require('assert');++const { boot, suite } = require('./helpers');++const { NAV_LINKS } = require('../server/home');++++function initLinks(html) {++ const at = html.indexOf('OpenVibeNavbar.init');++ if (at < 0) return null;++ const start = html.indexOf('links', at);++ const open = html.indexOf('[', start);++ let depth = 0, q = null, esc = false;++ for (let i = open; i < html.length; i += 1) {++ const c = html[i];++ if (q) { if (esc) esc = false; else if (c === '\\') esc = true; else if (c === q) q = null; continue; }++ if (c === '"' || c === "'") { q = c; continue; }++ if (c === '[') depth += 1; else if (c === ']') { depth -= 1; if (!depth) return JSON.parse(html.slice(open, i + 1)); }++ }++ return null;++}++++const t = suite('page-links');++++t('every page sends Events\' own list, and every row is labelled for where it goes', async () => {++ const h = await boot();++ try {++ const own = NAV_LINKS.map(({ label, href }) => ({ label, href }));++ assert.strictEqual(own[0].label, 'Events', 'the home row carries the site name');++ for (const path of ['/', '/updates', '/terms', '/privacy', '/dmca']) {++ const r = await fetch(h.base + path);++ assert.strictEqual(r.status, 200, `${path} answered ${r.status}`);++ const links = (initLinks(await r.text()) || []).map(({ label, href }) => ({ label, href }));++ assert.deepStrictEqual(links, own, `${path} sends Events' list`);++ }++ assert.ok(/GitHub/.test(own[1].label) && own[1].href.startsWith('https://github.com/'), 'the off-site guide is named GitHub');++ } finally { await h.stop(); }++});++++t.run();
@@ -51,7 +51,14 @@ function createApp({ config, store, auth, keys, worker, realtime, metrics, dnsLo
@@ -51,7 +51,14 @@ function createApp({ config, store, auth, keys, worker, realtime, metrics, dnsLo
// Terms, Privacy and DMCA in this site's own words (openvibe-shared/legal, profile 'service'; 11-03: the footer's
// Terms, Privacy and DMCA in this site's own words (openvibe-shared/legal, profile 'service'; 11-03: the footer's
// legal links answered 404 here). The facts must match the code: change both together.
// legal links answered 404 here). The facts must match the code: change both together.
const legal = require('openvibe-shared/legal');
const legal = require('openvibe-shared/legal');
- app.get(legal.PATHS, legal.handler({
+ // Shared's legal template starts the navbar without links, so /terms and /privacy showed its fallback
+ // (Home, My Account, Themes) instead of Events' own pages. Add Events' list to that init call.
+ const navLinks = JSON.stringify(require('./home').NAV_LINKS);
+ app.get(legal.PATHS, (req, res, next) => {
+ const send = res.send.bind(res);
+ res.send = (body) => send(String(body).replace('try{OpenVibeNavbar.init({service:', `try{OpenVibeNavbar.init({links:${navLinks},service:`));
+ next();
+ }, legal.handler({
"host": "openvibe.events",
"host": "openvibe.events",
"name": "OpenVibe.Events",
"name": "OpenVibe.Events",
"id": "events",
"id": "events",
@@ -26,6 +26,8 @@ const ovIcons = require('openvibe-shared/ov-icons');
@@ -26,6 +26,8 @@ const ovIcons = require('openvibe-shared/ov-icons');
const SITE_NAME = 'OpenVibe.Events';
const SITE_NAME = 'OpenVibe.Events';
const NETWORK_URL = 'https://openvibe.network';
const NETWORK_URL = 'https://openvibe.network';
const SOURCE = 'https://github.com/OpenVibers/OpenVibe.Events';
const SOURCE = 'https://github.com/OpenVibers/OpenVibe.Events';
+// The site's own places, the same on every page. The guide lives on GitHub, so its row is named for where it goes.
+const NAV_LINKS = [{ label: 'Events', href: '/' }, { label: 'GitHub', href: `${SOURCE}#readme` }];
const DESCRIPTION = 'The OpenVibe network\'s event bus: publish once and every subscriber gets it signed, retried and replayable, '
const DESCRIPTION = 'The OpenVibe network\'s event bus: publish once and every subscriber gets it signed, retried and replayable, '
+ 'by webhook, pull or realtime stream.';
+ 'by webhook, pull or realtime stream.';
@@ -457,7 +459,7 @@ const UPDATES_FONT = "<style>:where(body){font-family:var(--ov-font,'Inter',-app
@@ -457,7 +459,7 @@ const UPDATES_FONT = "<style>:where(body){font-family:var(--ov-font,'Inter',-app
/** /updates: what shipped on this site, the network's shared update log (openvibe-shared/frame updatesBody). */
/** /updates: what shipped on this site, the network's shared update log (openvibe-shared/frame updatesBody). */
function renderUpdates({ siteUrl }) {
function renderUpdates({ siteUrl }) {
- const links = [{ label: 'Guide', href: `${SOURCE}#readme` }];
+ const links = NAV_LINKS;
return shell.page({
return shell.page({
name: SITE_NAME, service: 'events', lang: 'en',
name: SITE_NAME, service: 'events', lang: 'en',
title: `What shipped on ${SITE_NAME}`,
title: `What shipped on ${SITE_NAME}`,
@@ -483,7 +485,7 @@ function renderHome({ siteUrl, apiUrl, stats = null }) {
@@ -483,7 +485,7 @@ function renderHome({ siteUrl, apiUrl, stats = null }) {
const nav = {
const nav = {
service: 'events',
service: 'events',
apiBase: NETWORK_URL, sessionUrl: '/auth/me', loginUrl: '/auth/login?next={path}', logoutUrl: '/auth/logout?next={url}', silentLogin: '/auth/login?silent=1&next={url}',
apiBase: NETWORK_URL, sessionUrl: '/auth/me', loginUrl: '/auth/login?next={path}', logoutUrl: '/auth/logout?next={url}', silentLogin: '/auth/login?silent=1&next={url}',
- links: [{ label: 'Guide', href: `${SOURCE}#readme` }],
+ links: NAV_LINKS,
history: { type: 'page', title: SITE_NAME },
history: { type: 'page', title: SITE_NAME },
};
};
const footer = FOOTER;
const footer = FOOTER;
@@ -507,7 +509,7 @@ function renderHome({ siteUrl, apiUrl, stats = null }) {
@@ -507,7 +509,7 @@ function renderHome({ siteUrl, apiUrl, stats = null }) {
// The publisher the site's own WebSite node names by @id, so the reference resolves on the page.
// The publisher the site's own WebSite node names by @id, so the reference resolves on the page.
seo.jsonLd.organization(),
seo.jsonLd.organization(),
]),
]),
- navbar: nav, footer, home: '/', navLinks: [{ label: 'Guide', href: `${SOURCE}#readme` }],
+ navbar: nav, footer, home: '/', navLinks: NAV_LINKS,
head: [
head: [
appIcon.headTags({ site: 'events' }),
appIcon.headTags({ site: 'events' }),
`<link rel="stylesheet" href="${ovServe.url('kit.css')}"><script src="${ovServe.url('kit-web.js')}" defer></script>`,
`<link rel="stylesheet" href="${ovServe.url('kit.css')}"><script src="${ovServe.url('kit-web.js')}" defer></script>`,
@@ -527,7 +529,7 @@ ${sections({ apiUrl, stats })}
@@ -527,7 +529,7 @@ ${sections({ apiUrl, stats })}
*/
*/
function renderNotFound({ siteUrl = 'https://openvibe.events' } = {}) {
function renderNotFound({ siteUrl = 'https://openvibe.events' } = {}) {
const host = String(siteUrl).replace(/^https?:\/\//, '').replace(/\/.*$/, '');
const host = String(siteUrl).replace(/^https?:\/\//, '').replace(/\/.*$/, '');
- const links = [{ label: 'Guide', href: `${SOURCE}#readme` }];
+ const links = NAV_LINKS;
return shell.page({
return shell.page({
name: SITE_NAME, service: 'events', lang: 'en',
name: SITE_NAME, service: 'events', lang: 'en',
title: `Page not found · ${SITE_NAME}`,
title: `Page not found · ${SITE_NAME}`,
@@ -553,4 +555,4 @@ ${kit.pageHead({ title: `Page not found`, icon: 'live', back: { href: '/', label
@@ -553,4 +555,4 @@ ${kit.pageHead({ title: `Page not found`, icon: 'live', back: { href: '/', label
});
});
}
}
-module.exports = { renderHome, renderUpdates, renderNotFound, HOME_CSP, DESCRIPTION, sections };
+module.exports = { renderHome, renderUpdates, renderNotFound, HOME_CSP, DESCRIPTION, sections, NAV_LINKS };
new file mode 100644
new file mode 100644
@@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
+'use strict';
+// Every page of openvibe.events gives the shared navbar the site's own page list (the owner, 2026-11-12): the home,
+// /updates, /terms, /privacy and /dmca all send Events / GitHub, and the GitHub row is named for where it goes.
+const assert = require('assert');
+const { boot, suite } = require('./helpers');
+const { NAV_LINKS } = require('../server/home');
+
+function initLinks(html) {
+ const at = html.indexOf('OpenVibeNavbar.init');
+ if (at < 0) return null;
+ const start = html.indexOf('links', at);
+ const open = html.indexOf('[', start);
+ let depth = 0, q = null, esc = false;
+ for (let i = open; i < html.length; i += 1) {
+ const c = html[i];
+ if (q) { if (esc) esc = false; else if (c === '\\') esc = true; else if (c === q) q = null; continue; }
+ if (c === '"' || c === "'") { q = c; continue; }
+ if (c === '[') depth += 1; else if (c === ']') { depth -= 1; if (!depth) return JSON.parse(html.slice(open, i + 1)); }
+ }
+ return null;
+}
+
+const t = suite('page-links');
+
+t('every page sends Events\' own list, and every row is labelled for where it goes', async () => {
+ const h = await boot();
+ try {
+ const own = NAV_LINKS.map(({ label, href }) => ({ label, href }));
+ assert.strictEqual(own[0].label, 'Events', 'the home row carries the site name');
+ for (const path of ['/', '/updates', '/terms', '/privacy', '/dmca']) {
+ const r = await fetch(h.base + path);
+ assert.strictEqual(r.status, 200, `${path} answered ${r.status}`);
+ const links = (initLinks(await r.text()) || []).map(({ label, href }) => ({ label, href }));
+ assert.deepStrictEqual(links, own, `${path} sends Events' list`);
+ }
+ assert.ok(/GitHub/.test(own[1].label) && own[1].href.startsWith('https://github.com/'), 'the off-site guide is named GitHub');
+ } finally { await h.stop(); }
+});
+
+t.run();