openvibers/openvibe.wiki Commits
Search has one box (#185)
Changes
@@@ -642,10 +642,20 @@ ${p.note ? html`<br><span class="wk-muted">${p.note}</span>` : ''}</section>`;}++// One search box: the site bar above (layout.js) carries the query; the page names it and lists what matched. The page had++// its own second form under the bar (2026-11-01).function searchPage({ query, results }) {-- return html`<section><h1>Search</h1>--<form action="/search" method="get" class="wk-form" role="search"><label>Words <input type="search" name="q" value="${query || ''}"></label><button type="submit">Search</button></form>--${query ? (results.length ? html`<ol class="wk-results">${results.map((r) => html`<li><a href="${wpath(r.space, r.page)}">${r.page.title}</a> <span class="wk-muted">${r.space.name}</span><br>${r.summary}</li>`)}</ol>` : html`<p>No published page matches.</p>`) : ''}++ if (!query) {++ return html`<section><h1>Search the wiki</h1>++<p>Type in the search bar above: it looks through the title and text of every public page.</p>++<p class="wk-search-next"><a href="/recent">Recent changes</a> · <a href="/">All wikis</a></p>++</section>`;++ }++ const n = results.length;++ return html`<section><h1>Results for “${query}”</h1>++${n ? html`<p class="wk-muted">${String(n)} ${n === 1 ? 'page matches' : 'pages match'}</p>++<ol class="wk-results">${results.map((r) => html`<li><a href="${wpath(r.space, r.page)}">${r.page.title}</a> <span class="wk-muted">${r.space.name}</span><br>${r.summary}</li>`)}</ol>`++ : html`<p>No published page matches. Try fewer or different words, or look through <a href="/recent">recent changes</a> and <a href="/">all wikis</a>.</p>`}</section>`;}nnew file mode 100644@@@ -0,0 +1,32 @@++'use strict';++/**++ * The search page has one search box: the site bar (layout.js) carries the query, and the page names it and lists what++ * matched. It used to draw a second form ("Words") under the bar (2026-11-01).++ */++const assert = require('assert');++const H = require('./helpers');++++const count = (s, re) => (s.match(re) || []).length;++++(async () => {++ const h = await H.boot();++ try {++ let r = await H.req(h, 'GET', '/search');++ assert.strictEqual(r.status, 200);++ assert.strictEqual(count(r.text, /role="search"/g), 1, 'one search form: the bar');++ assert.ok(!r.text.includes('<label>Words'), 'no second form');++ assert.ok(r.text.includes('<h1>Search the wiki</h1>'), 'the empty page says what to do');++ assert.ok(r.text.includes('href="/recent"') && r.text.includes('>All wikis</a>'), 'and where to go instead');++++ r = await H.req(h, 'GET', '/search?q=nothing-matches-this-xyz');++ assert.strictEqual(count(r.text, /role="search"/g), 1);++ assert.ok(r.text.includes('Results for “nothing-matches-this-xyz”'), 'the heading names the query');++ assert.ok(r.text.includes('No published page matches.'), 'and says when nothing matched');++++ r = await H.req(h, 'GET', '/search?q=%3Cscript%3Ealert(1)%3C%2Fscript%3E');++ assert.ok(!r.text.includes('<script>alert(1)</script>'), 'the query is escaped in the heading');++ } finally {++ await h.stop();++ }++ console.log('search page: all checks passed');++})().catch((e) => { console.error(e); process.exit(1); });
@@ -642,10 +642,20 @@ ${p.note ? html`<br><span class="wk-muted">${p.note}</span>` : ''}
@@ -642,10 +642,20 @@ ${p.note ? html`<br><span class="wk-muted">${p.note}</span>` : ''}
</section>`;
</section>`;
}
}
+// One search box: the site bar above (layout.js) carries the query; the page names it and lists what matched. The page had
+// its own second form under the bar (2026-11-01).
function searchPage({ query, results }) {
function searchPage({ query, results }) {
- return html`<section><h1>Search</h1>
-<form action="/search" method="get" class="wk-form" role="search"><label>Words <input type="search" name="q" value="${query || ''}"></label><button type="submit">Search</button></form>
-${query ? (results.length ? html`<ol class="wk-results">${results.map((r) => html`<li><a href="${wpath(r.space, r.page)}">${r.page.title}</a> <span class="wk-muted">${r.space.name}</span><br>${r.summary}</li>`)}</ol>` : html`<p>No published page matches.</p>`) : ''}
+ if (!query) {
+ return html`<section><h1>Search the wiki</h1>
+<p>Type in the search bar above: it looks through the title and text of every public page.</p>
+<p class="wk-search-next"><a href="/recent">Recent changes</a> · <a href="/">All wikis</a></p>
+</section>`;
+ }
+ const n = results.length;
+ return html`<section><h1>Results for “${query}”</h1>
+${n ? html`<p class="wk-muted">${String(n)} ${n === 1 ? 'page matches' : 'pages match'}</p>
+<ol class="wk-results">${results.map((r) => html`<li><a href="${wpath(r.space, r.page)}">${r.page.title}</a> <span class="wk-muted">${r.space.name}</span><br>${r.summary}</li>`)}</ol>`
+ : html`<p>No published page matches. Try fewer or different words, or look through <a href="/recent">recent changes</a> and <a href="/">all wikis</a>.</p>`}
</section>`;
</section>`;
}
}
new file mode 100644
new file mode 100644
@@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
+'use strict';
+/**
+ * The search page has one search box: the site bar (layout.js) carries the query, and the page names it and lists what
+ * matched. It used to draw a second form ("Words") under the bar (2026-11-01).
+ */
+const assert = require('assert');
+const H = require('./helpers');
+
+const count = (s, re) => (s.match(re) || []).length;
+
+(async () => {
+ const h = await H.boot();
+ try {
+ let r = await H.req(h, 'GET', '/search');
+ assert.strictEqual(r.status, 200);
+ assert.strictEqual(count(r.text, /role="search"/g), 1, 'one search form: the bar');
+ assert.ok(!r.text.includes('<label>Words'), 'no second form');
+ assert.ok(r.text.includes('<h1>Search the wiki</h1>'), 'the empty page says what to do');
+ assert.ok(r.text.includes('href="/recent"') && r.text.includes('>All wikis</a>'), 'and where to go instead');
+
+ r = await H.req(h, 'GET', '/search?q=nothing-matches-this-xyz');
+ assert.strictEqual(count(r.text, /role="search"/g), 1);
+ assert.ok(r.text.includes('Results for “nothing-matches-this-xyz”'), 'the heading names the query');
+ assert.ok(r.text.includes('No published page matches.'), 'and says when nothing matched');
+
+ r = await H.req(h, 'GET', '/search?q=%3Cscript%3Ealert(1)%3C%2Fscript%3E');
+ assert.ok(!r.text.includes('<script>alert(1)</script>'), 'the query is escaped in the heading');
+ } finally {
+ await h.stop();
+ }
+ console.log('search page: all checks passed');
+})().catch((e) => { console.error(e); process.exit(1); });