docula 1.2.0 → 1.6.0

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docula",
3
- "version": "1.2.0",
3
+ "version": "1.6.0",
4
4
  "description": "Beautiful Website for Your Projects",
5
5
  "type": "module",
6
6
  "main": "./dist/docula.js",
@@ -44,6 +44,7 @@
44
44
  "colorette": "^2.0.20",
45
45
  "ecto": "^4.8.2",
46
46
  "feed": "^5.2.0",
47
+ "hashery": "^1.5.0",
47
48
  "jiti": "^2.6.1",
48
49
  "serve-handler": "^6.1.6",
49
50
  "update-notifier": "^7.3.1",
@@ -78,10 +79,13 @@
78
79
  "test": "pnpm lint && vitest run --coverage",
79
80
  "test:ci": "pnpm lint:ci && vitest run --coverage",
80
81
  "test:e2e": "pnpm build && playwright test",
82
+ "docula:help": "pnpm build && node bin/docula.js help",
81
83
  "generate-init-file": "tsx scripts/generate-init-file.ts",
82
84
  "website:build": "node bin/docula.js build -s ./site -o ./site/dist",
83
- "website:serve": "pnpm build && node bin/docula.js serve -s ./site -o ./site/dist -w -p 3333",
85
+ "website:serve": "pnpm build && node bin/docula.js dev -s ./site -p 3333",
84
86
  "website:mega": "node bin/docula.js serve -s ./test/fixtures/mega-page-site --watch --clean",
87
+ "website:mega:custom": "node bin/docula.js serve -s ./test/fixtures/mega-custom-template --watch",
88
+ "website:singlepage": "node bin/docula.js dev -s ./test/fixtures/single-page-site --clean",
85
89
  "website:nohome": "node bin/docula.js serve -s ./test/fixtures/mega-page-site-no-home-page --watch --clean",
86
90
  "website:changelog": "node bin/docula.js serve -s ./test/fixtures/changelog-site --watch --clean"
87
91
  }
@@ -67,11 +67,32 @@
67
67
  {{/if}}
68
68
  </div>
69
69
  <span class="changelog-entry-date">{{entry.formattedDate}}</span>
