@zeropress/build-pages 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,121 @@
1
+ const searchRoot = document.querySelector('[data-site-search]');
2
+
3
+ if (searchRoot) {
4
+ const form = searchRoot.querySelector('[data-site-search-form]');
5
+ const input = searchRoot.querySelector('[data-site-search-input]');
6
+ const panel = searchRoot.querySelector('[data-site-search-panel]');
7
+ const status = searchRoot.querySelector('[data-site-search-status]');
8
+ const resultsList = searchRoot.querySelector('[data-site-search-results]');
9
+ let searchApiPromise;
10
+ let debounceTimer;
11
+ let requestId = 0;
12
+
13
+ const loadSearchApi = () => {
14
+ searchApiPromise ||= import('/_zeropress/search.js');
15
+ return searchApiPromise;
16
+ };
17
+
18
+ const clearResults = () => {
19
+ resultsList.replaceChildren();
20
+ };
21
+
22
+ const showPanel = () => {
23
+ panel.hidden = false;
24
+ };
25
+
26
+ const hidePanel = () => {
27
+ panel.hidden = true;
28
+ };
29
+
30
+ const setStatus = (message) => {
31
+ status.textContent = message;
32
+ };
33
+
34
+ const renderResults = async (items) => {
35
+ clearResults();
36
+ if (!items.length) {
37
+ setStatus('No results found.');
38
+ return;
39
+ }
40
+
41
+ setStatus(`${items.length} result${items.length === 1 ? '' : 's'} found.`);
42
+ const fragment = document.createDocumentFragment();
43
+
44
+ for (const item of items) {
45
+ const data = await item.data();
46
+ const title = data.meta?.title || data.url;
47
+ const excerpt = data.plain_excerpt || data.excerpt || '';
48
+ const listItem = document.createElement('li');
49
+ const link = document.createElement('a');
50
+ const meta = document.createElement('span');
51
+ const summary = document.createElement('p');
52
+
53
+ link.href = data.url;
54
+ link.textContent = title;
55
+ meta.textContent = data.meta?.type || 'page';
56
+ summary.textContent = excerpt;
57
+
58
+ listItem.append(link, meta, summary);
59
+ fragment.append(listItem);
60
+ }
61
+
62
+ resultsList.append(fragment);
63
+ };
64
+
65
+ const runSearch = async () => {
66
+ const query = input.value.trim();
67
+ const currentRequest = ++requestId;
68
+ showPanel();
69
+
70
+ if (query.length < 2) {
71
+ clearResults();
72
+ setStatus('Type at least two characters.');
73
+ return;
74
+ }
75
+
76
+ setStatus('Searching...');
77
+ clearResults();
78
+
79
+ try {
80
+ const searchApi = await loadSearchApi();
81
+ const response = await searchApi.search(query, { limit: 8 });
82
+ if (currentRequest === requestId) {
83
+ await renderResults(response.results || []);
84
+ }
85
+ } catch {
86
+ if (currentRequest === requestId) {
87
+ clearResults();
88
+ setStatus('Search is not available for this build.');
89
+ }
90
+ }
91
+ };
92
+
93
+ input.addEventListener('input', () => {
94
+ window.clearTimeout(debounceTimer);
95
+ debounceTimer = window.setTimeout(runSearch, 160);
96
+ });
97
+
98
+ input.addEventListener('focus', () => {
99
+ if (input.value.trim()) {
100
+ showPanel();
101
+ }
102
+ });
103
+
104
+ form.addEventListener('submit', (event) => {
105
+ event.preventDefault();
106
+ runSearch();
107
+ });
108
+
109
+ document.addEventListener('keydown', (event) => {
110
+ if (event.key === 'Escape') {
111
+ hidePanel();
112
+ input.blur();
113
+ }
114
+ });
115
+
116
+ document.addEventListener('click', (event) => {
117
+ if (!searchRoot.contains(event.target)) {
118
+ hidePanel();
119
+ }
120
+ });
121
+ }
@@ -13,9 +13,24 @@
13
13
  <header class="site-header">
14
14
  <div class="shell site-header__inner">
15
15
  <a class="brand" href="/">{{site.title}}</a>
16
- <nav class="site-nav" aria-label="Primary navigation">
17
- {{menu:primary}}
18
- </nav>
16
+ <div class="site-header__actions">
17
+ <nav class="site-nav" aria-label="Primary navigation">
18
+ {{menu:primary}}
19
+ </nav>
20
+ {{#if site.search}}
21
+ <div class="site-search" data-site-search>
22
+ <form class="site-search__form" role="search" data-site-search-form>
23
+ <label class="visually-hidden" for="site-search-input">Search docs</label>
24
+ <input id="site-search-input" class="site-search__input" type="search" placeholder="Search docs" autocomplete="off" spellcheck="false" data-site-search-input>
25
+ <button class="site-search__button" type="submit">Search</button>
26
+ </form>
27
+ <div class="site-search__panel" data-site-search-panel hidden>
28
+ <p class="site-search__status" data-site-search-status>Type to search documentation.</p>
29
+ <ol class="site-search__results" data-site-search-results></ol>
30
+ </div>
31
+ </div>
32
+ {{/if}}
33
+ </div>
19
34
  </div>
20
35
  </header>
21
36
  <main id="content">
@@ -33,5 +48,6 @@
33
48
  {{/if}}
34
49
  </div>
35
50
  </footer>
51
+ {{partial:theme-scripts}}
36
52
  </body>
37
53
  </html>
@@ -1,7 +1,7 @@
1
1
  <article class="shell doc-layout{{#if page.toc}} doc-layout--with-toc{{/if}}">
2
2
  <div class="doc-content">
3
3
  {{#if route.is_front_page}}
4
- <div class="prose">
4
+ <div class="prose" {{#if site.search}}{{#if_neq page.discoverability "delist"}}data-pagefind-body{{/if_neq}}{{/if}}>
5
5
  {{page.html}}
6
6
  </div>
7
7
  {{#else}}
@@ -10,7 +10,7 @@
10
10
  <h1>{{page.title}}</h1>
11
11
  {{#if page.excerpt}}<p class="lede">{{page.excerpt}}</p>{{/if}}
12
12
  </header>
13
- <div class="prose">
13
+ <div class="prose" {{#if site.search}}{{#if_neq page.discoverability "delist"}}data-pagefind-body{{/if_neq}}{{/if}}>
14
14
  {{page.html}}
15
15
  </div>
16
16
  {{/if}}
@@ -0,0 +1 @@
1
+ <script type="module" src="/assets/theme.js"></script>
@@ -3,7 +3,7 @@
3
3
  <p class="eyebrow">Post</p>
4
4
  <h1>{{post.title}}</h1>
5
5
  </header>
6
- <div class="prose">
6
+ <div class="prose" {{#if site.search}}{{#if_neq post.discoverability "delist"}}data-pagefind-body{{/if_neq}}{{/if}}>
7
7
  {{post.html}}
8
8
  </div>
9
9
  </article>
@@ -7,9 +7,8 @@
7
7
  "runtime": "0.6",
8
8
  "description": "Bundled documentation theme for @zeropress/build-pages",
9
9
  "features": {
10
- "comments": false,
11
- "newsletter": false,
12
- "post_index": false
10
+ "post_index": false,
11
+ "search": true
13
12
  },
14
13
  "menu_slots": {
15
14
  "primary": {