@abreen/tada 1.7.1 → 1.8.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/README.md +1 -0
- package/bin/tada.ts +2 -2
- package/build/site-variables.ts +1 -1
- package/build/types.d.ts +1 -0
- package/build/utils/render.ts +5 -1
- package/package.json +1 -1
- package/schema/site.schema.json +8 -2
- package/src/_base.scss +1 -0
- package/src/_layout.scss +32 -0
- package/src/literate/style.scss +0 -1
- package/src/search/index.ts +16 -7
- package/src/search/pdf-utils.ts +4 -0
- package/src/search/style.scss +3 -7
- package/templates/_bottom.html +5 -0
- package/templates/_heading.html +1 -1
- package/templates/_theme.scss +1 -0
- package/templates/_top.html +1 -1
- package/templates/code.html +1 -1
package/README.md
CHANGED
|
@@ -232,6 +232,7 @@ Example site configuration JSON file:
|
|
|
232
232
|
| `features.search` | Enable search UI and Pagefind index generation |
|
|
233
233
|
| `features.code` | Enable generated source-code HTML pages for configured code extensions |
|
|
234
234
|
| `features.favicon` | Enable automatically generated favicons |
|
|
235
|
+
| `features.footer` | Show the Tada footer at the bottom of every page |
|
|
235
236
|
| `base` | Full base URL of the deployed site, used for metadata and URL generation |
|
|
236
237
|
| `basePath` | URL prefix for deployment under a subpath (e.g., `"/cs101"`), use `"/"` at root |
|
|
237
238
|
| `internalDomains` | Domain names treated as internal by link processing (not marked external) |
|
package/bin/tada.ts
CHANGED
|
@@ -332,7 +332,7 @@ async function initCommand(args: string[]): Promise<void> {
|
|
|
332
332
|
base: 'http://localhost:8080',
|
|
333
333
|
basePath: '/',
|
|
334
334
|
internalDomains: ['localhost'],
|
|
335
|
-
features: { search: true, code: true, favicon: false },
|
|
335
|
+
features: { search: true, code: true, favicon: false, footer: true },
|
|
336
336
|
});
|
|
337
337
|
|
|
338
338
|
const prodConfig = createSiteConfig({
|
|
@@ -345,7 +345,7 @@ async function initCommand(args: string[]): Promise<void> {
|
|
|
345
345
|
base: prodBase,
|
|
346
346
|
basePath: prodBasePath,
|
|
347
347
|
internalDomains: [prodDomain],
|
|
348
|
-
features: { search: true, code: true, favicon: true },
|
|
348
|
+
features: { search: true, code: true, favicon: true, footer: true },
|
|
349
349
|
});
|
|
350
350
|
|
|
351
351
|
fs.writeFileSync(
|
package/build/site-variables.ts
CHANGED
|
@@ -10,7 +10,7 @@ const configDir = getProjectDir();
|
|
|
10
10
|
|
|
11
11
|
const DEFAULT: Partial<SiteVariables> = {
|
|
12
12
|
basePath: '/',
|
|
13
|
-
features: { search: true, code: true, favicon: true },
|
|
13
|
+
features: { search: true, code: true, favicon: true, footer: true },
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
const isValid = compileJsonSchema(siteSchema);
|
package/build/types.d.ts
CHANGED
package/build/utils/render.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
toPosix,
|
|
25
25
|
toUrlPath,
|
|
26
26
|
} from './paths';
|
|
27
|
+
import pkg from '../../package.json' with { type: 'json' };
|
|
27
28
|
import { parseFrontMatterAndContent } from './front-matter';
|
|
28
29
|
import { createMarkdown } from './markdown';
|
|
29
30
|
import { generateTocHtml, generateCodeTocHtml } from '../toc-plugin';
|
|
@@ -45,6 +46,8 @@ import type {
|
|
|
45
46
|
|
|
46
47
|
const log = makeLogger(import.meta.url);
|
|
47
48
|
|
|
49
|
+
const tadaVersion: string = pkg.version;
|
|
50
|
+
|
|
48
51
|
const REQUIRED_FRONT_MATTER_FIELDS = ['title'];
|
|
49
52
|
|
|
50
53
|
function isWatchMode(assetFiles: string[]): boolean {
|
|
@@ -133,6 +136,7 @@ function createTemplateParameters({
|
|
|
133
136
|
content,
|
|
134
137
|
applyBasePath,
|
|
135
138
|
isWatchMode,
|
|
139
|
+
tadaVersion,
|
|
136
140
|
};
|
|
137
141
|
}
|
|
138
142
|
|
|
@@ -291,7 +295,7 @@ export function renderCodePageAsset({
|
|
|
291
295
|
const codeFilePath = applyBasePath(
|
|
292
296
|
normalizeOutputPath(`/${toUrlPath(path.relative(contentDir, filePath))}`),
|
|
293
297
|
);
|
|
294
|
-
const titleHtml = `<
|
|
298
|
+
const titleHtml = `<code>${name + ext}</code>`;
|
|
295
299
|
const tocItems = lang === 'java' ? extractJavaMethodToc(sourceCode) : [];
|
|
296
300
|
const tocHtml = generateCodeTocHtml(tocItems);
|
|
297
301
|
const pageVariables: Record<string, unknown> = {
|
package/package.json
CHANGED
package/schema/site.schema.json
CHANGED
|
@@ -4,11 +4,17 @@
|
|
|
4
4
|
"properties": {
|
|
5
5
|
"features": {
|
|
6
6
|
"type": "object",
|
|
7
|
-
"default": {
|
|
7
|
+
"default": {
|
|
8
|
+
"search": true,
|
|
9
|
+
"code": true,
|
|
10
|
+
"favicon": true,
|
|
11
|
+
"footer": true
|
|
12
|
+
},
|
|
8
13
|
"properties": {
|
|
9
14
|
"search": { "type": "boolean", "default": true },
|
|
10
15
|
"code": { "type": "boolean", "default": true },
|
|
11
|
-
"favicon": { "type": "boolean", "default": true }
|
|
16
|
+
"favicon": { "type": "boolean", "default": true },
|
|
17
|
+
"footer": { "type": "boolean", "default": true }
|
|
12
18
|
},
|
|
13
19
|
"additionalProperties": false
|
|
14
20
|
},
|
package/src/_base.scss
CHANGED
package/src/_layout.scss
CHANGED
|
@@ -198,3 +198,35 @@ body.literate main table {
|
|
|
198
198
|
grid-template-columns: 1fr 1fr;
|
|
199
199
|
gap: var(--gap);
|
|
200
200
|
}
|
|
201
|
+
|
|
202
|
+
footer {
|
|
203
|
+
@include user-select(none);
|
|
204
|
+
text-align: center;
|
|
205
|
+
padding: 2rem 0 1rem;
|
|
206
|
+
color: var(--fg2-color);
|
|
207
|
+
|
|
208
|
+
a {
|
|
209
|
+
color: var(--fg2-color);
|
|
210
|
+
text-decoration: none;
|
|
211
|
+
|
|
212
|
+
@media (hover: hover) {
|
|
213
|
+
&:hover {
|
|
214
|
+
color: var(--link-color-hover);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
&:active {
|
|
219
|
+
color: var(--link-active-color);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
&::after {
|
|
223
|
+
content: '';
|
|
224
|
+
display: inline-block;
|
|
225
|
+
width: 1.3em;
|
|
226
|
+
height: 1.3em;
|
|
227
|
+
vertical-align: middle;
|
|
228
|
+
margin-left: 0.2em;
|
|
229
|
+
@include contained-mask(var(--icon-tada));
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
package/src/literate/style.scss
CHANGED
package/src/search/index.ts
CHANGED
|
@@ -11,7 +11,12 @@ interface PagefindSubResult {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
interface PagefindResult {
|
|
14
|
-
meta?: {
|
|
14
|
+
meta?: {
|
|
15
|
+
title?: string;
|
|
16
|
+
title_html?: string;
|
|
17
|
+
page?: string;
|
|
18
|
+
template?: string;
|
|
19
|
+
};
|
|
15
20
|
url: string;
|
|
16
21
|
excerpt?: string;
|
|
17
22
|
score: number;
|
|
@@ -74,11 +79,13 @@ async function doSearch(state: State) {
|
|
|
74
79
|
}));
|
|
75
80
|
return {
|
|
76
81
|
title,
|
|
82
|
+
titleHtml: d.meta?.title_html ?? null,
|
|
77
83
|
url: d.url,
|
|
78
84
|
excerpt: d.excerpt ?? '',
|
|
79
85
|
score: d.score ?? 0,
|
|
80
86
|
subResults,
|
|
81
87
|
pageNumber: getPdfPageNumber(d.url, d.meta?.page),
|
|
88
|
+
template: d.meta?.template ?? null,
|
|
82
89
|
};
|
|
83
90
|
});
|
|
84
91
|
|
|
@@ -139,14 +146,16 @@ function render(
|
|
|
139
146
|
const titleEl = doc.createElement('div');
|
|
140
147
|
titleEl.id = `title-${i}`;
|
|
141
148
|
titleEl.className = 'title';
|
|
142
|
-
|
|
149
|
+
if (result.template === 'code') {
|
|
150
|
+
titleEl.classList.add('code-page');
|
|
151
|
+
}
|
|
152
|
+
if (result.titleHtml) {
|
|
153
|
+
titleEl.innerHTML = result.titleHtml;
|
|
154
|
+
} else {
|
|
155
|
+
titleEl.textContent = result.title;
|
|
156
|
+
}
|
|
143
157
|
a.appendChild(titleEl);
|
|
144
158
|
|
|
145
|
-
const subtitle = doc.createElement('div');
|
|
146
|
-
subtitle.className = 'subtitle';
|
|
147
|
-
subtitle.innerText = result.url;
|
|
148
|
-
a.appendChild(subtitle);
|
|
149
|
-
|
|
150
159
|
const excerpt = doc.createElement('div');
|
|
151
160
|
excerpt.className = 'excerpt';
|
|
152
161
|
excerpt.innerHTML = result.excerpt;
|
package/src/search/pdf-utils.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
export type SubResult = { title: string; url: string; excerpt: string };
|
|
2
2
|
export type Result = {
|
|
3
3
|
title: string;
|
|
4
|
+
titleHtml: string | null;
|
|
4
5
|
url: string;
|
|
5
6
|
excerpt: string;
|
|
6
7
|
score: number;
|
|
7
8
|
subResults: SubResult[];
|
|
8
9
|
pageNumber: number | null;
|
|
10
|
+
template: string | null;
|
|
9
11
|
};
|
|
10
12
|
|
|
11
13
|
export function getPdfPageNumber(
|
|
@@ -66,11 +68,13 @@ export function groupPdfResults(results: Result[]): Result[] {
|
|
|
66
68
|
|
|
67
69
|
grouped.push({
|
|
68
70
|
title: primary.title,
|
|
71
|
+
titleHtml: null,
|
|
69
72
|
url: baseUrl,
|
|
70
73
|
excerpt: primary.excerpt,
|
|
71
74
|
score: primary.score,
|
|
72
75
|
subResults,
|
|
73
76
|
pageNumber: null,
|
|
77
|
+
template: null,
|
|
74
78
|
});
|
|
75
79
|
});
|
|
76
80
|
|
package/src/search/style.scss
CHANGED
|
@@ -129,13 +129,9 @@ header {
|
|
|
129
129
|
font-weight: 500;
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
-
ol
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
color: var(--fg2-color);
|
|
136
|
-
white-space: nowrap;
|
|
137
|
-
overflow: hidden;
|
|
138
|
-
text-overflow: ellipsis;
|
|
132
|
+
ol a .title.code-page code {
|
|
133
|
+
background: none;
|
|
134
|
+
padding: 0;
|
|
139
135
|
}
|
|
140
136
|
|
|
141
137
|
ol li .excerpt {
|
package/templates/_bottom.html
CHANGED
package/templates/_heading.html
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<% if (page.parent) { %>
|
|
3
3
|
<a class="breadcrumb" href="<%= applyBasePath(page.parent) %>" data-pagefind-ignore><%= page.parentLabel %></a>
|
|
4
4
|
<% } %>
|
|
5
|
-
<h1 data-pagefind-weight="10"><%= page.titleHtml %></h1>
|
|
5
|
+
<h1 data-pagefind-weight="10" data-pagefind-meta="title_html[data-title-html]" data-title-html="<%- page.titleHtml %>"><%= page.titleHtml %></h1>
|
|
6
6
|
|
|
7
7
|
<div class="info" data-pagefind-ignore>
|
|
8
8
|
<% if (page.published) { %>
|
package/templates/_theme.scss
CHANGED
|
@@ -67,6 +67,7 @@
|
|
|
67
67
|
--icon-search: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><circle cx='11' cy='11' r='7' stroke='<%= iconColor %>' stroke-width='2' fill='none'/><line x1='16.5' y1='16.5' x2='22' y2='22' stroke='<%= iconColor %>' stroke-width='2' stroke-linecap='round'/></svg>");
|
|
68
68
|
--icon-chevron: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><polyline points='9 18 15 12 9 6' stroke='<%= iconColor %>' stroke-width='2' fill='none' stroke-linecap='round' stroke-linejoin='round'/></svg>");
|
|
69
69
|
--icon-breadcrumb: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24'><path d='M3 7 H17 V22' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/><polyline points='11 16 17 22 23 16' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>");
|
|
70
|
+
--icon-tada: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='39' height='39' viewBox='0 0 24 24'><path fill='black' d='m14.53 1.45l-1.08 1.08l1.6 1.6q.33.375.33.87c0 .495-.11.64-.33.86L11.5 9.47l1 1.08l3.63-3.61c.53-.59.79-1.24.79-1.94s-.26-1.36-.79-1.95zm-3.98 2.02L9.47 4.55l.61.56c.22.22.33.52.33.89s-.11.67-.33.89l-.61.56l1.08 1.08l.56-.61c.53-.59.8-1.23.8-1.92c0-.72-.27-1.37-.8-1.97zM21 5.06c-.69 0-1.33.27-1.92.8l-5.63 5.64l1.08 1l5.58-5.56c.25-.25.55-.38.89-.38s.64.13.89.38l.61.61l1.03-1.08l-.56-.61c-.59-.53-1.25-.8-1.97-.8M7 8L2 22l14-5zm12 3.06c-.7 0-1.34.27-1.94.8l-1.59 1.59l1.08 1.08l1.59-1.59c.25-.25.53-.38.86-.38s.63.13.88.38l1.62 1.59l1.05-1.03l-1.6-1.64c-.59-.53-1.25-.8-1.95-.8'/></svg>");
|
|
70
71
|
|
|
71
72
|
color-scheme: light dark;
|
|
72
73
|
}
|
package/templates/_top.html
CHANGED
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
</style></noscript>
|
|
55
55
|
</head>
|
|
56
56
|
|
|
57
|
-
<body class="<%= page.template %><% if (page.tocHtml) { %> toc-is-active<% } %>">
|
|
57
|
+
<body class="<%= page.template %><% if (page.tocHtml) { %> toc-is-active<% } %>" data-pagefind-meta="template:<%= page.template %>">
|
|
58
58
|
<header data-pagefind-ignore>
|
|
59
59
|
<div class="header-controls">
|
|
60
60
|
<div id="to-top-container" class="to-top-container"></div>
|
package/templates/code.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<div class="main-content">
|
|
4
4
|
<main class="body" data-pagefind-body>
|
|
5
5
|
<div class="file-header">
|
|
6
|
-
<h1 data-pagefind-weight="10"><%= page.titleHtml %></h1>
|
|
6
|
+
<h1 data-pagefind-weight="10" data-pagefind-meta="title_html[data-title-html]" data-title-html="<%- page.titleHtml %>"><%= page.titleHtml %></h1>
|
|
7
7
|
<%= render('_download.html') %>
|
|
8
8
|
</div>
|
|
9
9
|
<div class="code-body">
|