70
- <div class="changelog-entry-body">
71
- {{{entry.generatedHtml}}}
70
+ {{#if entry.previewImage}}
71
+ <div class="changelog-entry-image">
72
+ <img src="{{entry.previewImage}}" alt="{{entry.title}}" />
72
73
  </div>
74
+ {{/if}}
75
+ <div class="changelog-entry-preview">
76
+ {{{entry.preview}}}
77
+ </div>
78
+ <span class="changelog-read-more">Read more &rarr;</span>
73
79
  </div>
74
80
  {{/each}}
81
+ {{#if hasPagination}}
82
+ <nav class="changelog-pagination">
83
+ {{#if hasPrevPage}}
84
+ <a class="changelog-pagination-link" href="{{prevPageUrl}}">&larr; Newer</a>
85
+ {{else}}
86
+ <span class="changelog-pagination-link changelog-pagination-disabled">&larr; Newer</span>
87
+ {{/if}}
88
+ <span class="changelog-pagination-info">Page {{currentPage}} of {{totalPages}}</span>
89
+ {{#if hasNextPage}}
90
+ <a class="changelog-pagination-link" href="{{nextPageUrl}}">Older &rarr;</a>
91
+ {{else}}
92
+ <span class="changelog-pagination-link changelog-pagination-disabled">Older &rarr;</span>
93
+ {{/if}}
94
+ </nav>
95
+ {{/if}}
75
96
  {{/if}}
76
97
  </div>
77
98
  </main>
@@ -224,6 +224,7 @@ hr {
224
224
 
225
225
  /* Changelog */
226
226
  .changelog-entry {
227
+ position: relative;
227
228
  overflow: hidden;
228
229
  width: 100%;
229
230
  line-break: anywhere;
@@ -366,6 +367,80 @@ h1.changelog-entry-title {
366
367
  border-bottom: none;
367
368
  }
368
369
 
370
+ .changelog-entry-title::after {
371
+ content: "";
372
+ position: absolute;
373
+ inset: 0;
374
+ z-index: 1;
375
+ }
376
+
377
+ .changelog-entry:hover {
378
+ cursor: pointer;
379
+ }
380
+
381
+ .changelog-entry-image {
382
+ margin-top: 0.75rem;
383
+ }
384
+
385
+ .changelog-entry-image img {
386
+ max-width: 100%;
387
+ height: auto;
388
+ border-radius: 0.5rem;
389
+ }
390
+
391
+ .changelog-entry-preview {
392
+ margin-top: 0.75rem;
393
+ font-size: 0.9375rem;
394
+ line-height: 1.6;
395
+ overflow-wrap: break-word;
396
+ color: var(--color-secondary-dark);
397
+ }
398
+
399
+ .changelog-read-more {
400
+ display: inline-block;
401
+ margin-top: 0.5rem;
402
+ font-size: 0.875rem;
403
+ color: var(--color-primary);
404
+ }
405
+
406
+ .changelog-entry:hover .changelog-read-more {
407
+ text-decoration: underline;
408
+ }
409
+
410
+ .changelog-pagination {
411
+ display: flex;
412
+ justify-content: center;
413
+ align-items: center;
414
+ gap: 1rem;
415
+ padding: 1.5rem 0;
416
+ margin-top: 0.75rem;
417
+ border-top: 1px solid var(--color-border);
418
+ }
419
+
420
+ .changelog-pagination-link {
421
+ font-size: 0.875rem;
422
+ color: var(--color-primary);
423
+ text-decoration: none;
424
+ }
425
+
426
+ .changelog-pagination-link:hover {
427
+ text-decoration: underline;
428
+ }
429
+
430
+ .changelog-pagination-disabled {
431
+ color: var(--color-secondary-dark);
432
+ cursor: default;
433
+ }
434
+
435
+ .changelog-pagination-disabled:hover {
436
+ text-decoration: none;
437
+ }
438
+
439
+ .changelog-pagination-info {
440
+ font-size: 0.875rem;
441
+ color: var(--color-secondary-dark);
442
+ }
443
+
369
444
  .github-corner {
370
445
  fill: var(--color-primary) !important;
371
446
  }
@@ -0,0 +1,30 @@
1
+ :root {
2
+ --font-family: "Open Sans", sans-serif;
3
+
4
+ --color-primary: #322d3c;
5
+ --color-secondary: #8cdc00;
6
+ --color-secondary-dark: #8cdc00;
7
+ --color-text: #322d3c;
8
+
9
+ --background: #ffffff;
10
+ --home-background: #ffffff;
11
+ --header-background: #ffffff;
12
+
13
+ --sidebar-background: #ffffff;
14
+ --sidebar-text: #322d3c;
15
+ --sidebar-text-active: #7d7887;
16
+
17
+ --border: rgba(238, 238, 245, 1);
18
+
19
+ --background-search-highlight: var(--color-secondary-dark);
20
+ --color-search-highlight: #ffffff;
21
+ --search-input-background: var(--header-background);
22
+
23
+ --code: rgba(238, 238, 245, 1);
24
+
25
+ --pagefind-ui-text: var(--color-text) !important;
26
+ --pagefind-ui-font: var(--font-family) !important;
27
+ --pagefind-ui-background: var(--background) !important;
28
+ --pagefind-ui-border: var(--border) !important;
29
+ --pagefind-ui-scale: 0.9 !important;
30
+ }
@@ -56,11 +56,18 @@
56
56
  {{#if content}}
57
57
  {{> singlepage/hero }}
58
58
  {{> singlepage/content }}
59
+ {{#if hasApi}}
60
+ <div class="home-actions">
61
+ {{> multipage/api-reference }}
62
+ </div>
63
+ {{/if}}
59
64
  {{else}}
60
65
  <main class="home">
61
66
  {{> multipage/hero }}
62
67
  <div class="home-actions">
68
+ {{#if hasDocuments}}
63
69
  {{> multipage/documentation }}
70
+ {{/if}}
64
71
  {{#if hasApi}}
65
72
  {{> multipage/api-reference }}
66
73
  {{/if}}
@@ -3,7 +3,7 @@
3
3
 
4
4
  <head>
5
5
  {{> header }}
6
- <link rel="stylesheet" href="/css/api.css">
6
+ <link rel="stylesheet" href="{{baseUrl}}/css/api.css">
7
7
  <title>API Reference - {{ siteTitle }}</title>
8
8
  <meta name="description" content="API Reference for {{ siteTitle }}" />
9
9
  </head>
@@ -70,6 +70,43 @@
70
70
  </select>
71
71
  <input type="password" class="api-auth__value api-auth__value--hidden" id="api-auth-value" placeholder="Enter value..." />
72
72
  <span class="api-auth__cookie-status api-auth__cookie-status--hidden" id="api-auth-cookie-status"></span>
73
+ <script>
74
+ (function() {
75
+ var authTypeSelect = document.getElementById('api-auth-type');
76
+ if (!authTypeSelect) return;
77
+
78
+ // Restore selection from localStorage
79
+ var savedAuthType = localStorage.getItem('docula-api-auth-type');
80
+ if (savedAuthType) {
81
+ for (var i = 0; i < authTypeSelect.options.length; i++) {
82
+ if (authTypeSelect.options[i].value === savedAuthType) {
83
+ authTypeSelect.selectedIndex = i;
84
+ break;
85
+ }
86
+ }
87
+ }
88
+
89
+ // Update UI based on selection
90
+ var selectedOption = authTypeSelect.options[authTypeSelect.selectedIndex];
91
+ var authValueInput = document.getElementById('api-auth-value');
92
+ var cookieStatusBadge = document.getElementById('api-auth-cookie-status');
93
+
94
+ if (selectedOption.value === 'none') return;
95
+
96
+ var isCookieAuth = selectedOption.getAttribute('data-scheme-type') === 'apiKey'
97
+ && selectedOption.getAttribute('data-scheme-in') === 'cookie';
98
+
99
+ if (isCookieAuth) {
100
+ if (cookieStatusBadge) {
101
+ var auth = window.__doculaAuth || { loggedIn: false };
102
+ cookieStatusBadge.textContent = auth.loggedIn ? 'Logged in' : 'Not logged in — use Login button above';
103
+ cookieStatusBadge.className = 'api-auth__cookie-status' + (auth.loggedIn ? ' api-auth__cookie-status--ok' : ' api-auth__cookie-status--warn');
104
+ }
105
+ } else {
106
+ if (authValueInput) authValueInput.classList.remove('api-auth__value--hidden');
107
+ }
108
+ })();
109
+ </script>
73
110
  </div>
74
111
  </div>
75
112
  {{/if}}
@@ -213,7 +250,7 @@
213
250
  {{> footer }}
214
251
  {{> scripts }}
215
252
 
216
- <script src="/js/api.js"></script>
253
+ <script src="{{baseUrl}}/js/api.js"></script>
217
254
  </body>
218
255
 
219
256
  </html>
@@ -12,7 +12,7 @@
12
12
  <main class="versions-container">
13
13
  <div class="versions-content">
14
14
  <div class="changelog-entry-nav">
15
- <a href="/changelog/">&larr; Back to Changelog</a>
15
+ <a href="{{changelogUrl}}/">&larr; Back to Changelog</a>
16
16
  </div>
17
17
  <div class="changelog-entry changelog-entry-single">
18
18
  <div class="changelog-entry-header">
@@ -16,17 +16,38 @@
16
16
  {{#each entries as |entry|}}
17
17
  <div class="changelog-entry">
18
18
  <div class="changelog-entry-header">
19
- <a class="changelog-entry-title" href="/changelog/{{entry.slug}}/">{{entry.title}}</a>
19
+ <a class="changelog-entry-title" href="{{changelogUrl}}/{{entry.slug}}/">{{entry.title}}</a>
20
20
  {{#if entry.tag}}
21
21
  <span class="changelog-tag changelog-tag-{{entry.tagClass}}">{{entry.tag}}</span>
22
22
  {{/if}}
23
23
  </div>
24
24
  <span class="changelog-entry-date">{{entry.formattedDate}}</span>
25
- <div class="changelog-entry-body">
26
- {{{entry.generatedHtml}}}
25
+ {{#if entry.previewImage}}
26
+ <div class="changelog-entry-image">
27
+ <img src="{{entry.previewImage}}" alt="{{entry.title}}" />
27
28
  </div>
29
+ {{/if}}
30
+ <div class="changelog-entry-preview">
31
+ {{{entry.preview}}}
32
+ </div>
33
+ <span class="changelog-read-more">Read more &rarr;</span>
28
34
  </div>
29
35
  {{/each}}
36
+ {{#if hasPagination}}
37
+ <nav class="changelog-pagination">
38
+ {{#if hasPrevPage}}
39
+ <a class="changelog-pagination-link" href="{{prevPageUrl}}">&larr; Newer</a>
40
+ {{else}}
41
+ <span class="changelog-pagination-link changelog-pagination-disabled">&larr; Newer</span>
42
+ {{/if}}
43
+ <span class="changelog-pagination-info">Page {{currentPage}} of {{totalPages}}</span>
44
+ {{#if hasNextPage}}
45
+ <a class="changelog-pagination-link" href="{{nextPageUrl}}">Older &rarr;</a>
46
+ {{else}}
47
+ <span class="changelog-pagination-link changelog-pagination-disabled">Older &rarr;</span>
48
+ {{/if}}
49
+ </nav>
50
+ {{/if}}
30
51
  {{/if}}
31
52
  </div>
32
53
  </main>
@@ -1,36 +1,3 @@
1
- :root {
2
- --bg: #121212;
3
- --fg: #ffffff;
4
- --border: rgba(255, 255, 255, 0.1);
5
- --border-strong: rgba(255, 255, 255, 0.2);
6
- --border-hover: rgba(255, 255, 255, 0.4);
7
- --surface: #262626;
8
- --surface-hover: rgba(255, 255, 255, 0.1);
9
- --muted: #c5cdd3;
10
- --muted-fg: rgba(255, 255, 255, 0.65);
11
- --code-bg: rgba(255, 255, 255, 0.075);
12
- --pre-bg: rgba(255, 255, 255, 0.05);
13
- --link: #6ea8fe;
14
- --scrollbar: rgba(255, 255, 255, 0.2);
15
- --header-height: 81px;
16
- }
17
-
18
- [data-theme="light"] {
19
- --bg: #ffffff;
20
- --fg: #1a1a1a;
21
- --border: rgba(0, 0, 0, 0.1);
22
- --border-strong: rgba(0, 0, 0, 0.15);
23
- --border-hover: rgba(0, 0, 0, 0.3);
24
- --surface: #f0f0f0;
25
- --surface-hover: rgba(0, 0, 0, 0.06);
26
- --muted: #6b7280;
27
- --muted-fg: rgba(0, 0, 0, 0.5);
28
- --code-bg: rgba(0, 0, 0, 0.05);
29
- --pre-bg: rgba(0, 0, 0, 0.03);
30
- --link: #0969da;
31
- --scrollbar: rgba(0, 0, 0, 0.2);
32
- }
33
-
34
1
  html {
35
2
  scroll-behavior: smooth;
36
3
  overflow-x: clip;
@@ -107,7 +74,6 @@ body {
107
74
  }
108
75
 
109
76
  .theme-button {
110
- margin-left: auto;
111
77
  border: 1px solid transparent;
112
78
  border-radius: 4px;
113
79
  padding: 0px 5px;
@@ -120,6 +86,13 @@ body {
120
86
  }
121
87
  }
122
88
 
89
+ .header-actions {
90
+ margin-left: auto;
91
+ display: flex;
92
+ align-items: center;
93
+ gap: 8px;
94
+ }
95
+
123
96
  .theme-button--fixed {
124
97
  position: fixed;
125
98
  bottom: 16px;
@@ -137,6 +110,22 @@ body {
137
110
  display: none;
138
111
  }
139
112
 
113
+ .cookie-auth {
114
+ display: flex;
115
+ align-items: center;
116
+ gap: 8px;
117
+ }
118
+
119
+ #cookie-auth-logout,
120
+ #cookie-auth-logout-mobile,
121
+ .cookie-auth-user { display: none; }
122
+
123
+ .docula-auth-logged-in #cookie-auth-login,
124
+ .docula-auth-logged-in #cookie-auth-login-mobile { display: none; }
125
+ .docula-auth-logged-in #cookie-auth-logout,
126
+ .docula-auth-logged-in #cookie-auth-logout-mobile { display: flex; }
127
+ .docula-auth-logged-in .cookie-auth-user { display: inline; }
128
+
140
129
  .cookie-auth-btn {
141
130
  border: 1px solid var(--border);
142
131
  border-radius: 4px;
@@ -159,7 +148,7 @@ body {
159
148
  }
160
149
 
161
150
  .cookie-auth-user:empty {
162
- display: none;
151
+ display: none !important;
163
152
  }
164
153
 
165
154
  .cookie-auth-user {
@@ -269,7 +258,6 @@ body {
269
258
  min-width: 288px;
270
259
  display: flex;
271
260
  flex-direction: column;
272
- gap: 12px;
273
261
  position: sticky;
274
262
  top: var(--header-height);
275
263
  max-height: calc(100vh - var(--header-height));
@@ -277,6 +265,18 @@ body {
277
265
  align-self: flex-start;
278
266
  }
279
267
 
268
+ .nav-sidebar__section {
269
+ margin-top: 1px;
270
+ }
271
+
272
+ .nav-sidebar__section:has(.nav-sidebar__title) {
273
+ margin-top: 12px;
274
+ }
275
+
276
+ .nav-sidebar__section:first-child {
277
+ margin-top: 0;
278
+ }
279
+
280
280
  .nav-sidebar__title {
281
281
  font-size: 12px;
282
282
  font-weight: 600;
@@ -684,6 +684,7 @@ body {
684
684
  }
685
685
 
686
686
  .changelog-entry {
687
+ position: relative;
687
688
  border-bottom: 1px solid var(--border);
688
689
  padding: 20px 0;
689
690
  }
@@ -744,6 +745,88 @@ body {
744
745
  color: #92400e;
745
746
  }
746
747
 
748
+ .changelog-entry-title::after {
749
+ content: "";
750
+ position: absolute;
751
+ inset: 0;
752
+ z-index: 1;
753
+ }
754
+
755
+ .changelog-entry:hover {
756
+ cursor: pointer;
757
+ }
758
+
759
+ .changelog-entry-single .changelog-entry-title::after {
760
+ display: none;
761
+ }
762
+
763
+ .changelog-entry-single:hover {
764
+ cursor: default;
765
+ }
766
+
767
+ .changelog-entry-image {
768
+ margin-top: 12px;
769
+ }
770
+
771
+ .changelog-entry-image img {
772
+ max-width: 100%;
773
+ height: auto;
774
+ border-radius: 8px;
775
+ }
776
+
777
+ .changelog-entry-preview {
778
+ margin-top: 12px;
779
+ font-size: 15px;
780
+ line-height: 1.6;
781
+ overflow-wrap: break-word;
782
+ color: var(--muted);
783
+ }
784
+
785
+ .changelog-read-more {
786
+ display: inline-block;
787
+ margin-top: 8px;
788
+ font-size: 14px;
789
+ color: var(--muted);
790
+ }
791
+
792
+ .changelog-entry:hover .changelog-read-more {
793
+ color: var(--fg);
794
+ }
795
+
796
+ .changelog-pagination {
797
+ display: flex;
798
+ justify-content: center;
799
+ align-items: center;
800
+ gap: 16px;
801
+ padding: 24px 0;
802
+ margin-top: 12px;
803
+ border-top: 1px solid var(--border);
804
+ }
805
+
806
+ .changelog-pagination-link {
807
+ font-size: 14px;
808
+ color: var(--muted);
809
+ text-decoration: none;
810
+ }
811
+
812
+ .changelog-pagination-link:hover {
813
+ color: var(--fg);
814
+ }
815
+
816
+ .changelog-pagination-disabled {
817
+ color: var(--muted);
818
+ cursor: default;
819
+ }
820
+
821
+ .changelog-pagination-disabled:hover {
822
+ text-decoration: none;
823
+ }
824
+
825
+ .changelog-pagination-info {
826
+ font-size: 14px;
827
+ color: var(--muted);
828
+ }
829
+
747
830
  /* Footer */
748
831
  footer {
749
832
  height: 4rem;
@@ -777,6 +860,11 @@ footer {
777
860
  height: 1.25rem;
778
861
  }
779
862
 
863
+ .footer__updated {
864
+ font-size: 13px;
865
+ color: var(--muted);
866
+ }
867
+
780
868
  @media (min-width: 992px) {
781
869
  footer { height: 4.75rem; }
782
870
  }
@@ -0,0 +1,32 @@
1
+ :root {
2
+ --bg: #121212;
3
+ --fg: #ffffff;
4
+ --border: rgba(255, 255, 255, 0.1);
5
+ --border-strong: rgba(255, 255, 255, 0.2);
6
+ --border-hover: rgba(255, 255, 255, 0.4);
7
+ --surface: #262626;
8
+ --surface-hover: rgba(255, 255, 255, 0.1);
9
+ --muted: #c5cdd3;
10
+ --muted-fg: rgba(255, 255, 255, 0.65);
11
+ --code-bg: rgba(255, 255, 255, 0.075);
12
+ --pre-bg: rgba(255, 255, 255, 0.05);
13
+ --link: #6ea8fe;
14
+ --scrollbar: rgba(255, 255, 255, 0.2);
15
+ --header-height: 81px;
16
+ }
17
+
18
+ [data-theme="light"] {
19
+ --bg: #ffffff;
20
+ --fg: #1a1a1a;
21
+ --border: rgba(0, 0, 0, 0.1);
22
+ --border-strong: rgba(0, 0, 0, 0.15);
23
+ --border-hover: rgba(0, 0, 0, 0.3);
24
+ --surface: #f0f0f0;
25
+ --surface-hover: rgba(0, 0, 0, 0.06);
26
+ --muted: #6b7280;
27
+ --muted-fg: rgba(0, 0, 0, 0.5);
28
+ --code-bg: rgba(0, 0, 0, 0.05);
29
+ --pre-bg: rgba(0, 0, 0, 0.03);
30
+ --link: #0969da;
31
+ --scrollbar: rgba(0, 0, 0, 0.2);
32
+ }
@@ -3,7 +3,7 @@
3
3
 
4
4
  <head>
5
5
  {{> header }}
6
- <link rel="stylesheet" href="/css/home.css">
6
+ <link rel="stylesheet" href="{{baseUrl}}/css/home.css">
7
7
  <title>{{ siteTitle }}</title>
8
8
  </head>
9
9
 
@@ -24,18 +24,25 @@
24
24
 
25
25
  {{#if content}}
26
26
  <header class="home-hero">
27
- <img src="/logo.svg" alt="logo" />
27
+ <img src="{{baseUrl}}/logo.svg" alt="logo" />
28
28
  {{#if announcement}}
29
29
  <div class="announcement">{{{announcement}}}</div>
30
30
  {{/if}}
31
31
  </header>
32
32
  <div class="home-content">{{{content}}}</div>
33
+ {{#if hasApi}}
34
+ <div class="home-actions">
35
+ {{> api-reference }}
36
+ </div>
37
+ {{/if}}
33
38
  {{> home }}
34
39
  {{else}}
35
40
  <main class="home">
36
41
  {{> hero }}
37
42
  <div class="home-actions">
43
+ {{#if hasDocuments}}
38
44
  {{> documentation }}
45
+ {{/if}}
39
46
  {{#if hasApi}}
40
47
  {{> api-reference }}
41
48
  {{/if}}
@@ -49,7 +56,7 @@
49
56
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"/><polyline points="10 17 15 12 10 7"/><line x1="15" x2="3" y1="12" y2="12"/></svg>
50
57
  <span>Log In</span>
51
58
  </a>
52
- <button class="cookie-auth-btn cookie-auth-btn--fixed" id="cookie-auth-logout" style="display:none">
59
+ <button class="cookie-auth-btn cookie-auth-btn--fixed" id="cookie-auth-logout">
53
60
  <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" x2="9" y1="12" y2="12"/></svg>
54
61
  <span>Log Out</span>
55
62
  </button>
@@ -1 +1 @@
1
- <a href="/api" class="home-docs-button">API Reference</a>
1
+ <a href="{{apiUrl}}" class="home-docs-button">API Reference</a>
@@ -1 +1 @@
1
- <a href="/docs" class="home-docs-button">Documentation</a>
1
+ <a href="{{docsUrl}}" class="home-docs-button">Documentation</a>
@@ -1,9 +1,9 @@
1
1
  <footer>
2
2
  {{#if enableLlmsTxt}}
3
- <a href="/llms.txt" class="footer__link">llms.txt</a>
3
+ <a href="{{baseUrl}}/llms.txt" class="footer__link">llms.txt</a>
4
4
  {{/if}}
5
5
  {{#if hasFeed}}
6
- <a href="/feed.xml" class="footer__link" aria-label="RSS Feed">
6
+ <a href="{{baseUrl}}/feed.xml" class="footer__link" aria-label="RSS Feed">
7
7
  <svg class="footer__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><circle cx="6.18" cy="17.82" r="2.18"/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z"/></svg>
8
8
  </a>
9
9
  {{/if}}
@@ -11,4 +11,7 @@
11
11
  <a href="https://docula.org/" target="_blank" rel="noopener noreferrer" class="footer__link" aria-label="Docula">
12
12
  <svg class="footer__bat" xmlns="http://www.w3.org/2000/svg" viewBox="70 110 360 205" fill="currentColor"><path d="M420,173c-16.76-18-72.78-36.65-131.59-30.58A160.15,160.15,0,0,0,269,120.55c-3.78,4.52-11.15,9.45-19,9.45s-15.23-4.93-19-9.45a160.15,160.15,0,0,0-19.4,21.83C152.78,136.31,96.76,154.94,80,173c48.86,5.86,79.5,34.09,79.5,72.06,52.37,0,77,28,90.5,59.94C263.54,273,288.13,245,340.5,245,340.5,207,371.14,178.8,420,173Z"/><circle cx="239.19" cy="145.36" r="3.32" fill="#fff"/><circle cx="260.81" cy="145.36" r="3.32" fill="#fff"/></svg>
13
13
  </a>
14
+ {{#if lastModified}}
15
+ <span class="footer__updated">updated: {{lastModified}}</span>
16
+ {{/if}}
14
17
  </footer>