openvibers/openvibe.network Commits
A profile names the Live channel by its @handle (#752)
Changes
@@@ -391,7 +391,7 @@ function monthDay(day) {function publicPlacesHtml(places) {const cards = [];-- if (places.live) cards.push(`<li><a href="${esc(places.live.url)}"><strong>${esc(places.live.title)}</strong>${places.live.is_live ? '<span class="pf-live">Live now</span>' : '<span>Live channel</span>'}</a></li>`);++ if (places.live) cards.push(`<li><a href="${esc(places.live.url)}"><strong>@${esc(places.live.username || places.live.title)}</strong>${places.live.is_live ? '<span class="pf-live">Live now</span>' : '<span>Live channel</span>'}</a></li>`);for (const video of places.videos || []) cards.push(`<li><a href="${esc(video.url)}"><strong>${esc(video.title)}</strong><span>Video${video.date ? ` · ${esc(monthDay(video.date))}` : ''}</span></a></li>`);for (const space of places.spaces || []) cards.push(`<li><a href="${esc(space.url)}"><strong>${esc(space.title)}</strong><span>Published site</span></a></li>`);for (const paste of places.community || []) cards.push(`<li><a href="${esc(paste.url)}"><strong>${esc(paste.title)}</strong><span>Community paste</span></a></li>`);@@@ -100,6 +100,7 @@ const INSTANCES = [assert.ok(!r.text.includes('<script>alert(1)</script>') && r.text.includes('Hello there'), 'the saved public-page bio is shown as text');assert.ok(r.text.includes('href="https://example.com/"'), 'HTTPS public links render');assert.ok(r.text.includes('aria-labelledby="pf-places"') && r.text.includes('Live now') && r.text.includes('First video') && r.text.includes('Video · Nov 7, 2026') && r.text.includes('A public note') && r.text.includes('Ana Site'));++ assert.ok(/<a href="https:\/\/openvibe\.live\/@Ana"><strong>@Ana<\/strong>/.test(r.text), 'her Live channel is named by its @handle, as its address is');assert.ok(!r.text.includes('Private video') && !r.text.includes('Hidden note') && !r.text.includes('Hidden Site'), 'private or unlisted places are omitted');assert.ok(r.text.includes('Sparkles <b>') && !r.text.includes('Sparkles <b>'), 'item names are escaped');assert.ok(r.text.includes('id="pf-wearing"') && /pf-worn r-legendary[\s\S]*Royal Crown/.test(r.text), 'the crown is in the showcase');
@@ -391,7 +391,7 @@ function monthDay(day) {
@@ -391,7 +391,7 @@ function monthDay(day) {
function publicPlacesHtml(places) {
function publicPlacesHtml(places) {
const cards = [];
const cards = [];
- if (places.live) cards.push(`<li><a href="${esc(places.live.url)}"><strong>${esc(places.live.title)}</strong>${places.live.is_live ? '<span class="pf-live">Live now</span>' : '<span>Live channel</span>'}</a></li>`);
+ if (places.live) cards.push(`<li><a href="${esc(places.live.url)}"><strong>@${esc(places.live.username || places.live.title)}</strong>${places.live.is_live ? '<span class="pf-live">Live now</span>' : '<span>Live channel</span>'}</a></li>`);
for (const video of places.videos || []) cards.push(`<li><a href="${esc(video.url)}"><strong>${esc(video.title)}</strong><span>Video${video.date ? ` · ${esc(monthDay(video.date))}` : ''}</span></a></li>`);
for (const video of places.videos || []) cards.push(`<li><a href="${esc(video.url)}"><strong>${esc(video.title)}</strong><span>Video${video.date ? ` · ${esc(monthDay(video.date))}` : ''}</span></a></li>`);
for (const space of places.spaces || []) cards.push(`<li><a href="${esc(space.url)}"><strong>${esc(space.title)}</strong><span>Published site</span></a></li>`);
for (const space of places.spaces || []) cards.push(`<li><a href="${esc(space.url)}"><strong>${esc(space.title)}</strong><span>Published site</span></a></li>`);
for (const paste of places.community || []) cards.push(`<li><a href="${esc(paste.url)}"><strong>${esc(paste.title)}</strong><span>Community paste</span></a></li>`);
for (const paste of places.community || []) cards.push(`<li><a href="${esc(paste.url)}"><strong>${esc(paste.title)}</strong><span>Community paste</span></a></li>`);
@@ -100,6 +100,7 @@ const INSTANCES = [
@@ -100,6 +100,7 @@ const INSTANCES = [
assert.ok(!r.text.includes('<script>alert(1)</script>') && r.text.includes('Hello there'), 'the saved public-page bio is shown as text');
assert.ok(!r.text.includes('<script>alert(1)</script>') && r.text.includes('Hello there'), 'the saved public-page bio is shown as text');
assert.ok(r.text.includes('href="https://example.com/"'), 'HTTPS public links render');
assert.ok(r.text.includes('href="https://example.com/"'), 'HTTPS public links render');
assert.ok(r.text.includes('aria-labelledby="pf-places"') && r.text.includes('Live now') && r.text.includes('First video') && r.text.includes('Video · Nov 7, 2026') && r.text.includes('A public note') && r.text.includes('Ana Site'));
assert.ok(r.text.includes('aria-labelledby="pf-places"') && r.text.includes('Live now') && r.text.includes('First video') && r.text.includes('Video · Nov 7, 2026') && r.text.includes('A public note') && r.text.includes('Ana Site'));
+ assert.ok(/<a href="https:\/\/openvibe\.live\/@Ana"><strong>@Ana<\/strong>/.test(r.text), 'her Live channel is named by its @handle, as its address is');
assert.ok(!r.text.includes('Private video') && !r.text.includes('Hidden note') && !r.text.includes('Hidden Site'), 'private or unlisted places are omitted');
assert.ok(!r.text.includes('Private video') && !r.text.includes('Hidden note') && !r.text.includes('Hidden Site'), 'private or unlisted places are omitted');
assert.ok(r.text.includes('Sparkles <b>') && !r.text.includes('Sparkles <b>'), 'item names are escaped');
assert.ok(r.text.includes('Sparkles <b>') && !r.text.includes('Sparkles <b>'), 'item names are escaped');
assert.ok(r.text.includes('id="pf-wearing"') && /pf-worn r-legendary[\s\S]*Royal Crown/.test(r.text), 'the crown is in the showcase');
assert.ok(r.text.includes('id="pf-wearing"') && /pf-worn r-legendary[\s\S]*Royal Crown/.test(r.text), 'the crown is in the showcase');