docula 1.9.0 → 1.10.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/dist/docula.d.ts +7 -0
- package/dist/docula.js +16 -2
- package/package.json +4 -4
- package/templates/classic/changelog-entry.hbs +1 -1
- package/templates/classic/changelog.hbs +1 -1
- package/templates/classic/includes/multipage/home.hbs +1 -1
- package/templates/classic/includes/singlepage/content.hbs +1 -1
- package/templates/modern/changelog.hbs +1 -1
- package/templates/modern/css/styles.css +12 -1
- package/templates/modern/includes/header-bar.hbs +16 -3
- package/templates/modern/includes/home.hbs +1 -1
- package/templates/modern/includes/scripts.hbs +43 -0
package/dist/docula.d.ts
CHANGED
|
@@ -139,6 +139,7 @@ type DoculaChangelogEntry = {
|
|
|
139
139
|
content: string;
|
|
140
140
|
generatedHtml: string;
|
|
141
141
|
preview: string;
|
|
142
|
+
draft?: boolean;
|
|
142
143
|
previewImage?: string;
|
|
143
144
|
urlPath: string;
|
|
144
145
|
lastModified: string;
|
|
@@ -180,6 +181,7 @@ type DoculaData = {
|
|
|
180
181
|
enableLlmsTxt?: boolean;
|
|
181
182
|
hasFeed?: boolean;
|
|
182
183
|
lastModified?: string;
|
|
184
|
+
homeUrl?: string;
|
|
183
185
|
baseUrl: string;
|
|
184
186
|
docsPath: string;
|
|
185
187
|
apiPath: string;
|
|
@@ -334,6 +336,11 @@ declare class DoculaOptions {
|
|
|
334
336
|
* When true, suppresses all non-error console output during the build.
|
|
335
337
|
*/
|
|
336
338
|
quiet: boolean;
|
|
339
|
+
/**
|
|
340
|
+
* URL for the logo/home link in the header. Defaults to baseUrl or "/".
|
|
341
|
+
* Useful when hosting docs under a subpath but the logo should link to the parent site.
|
|
342
|
+
*/
|
|
343
|
+
homeUrl?: string;
|
|
337
344
|
/**
|
|
338
345
|
* Base URL path prefix for all generated paths (e.g., "/docs").
|
|
339
346
|
* When set, all asset and navigation URLs are prefixed with this path.
|
package/dist/docula.js
CHANGED
|
@@ -1330,6 +1330,9 @@ function getChangelogEntries(changelogPath, options, hash, cachedEntries, previo
|
|
|
1330
1330
|
}
|
|
1331
1331
|
}
|
|
1332
1332
|
const entry = parseChangelogEntry(filePath, options);
|
|
1333
|
+
if (entry.draft) {
|
|
1334
|
+
continue;
|
|
1335
|
+
}
|
|
1333
1336
|
entries.push(entry);
|
|
1334
1337
|
}
|
|
1335
1338
|
}
|
|
@@ -1375,6 +1378,7 @@ function parseChangelogEntry(filePath, options) {
|
|
|
1375
1378
|
});
|
|
1376
1379
|
}
|
|
1377
1380
|
const previewImage = matterData.previewImage;
|
|
1381
|
+
const draft = matterData.draft === true;
|
|
1378
1382
|
return {
|
|
1379
1383
|
title: matterData.title ?? fileName,
|
|
1380
1384
|
date: dateString,
|
|
@@ -1387,8 +1391,9 @@ function parseChangelogEntry(filePath, options) {
|
|
|
1387
1391
|
mdx: isMdx
|
|
1388
1392
|
}),
|
|
1389
1393
|
preview: generateChangelogPreview(markdownContent, 500, isMdx),
|
|
1394
|
+
draft,
|
|
1390
1395
|
previewImage,
|
|
1391
|
-
urlPath:
|
|
1396
|
+
urlPath: `${buildUrlPath(options.baseUrl, options.changelogPath, slug)}/index.html`,
|
|
1392
1397
|
lastModified: fs5.statSync(filePath).mtime.toISOString().split("T")[0]
|
|
1393
1398
|
};
|
|
1394
1399
|
}
|
|
@@ -1485,7 +1490,7 @@ function convertReleaseToChangelogEntry(release, options) {
|
|
|
1485
1490
|
content: body,
|
|
1486
1491
|
generatedHtml: new Writr4(body, writrOptions4).renderSync(),
|
|
1487
1492
|
preview: generateChangelogPreview(body),
|
|
1488
|
-
urlPath:
|
|
1493
|
+
urlPath: `${buildUrlPath(options.baseUrl, options.changelogPath, slug)}/index.html`,
|
|
1489
1494
|
lastModified: dateString
|
|
1490
1495
|
};
|
|
1491
1496
|
}
|
|
@@ -2918,6 +2923,11 @@ var DoculaOptions = class {
|
|
|
2918
2923
|
* When true, suppresses all non-error console output during the build.
|
|
2919
2924
|
*/
|
|
2920
2925
|
quiet = false;
|
|
2926
|
+
/**
|
|
2927
|
+
* URL for the logo/home link in the header. Defaults to baseUrl or "/".
|
|
2928
|
+
* Useful when hosting docs under a subpath but the logo should link to the parent site.
|
|
2929
|
+
*/
|
|
2930
|
+
homeUrl;
|
|
2921
2931
|
/**
|
|
2922
2932
|
* Base URL path prefix for all generated paths (e.g., "/docs").
|
|
2923
2933
|
* When set, all asset and navigation URLs are prefixed with this path.
|
|
@@ -3074,6 +3084,9 @@ var DoculaOptions = class {
|
|
|
3074
3084
|
if (options.cache && typeof options.cache === "object" && options.cache.github !== null && typeof options.cache.github === "object" && typeof options.cache.github.ttl === "number") {
|
|
3075
3085
|
this.cache = options.cache;
|
|
3076
3086
|
}
|
|
3087
|
+
if (options.homeUrl !== void 0 && typeof options.homeUrl === "string") {
|
|
3088
|
+
this.homeUrl = options.homeUrl === "/" ? "/" : trimTrailingSlashes(options.homeUrl);
|
|
3089
|
+
}
|
|
3077
3090
|
if (options.baseUrl !== void 0 && typeof options.baseUrl === "string") {
|
|
3078
3091
|
this.baseUrl = trimTrailingSlashes(options.baseUrl);
|
|
3079
3092
|
}
|
|
@@ -3229,6 +3242,7 @@ var DoculaBuilder = class {
|
|
|
3229
3242
|
cookieAuth: this.options.cookieAuth,
|
|
3230
3243
|
headerLinks: this.options.headerLinks,
|
|
3231
3244
|
enableLlmsTxt: this.options.enableLlmsTxt,
|
|
3245
|
+
homeUrl: this.options.homeUrl,
|
|
3232
3246
|
baseUrl: this.options.baseUrl,
|
|
3233
3247
|
docsPath: this.options.docsPath,
|
|
3234
3248
|
apiPath: this.options.apiPath,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docula",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Beautiful Website for Your Projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/docula.js",
|
|
@@ -48,14 +48,14 @@
|
|
|
48
48
|
"colorette": "^2.0.20",
|
|
49
49
|
"ecto": "^4.8.3",
|
|
50
50
|
"feed": "^5.2.0",
|
|
51
|
-
"hashery": "^1.5.
|
|
51
|
+
"hashery": "^1.5.1",
|
|
52
52
|
"jiti": "^2.6.1",
|
|
53
53
|
"serve-handler": "^6.1.7",
|
|
54
54
|
"update-notifier": "^7.3.1",
|
|
55
|
-
"writr": "^6.0
|
|
55
|
+
"writr": "^6.1.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
|
-
"@biomejs/biome": "^2.4.
|
|
58
|
+
"@biomejs/biome": "^2.4.8",
|
|
59
59
|
"@playwright/test": "^1.58.2",
|
|
60
60
|
"@types/express": "^5.0.6",
|
|
61
61
|
"@types/js-yaml": "^4.0.9",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
<main class="versions-container">
|
|
59
59
|
<div class="versions-content">
|
|
60
60
|
<div class="changelog-entry-nav">
|
|
61
|
-
<a href="/
|
|
61
|
+
<a href="{{changelogUrl}}/">← Back to Changelog</a>
|
|
62
62
|
</div>
|
|
63
63
|
<div class="changelog-entry changelog-entry-single">
|
|
64
64
|
<div class="changelog-entry-header">
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
{{#each entries as |entry|}}
|
|
63
63
|
<div class="changelog-entry">
|
|
64
64
|
<div class="changelog-entry-header">
|
|
65
|
-
<a class="changelog-entry-title" href="/
|
|
65
|
+
<a class="changelog-entry-title" href="{{@root.changelogUrl}}/{{entry.slug}}/">{{entry.title}}</a>
|
|
66
66
|
{{#if entry.tag}}
|
|
67
67
|
<span class="changelog-tag changelog-tag-{{entry.tagClass}}">{{entry.tag}}</span>
|
|
68
68
|
{{/if}}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{{#each entries as |entry|}}
|
|
18
18
|
<div class="changelog-entry">
|
|
19
19
|
<div class="changelog-entry-header">
|
|
20
|
-
<a class="changelog-entry-title" href="{{changelogUrl}}/{{entry.slug}}/">{{entry.title}}</a>
|
|
20
|
+
<a class="changelog-entry-title" href="{{@root.changelogUrl}}/{{entry.slug}}/">{{entry.title}}</a>
|
|
21
21
|
{{#if entry.tag}}
|
|
22
22
|
<span class="changelog-tag changelog-tag-{{entry.tagClass}}">{{entry.tag}}</span>
|
|
23
23
|
{{/if}}
|
|
@@ -68,10 +68,12 @@ body {
|
|
|
68
68
|
gap: 12px;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
.logo-link { display: flex; align-items: center; gap: 8px; text-decoration: none; color: var(--fg); }
|
|
71
72
|
.logo__img {
|
|
72
73
|
height: 75px;
|
|
73
74
|
width: auto;
|
|
74
75
|
}
|
|
76
|
+
.logo__text { font-size: 18px; font-weight: 600; }
|
|
75
77
|
|
|
76
78
|
.theme-button {
|
|
77
79
|
border: 1px solid transparent;
|
|
@@ -354,8 +356,17 @@ body {
|
|
|
354
356
|
.article__main li, .release-body li, .changelog-entry-body li, .home-content li { margin-bottom: 6px; list-style: disc; }
|
|
355
357
|
.article__main ol li, .release-body ol li, .changelog-entry-body ol li, .home-content ol li { list-style: decimal; }
|
|
356
358
|
.article__main a, .release-body a, .changelog-entry-body a, .home-content a { color: var(--link); text-decoration: underline; }
|
|
357
|
-
.article__main pre, .release-body pre, .changelog-entry-body pre, .home-content pre { background: var(--pre-bg); border-radius: 6px; padding: 12px 16px; margin-bottom: 20px; overflow-x: auto; }
|
|
359
|
+
.article__main pre, .release-body pre, .changelog-entry-body pre, .home-content pre { background: var(--pre-bg); border-radius: 6px; padding: 12px 16px; margin-bottom: 20px; overflow-x: auto; position: relative; }
|
|
358
360
|
.article__main pre code, .release-body pre code, .changelog-entry-body pre code, .home-content pre code { background: none; padding: 0; font-size: 13.5px; line-height: 1.5; }
|
|
361
|
+
.copy-code-btn { position: absolute; top: 8px; right: 8px; padding: 4px; line-height: 0; border-radius: 4px; background: transparent; color: var(--muted); border: none; cursor: pointer; opacity: 0; transition: opacity 0.15s; }
|
|
362
|
+
pre:hover .copy-code-btn { opacity: 1; }
|
|
363
|
+
.copy-code-btn:hover { color: var(--fg); }
|
|
364
|
+
.article__main img, .changelog-entry-body img { cursor: zoom-in; }
|
|
365
|
+
.lightbox-overlay { display: none; position: fixed; inset: 0; z-index: 200; background: rgba(0, 0, 0, 0.8); justify-content: center; align-items: center; cursor: pointer; }
|
|
366
|
+
.lightbox-overlay--visible { display: flex !important; }
|
|
367
|
+
.lightbox-overlay img { max-width: 90vw; max-height: 90vh; border-radius: 8px; box-shadow: 0 4px 24px rgba(0, 0, 0, 0.4); cursor: default; }
|
|
368
|
+
.lightbox-close { position: absolute; top: 16px; right: 16px; background: none; border: none; color: #fff; cursor: pointer; padding: 4px; line-height: 0; }
|
|
369
|
+
.lightbox-close:hover { opacity: 0.7; }
|
|
359
370
|
.article__main blockquote, .release-body blockquote, .changelog-entry-body blockquote, .home-content blockquote { border-left: 3px solid var(--border-strong); padding: 10px 16px; margin-bottom: 15px; color: var(--muted); }
|
|
360
371
|
.article__main img, .release-body img, .changelog-entry-body img, .home-content img { max-width: 100%; border-radius: 6px; }
|
|
361
372
|
.article__main table, .release-body table, .changelog-entry-body table, .home-content table { width: 100%; border-collapse: collapse; margin-bottom: 15px; }
|
|
@@ -4,10 +4,17 @@
|
|
|
4
4
|
<button class="mobile-menu-toggle" id="mobile-menu-toggle" aria-label="Toggle navigation menu">
|
|
5
5
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
|
|
6
6
|
</button>
|
|
7
|
-
<a href="{{baseUrl}}/">
|
|
7
|
+
<a href="{{baseUrl}}/" class="logo-link">
|
|
8
8
|
<img alt="{{siteTitle}}" class="logo__img" src="{{baseUrl}}/logo.svg">
|
|
9
|
+
<span class="logo__text">{{siteTitle}}</span>
|
|
9
10
|
</a>
|
|
10
11
|
<nav class="header-bottom__nav">
|
|
12
|
+
{{#if homeUrl}}
|
|
13
|
+
<a class="header-bottom__item header-bottom__item--home" href="{{homeUrl}}">
|
|
14
|
+
<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="m12 19-7-7 7-7"/><path d="M19 12H5"/></svg>
|
|
15
|
+
<span>Back to Home</span>
|
|
16
|
+
</a>
|
|
17
|
+
{{/if}}
|
|
11
18
|
{{#if hasDocuments}}
|
|
12
19
|
<a class="header-bottom__item" href="{{docsUrl}}/" id="nav-docs">
|
|
13
20
|
<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="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
|
|
@@ -21,7 +28,7 @@
|
|
|
21
28
|
</a>
|
|
22
29
|
{{/if}}
|
|
23
30
|
{{#if hasChangelog}}
|
|
24
|
-
<a class="header-bottom__item" href="{{changelogUrl}}" id="nav-changelog">
|
|
31
|
+
<a class="header-bottom__item" href="{{changelogUrl}}/" id="nav-changelog">
|
|
25
32
|
<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="M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z"/><path d="M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14"/><path d="M8 6v8"/></svg>
|
|
26
33
|
<span>Changelog</span>
|
|
27
34
|
</a>
|
|
@@ -67,6 +74,12 @@
|
|
|
67
74
|
</header>
|
|
68
75
|
<aside class="mobile-sidebar" id="mobile-sidebar">
|
|
69
76
|
<nav class="mobile-nav">
|
|
77
|
+
{{#if homeUrl}}
|
|
78
|
+
<a class="mobile-nav__item" href="{{homeUrl}}">
|
|
79
|
+
<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="m12 19-7-7 7-7"/><path d="M19 12H5"/></svg>
|
|
80
|
+
<span>Back to Home</span>
|
|
81
|
+
</a>
|
|
82
|
+
{{/if}}
|
|
70
83
|
{{#if hasDocuments}}
|
|
71
84
|
<a class="mobile-nav__item" href="{{docsUrl}}/">
|
|
72
85
|
<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="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
|
|
@@ -80,7 +93,7 @@
|
|
|
80
93
|
</a>
|
|
81
94
|
{{/if}}
|
|
82
95
|
{{#if hasChangelog}}
|
|
83
|
-
<a class="mobile-nav__item" href="{{changelogUrl}}">
|
|
96
|
+
<a class="mobile-nav__item" href="{{changelogUrl}}/">
|
|
84
97
|
<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="M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z"/><path d="M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14"/><path d="M8 6v8"/></svg>
|
|
85
98
|
<span>Changelog</span>
|
|
86
99
|
</a>
|
|
@@ -5,6 +5,25 @@
|
|
|
5
5
|
hljs.highlightAll();
|
|
6
6
|
var kbd = document.querySelector('.search-button__shortcut');
|
|
7
7
|
if (kbd) kbd.textContent = navigator.platform.indexOf('Mac') > -1 ? '⌘K' : 'Ctrl K';
|
|
8
|
+
|
|
9
|
+
// Copy code buttons
|
|
10
|
+
const copyIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
|
|
11
|
+
const checkIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>';
|
|
12
|
+
document.querySelectorAll('pre').forEach(function(pre) {
|
|
13
|
+
const btn = document.createElement('button');
|
|
14
|
+
btn.className = 'copy-code-btn';
|
|
15
|
+
btn.innerHTML = copyIcon;
|
|
16
|
+
btn.setAttribute('aria-label', 'Copy code');
|
|
17
|
+
btn.addEventListener('click', function() {
|
|
18
|
+
const code = pre.querySelector('code');
|
|
19
|
+
const text = code ? code.textContent : pre.textContent;
|
|
20
|
+
navigator.clipboard.writeText(text || '').then(function() {
|
|
21
|
+
btn.innerHTML = checkIcon;
|
|
22
|
+
setTimeout(function() { btn.innerHTML = copyIcon; }, 2000);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
pre.appendChild(btn);
|
|
26
|
+
});
|
|
8
27
|
});
|
|
9
28
|
</script>
|
|
10
29
|
<script>
|
|
@@ -243,5 +262,29 @@
|
|
|
243
262
|
const aside = tocSidebar.closest('.content-aside');
|
|
244
263
|
if (aside) { aside.style.display = 'none'; }
|
|
245
264
|
}
|
|
265
|
+
|
|
266
|
+
// Image lightbox
|
|
267
|
+
const lightboxOverlay = document.createElement('div');
|
|
268
|
+
lightboxOverlay.className = 'lightbox-overlay';
|
|
269
|
+
lightboxOverlay.addEventListener('click', function(e) {
|
|
270
|
+
if (e.target !== lightboxImg) lightboxOverlay.classList.remove('lightbox-overlay--visible');
|
|
271
|
+
});
|
|
272
|
+
const lightboxClose = document.createElement('button');
|
|
273
|
+
lightboxClose.className = 'lightbox-close';
|
|
274
|
+
lightboxClose.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';
|
|
275
|
+
lightboxClose.addEventListener('click', function() {
|
|
276
|
+
lightboxOverlay.classList.remove('lightbox-overlay--visible');
|
|
277
|
+
});
|
|
278
|
+
const lightboxImg = document.createElement('img');
|
|
279
|
+
lightboxOverlay.appendChild(lightboxClose);
|
|
280
|
+
lightboxOverlay.appendChild(lightboxImg);
|
|
281
|
+
document.body.appendChild(lightboxOverlay);
|
|
282
|
+
|
|
283
|
+
document.querySelectorAll('.article__main img, .changelog-entry-body img').forEach(function(img) {
|
|
284
|
+
img.addEventListener('click', function() {
|
|
285
|
+
lightboxImg.src = img.src;
|
|
286
|
+
lightboxOverlay.classList.add('lightbox-overlay--visible');
|
|
287
|
+
});
|
|
288
|
+
});
|
|
246
289
|
});
|
|
247
290
|
</script>
|