openvibers/openvibe.shared Commits
1.11.1: the footer's shipped line follows the footer's own service (a local or unmapped host showed the whole network); an id that is not a registry id falls back to the hostname
Changes
@@@ -4,6 +4,10 @@ All notable changes to `openvibe-shared`. Versions follow [semver](https://semvebreaking change to any exported module, browser global or served file name is a new major.A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).++## 1.11.1 — 2026-09-24++++Fix: the footer's "shipped X ago" line uses the footer's own `service` (`live`, `wiki`, …). Before, it resolved the page's hostname, so a local or unmapped host showed the whole network. A site id that is not a registry id (a Tools satellite's `dev`) falls back to the hostname rather than to the whole network.++## 1.11.0 — 2026-09-24**The OpenVibe Frame.** The shared navbar, footer and "shipped" views every OpenVibe site sits in were called the "chrome", which was borrowed jargon easily mistaken for the browser. They are now the Frame:@@@ -191,7 +191,7 @@if (c.shipped === false) return '';const host = typeof location !== 'undefined' ? location.hostname : '';const updates = c.updates || `${NETWORK_URL}/updates?site=${encodeURIComponent(host || c.service || '')}`;-- return `<a class="ovf-shipped" data-ov-shipped="latest" data-service="auto" href="${esc(updates)}" hidden></a>`;++ return `<a class="ovf-shipped" data-ov-shipped="latest" data-service="${esc(c.service || 'auto')}" href="${esc(updates)}" hidden></a>`;}function updatesHref(c) {const host = typeof location !== 'undefined' ? location.hostname : '';@@@ -1,12 +1,12 @@{"name": "openvibe-shared",-- "version": "1.11.0",++ "version": "1.11.1","lockfileVersion": 3,"requires": true,"packages": {"": {"name": "openvibe-shared",-- "version": "1.11.0",++ "version": "1.11.1","license": "MIT","dependencies": {"jsonwebtoken": "^9.0.0"@@@ -1,6 +1,6 @@{"name": "openvibe-shared",-- "version": "1.11.0",++ "version": "1.11.1","description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site","main": "index.js","exports": {@@@ -124,9 +124,11 @@const m = /(?:^|\.)openvibe\.([a-z]+)$/.exec(h);return m && SITE_NAMES[m[1]] ? m[1] : null;}++ /** 'auto' = this page's host; a site id that is not a registry id (a Tools satellite's 'dev') also falls back to the host; '' = the whole network. */function resolveService(s) {-- if (s === 'auto') return typeof location !== 'undefined' ? serviceFor(location.hostname) : null;-- return s ? serviceFor(s) : null;++ const host = () => (typeof location !== 'undefined' ? serviceFor(location.hostname) : null);++ if (s === 'auto') return host();++ return s ? (serviceFor(s) || host()) : null;}// One request per feed URL for 30 s, shared by the footer line, the pill and the list on a page.@@@ -88,6 +88,15 @@ const data = {assert.strictEqual(sf('www.openvibe.live'), 'live');assert.strictEqual(sf('example.com'), null);assert.strictEqual(sf('live'), 'live');++ // A footer's own site id wins over the page's host; an id that is not a registry id falls back to the host.++ globalThis.location = { hostname: 'dev.openvibe.tools' };++ const own = document.createElement('a');++ await shipped.latest(own, { service: 'live', api: 'https://example.test/feed' });++ globalThis.fetch = async (url) => ({ ok: true, json: async () => ({ entries: [{ service: new URL(url).searchParams.get('service') || 'all', subject: 's', deployed_at: new Date().toISOString() }] }) });++ const sat = document.createElement('a');++ await shipped.latest(sat, { service: 'dev', api: 'https://example.test/feed2' });++ assert.ok(sat.textContent.includes('shipped') && !sat.textContent.includes('all shipped'), 'a satellite id resolves to tools by host');++ delete globalThis.location;// log(): pages with the cursor, and the "Load more" button disappears on the last page.const calls = [];
@@ -4,6 +4,10 @@ All notable changes to `openvibe-shared`. Versions follow [semver](https://semve
@@ -4,6 +4,10 @@ All notable changes to `openvibe-shared`. Versions follow [semver](https://semve
breaking change to any exported module, browser global or served file name is a new major.
breaking change to any exported module, browser global or served file name is a new major.
A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
A release is the git tag `vX.Y.Z`; consumers pin the tag's tarball (see README).
+## 1.11.1 — 2026-09-24
+
+Fix: the footer's "shipped X ago" line uses the footer's own `service` (`live`, `wiki`, …). Before, it resolved the page's hostname, so a local or unmapped host showed the whole network. A site id that is not a registry id (a Tools satellite's `dev`) falls back to the hostname rather than to the whole network.
+
## 1.11.0 — 2026-09-24
## 1.11.0 — 2026-09-24
**The OpenVibe Frame.** The shared navbar, footer and "shipped" views every OpenVibe site sits in were called the "chrome", which was borrowed jargon easily mistaken for the browser. They are now the Frame:
**The OpenVibe Frame.** The shared navbar, footer and "shipped" views every OpenVibe site sits in were called the "chrome", which was borrowed jargon easily mistaken for the browser. They are now the Frame:
@@ -191,7 +191,7 @@
@@ -191,7 +191,7 @@
if (c.shipped === false) return '';
if (c.shipped === false) return '';
const host = typeof location !== 'undefined' ? location.hostname : '';
const host = typeof location !== 'undefined' ? location.hostname : '';
const updates = c.updates || `${NETWORK_URL}/updates?site=${encodeURIComponent(host || c.service || '')}`;
const updates = c.updates || `${NETWORK_URL}/updates?site=${encodeURIComponent(host || c.service || '')}`;
- return `<a class="ovf-shipped" data-ov-shipped="latest" data-service="auto" href="${esc(updates)}" hidden></a>`;
+ return `<a class="ovf-shipped" data-ov-shipped="latest" data-service="${esc(c.service || 'auto')}" href="${esc(updates)}" hidden></a>`;
}
}
function updatesHref(c) {
function updatesHref(c) {
const host = typeof location !== 'undefined' ? location.hostname : '';
const host = typeof location !== 'undefined' ? location.hostname : '';
@@ -1,12 +1,12 @@
@@ -1,12 +1,12 @@
{
{
"name": "openvibe-shared",
"name": "openvibe-shared",
- "version": "1.11.0",
+ "version": "1.11.1",
"lockfileVersion": 3,
"lockfileVersion": 3,
"requires": true,
"requires": true,
"packages": {
"packages": {
"": {
"": {
"name": "openvibe-shared",
"name": "openvibe-shared",
- "version": "1.11.0",
+ "version": "1.11.1",
"license": "MIT",
"license": "MIT",
"dependencies": {
"dependencies": {
"jsonwebtoken": "^9.0.0"
"jsonwebtoken": "^9.0.0"
@@ -1,6 +1,6 @@
@@ -1,6 +1,6 @@
{
{
"name": "openvibe-shared",
"name": "openvibe-shared",
- "version": "1.11.0",
+ "version": "1.11.1",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"description": "Shared navbar, footer, themes, icons, legal pages, SEO, auth and analytics for every OpenVibe site",
"main": "index.js",
"main": "index.js",
"exports": {
"exports": {
@@ -124,9 +124,11 @@
@@ -124,9 +124,11 @@
const m = /(?:^|\.)openvibe\.([a-z]+)$/.exec(h);
const m = /(?:^|\.)openvibe\.([a-z]+)$/.exec(h);
return m && SITE_NAMES[m[1]] ? m[1] : null;
return m && SITE_NAMES[m[1]] ? m[1] : null;
}
}
+ /** 'auto' = this page's host; a site id that is not a registry id (a Tools satellite's 'dev') also falls back to the host; '' = the whole network. */
function resolveService(s) {
function resolveService(s) {
- if (s === 'auto') return typeof location !== 'undefined' ? serviceFor(location.hostname) : null;
- return s ? serviceFor(s) : null;
+ const host = () => (typeof location !== 'undefined' ? serviceFor(location.hostname) : null);
+ if (s === 'auto') return host();
+ return s ? (serviceFor(s) || host()) : null;
}
}
// One request per feed URL for 30 s, shared by the footer line, the pill and the list on a page.
// One request per feed URL for 30 s, shared by the footer line, the pill and the list on a page.
@@ -88,6 +88,15 @@ const data = {
@@ -88,6 +88,15 @@ const data = {
assert.strictEqual(sf('www.openvibe.live'), 'live');
assert.strictEqual(sf('www.openvibe.live'), 'live');
assert.strictEqual(sf('example.com'), null);
assert.strictEqual(sf('example.com'), null);
assert.strictEqual(sf('live'), 'live');
assert.strictEqual(sf('live'), 'live');
+ // A footer's own site id wins over the page's host; an id that is not a registry id falls back to the host.
+ globalThis.location = { hostname: 'dev.openvibe.tools' };
+ const own = document.createElement('a');
+ await shipped.latest(own, { service: 'live', api: 'https://example.test/feed' });
+ globalThis.fetch = async (url) => ({ ok: true, json: async () => ({ entries: [{ service: new URL(url).searchParams.get('service') || 'all', subject: 's', deployed_at: new Date().toISOString() }] }) });
+ const sat = document.createElement('a');
+ await shipped.latest(sat, { service: 'dev', api: 'https://example.test/feed2' });
+ assert.ok(sat.textContent.includes('shipped') && !sat.textContent.includes('all shipped'), 'a satellite id resolves to tools by host');
+ delete globalThis.location;
// log(): pages with the cursor, and the "Load more" button disappears on the last page.
// log(): pages with the cursor, and the "Load more" button disappears on the last page.
const calls = [];
const calls = [];