@terrymooreii/sia 2.0.0 → 2.0.1
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/_config.yml +0 -1
- package/defaults/includes/footer.njk +2 -2
- package/defaults/includes/header.njk +5 -5
- package/defaults/includes/tag-list.njk +1 -1
- package/defaults/layouts/base.njk +3 -3
- package/defaults/layouts/note.njk +2 -2
- package/defaults/layouts/post.njk +3 -3
- package/defaults/pages/blog.njk +1 -1
- package/defaults/pages/index.njk +3 -3
- package/defaults/pages/notes.njk +1 -1
- package/defaults/pages/tag.njk +2 -2
- package/defaults/pages/tags.njk +2 -2
- package/lib/build.js +6 -3
- package/lib/collections.js +9 -5
- package/lib/config.js +8 -0
- package/lib/content.js +3 -1
- package/lib/templates.js +19 -0
- package/package.json +1 -1
package/_config.yml
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
</p>
|
|
7
7
|
|
|
8
8
|
<nav class="footer-nav">
|
|
9
|
-
<a href="/feed.xml" class="footer-link">RSS</a>
|
|
10
|
-
<a href="/tags/" class="footer-link">Tags</a>
|
|
9
|
+
<a href="{{ '/feed.xml' | url }}" class="footer-link">RSS</a>
|
|
10
|
+
<a href="{{ '/tags/' | url }}" class="footer-link">Tags</a>
|
|
11
11
|
</nav>
|
|
12
12
|
</div>
|
|
13
13
|
</footer>
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
<header class="site-header">
|
|
2
2
|
<div class="container">
|
|
3
|
-
<a href="/" class="site-logo">{{ site.title }}</a>
|
|
3
|
+
<a href="{{ '/' | url }}" class="site-logo">{{ site.title }}</a>
|
|
4
4
|
|
|
5
5
|
<nav class="site-nav">
|
|
6
|
-
<a href="/" class="nav-link{% if page.url == '/' %} active{% endif %}">Home</a>
|
|
7
|
-
<a href="/blog/" class="nav-link{% if page.url and page.url.startsWith('/blog') %} active{% endif %}">Blog</a>
|
|
8
|
-
<a href="/notes/" class="nav-link{% if page.url and page.url.startsWith('/notes') %} active{% endif %}">Notes</a>
|
|
9
|
-
<a href="/tags/" class="nav-link{% if page.url and page.url.startsWith('/tags') %} active{% endif %}">Tags</a>
|
|
6
|
+
<a href="{{ '/' | url }}" class="nav-link{% if page.url == ('/' | url) %} active{% endif %}">Home</a>
|
|
7
|
+
<a href="{{ '/blog/' | url }}" class="nav-link{% if page.url and page.url.startsWith('/blog') %} active{% endif %}">Blog</a>
|
|
8
|
+
<a href="{{ '/notes/' | url }}" class="nav-link{% if page.url and page.url.startsWith('/notes') %} active{% endif %}">Notes</a>
|
|
9
|
+
<a href="{{ '/tags/' | url }}" class="nav-link{% if page.url and page.url.startsWith('/tags') %} active{% endif %}">Tags</a>
|
|
10
10
|
{% if collections.pages %}
|
|
11
11
|
{% for p in collections.pages | limit(3) %}
|
|
12
12
|
<a href="{{ p.url }}" class="nav-link{% if page.url == p.url %} active{% endif %}">{{ p.title }}</a>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{% if allTags and allTags.length %}
|
|
2
2
|
<div class="tag-cloud">
|
|
3
3
|
{% for tag in allTags %}
|
|
4
|
-
<a href="/tags/{{ tag.slug }}/" class="tag tag-{{ 'lg' if tag.count > 10 else ('md' if tag.count > 5 else 'sm') }}">
|
|
4
|
+
<a href="{{ '/tags/' | url }}{{ tag.slug }}/" class="tag tag-{{ 'lg' if tag.count > 10 else ('md' if tag.count > 5 else 'sm') }}">
|
|
5
5
|
{{ tag.name }}
|
|
6
6
|
<span class="tag-count">({{ tag.count }})</span>
|
|
7
7
|
</a>
|
|
@@ -15,16 +15,16 @@
|
|
|
15
15
|
})();
|
|
16
16
|
</script>
|
|
17
17
|
|
|
18
|
-
<link rel="stylesheet" href="/styles/main.css">
|
|
18
|
+
<link rel="stylesheet" href="{{ '/styles/main.css' | url }}">
|
|
19
19
|
|
|
20
20
|
<!-- Open Graph -->
|
|
21
21
|
<meta property="og:title" content="{{ title or site.title }}">
|
|
22
22
|
<meta property="og:description" content="{{ page.excerpt or site.description }}">
|
|
23
23
|
<meta property="og:type" content="{% if page.collection == 'posts' %}article{% else %}website{% endif %}">
|
|
24
|
-
<meta property="og:url" content="{{ site.url }}{{ page.url or '/' }}">
|
|
24
|
+
<meta property="og:url" content="{{ site.url }}{{ page.url or ('/' | url) }}">
|
|
25
25
|
|
|
26
26
|
<!-- RSS Feed -->
|
|
27
|
-
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="/feed.xml">
|
|
27
|
+
<link rel="alternate" type="application/rss+xml" title="{{ site.title }}" href="{{ '/feed.xml' | url }}">
|
|
28
28
|
|
|
29
29
|
{% block head %}{% endblock %}
|
|
30
30
|
</head>
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
{% if page.tags and page.tags.length %}
|
|
12
12
|
<span class="note-tags">
|
|
13
13
|
{% for tag in page.tags %}
|
|
14
|
-
<a href="/tags/{{ tag | slug }}/" class="tag">{{ tag }}</a>
|
|
14
|
+
<a href="{{ '/tags/' | url }}{{ tag | slug }}/" class="tag">{{ tag }}</a>
|
|
15
15
|
{% endfor %}
|
|
16
16
|
</span>
|
|
17
17
|
{% endif %}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
</article>
|
|
20
20
|
|
|
21
21
|
<nav class="note-nav">
|
|
22
|
-
<a href="/notes/" class="btn btn-secondary">← All Notes</a>
|
|
22
|
+
<a href="{{ '/notes/' | url }}" class="btn btn-secondary">← All Notes</a>
|
|
23
23
|
</nav>
|
|
24
24
|
{% endblock %}
|
|
25
25
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<span class="post-meta-divider">·</span>
|
|
12
12
|
<span class="post-tags">
|
|
13
13
|
{% for tag in page.tags %}
|
|
14
|
-
<a href="/tags/{{ tag | slug }}/" class="tag">{{ tag }}</a>{% if not loop.last %}, {% endif %}
|
|
14
|
+
<a href="{{ '/tags/' | url }}{{ tag | slug }}/" class="tag">{{ tag }}</a>{% if not loop.last %}, {% endif %}
|
|
15
15
|
{% endfor %}
|
|
16
16
|
</span>
|
|
17
17
|
{% endif %}
|
|
@@ -29,13 +29,13 @@
|
|
|
29
29
|
<div class="post-tags-footer">
|
|
30
30
|
<span class="tags-label">Tagged:</span>
|
|
31
31
|
{% for tag in page.tags %}
|
|
32
|
-
<a href="/tags/{{ tag | slug }}/" class="tag">{{ tag }}</a>
|
|
32
|
+
<a href="{{ '/tags/' | url }}{{ tag | slug }}/" class="tag">{{ tag }}</a>
|
|
33
33
|
{% endfor %}
|
|
34
34
|
</div>
|
|
35
35
|
{% endif %}
|
|
36
36
|
|
|
37
37
|
<nav class="post-nav">
|
|
38
|
-
<a href="/blog/" class="btn btn-secondary">← Back to Blog</a>
|
|
38
|
+
<a href="{{ '/blog/' | url }}" class="btn btn-secondary">← Back to Blog</a>
|
|
39
39
|
</nav>
|
|
40
40
|
</footer>
|
|
41
41
|
</article>
|
package/defaults/pages/blog.njk
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
{% if post.tags and post.tags.length %}
|
|
20
20
|
<div class="post-card-tags">
|
|
21
21
|
{% for tag in post.tags %}
|
|
22
|
-
<a href="/tags/{{ tag | slug }}/" class="tag tag-sm">{{ tag }}</a>
|
|
22
|
+
<a href="{{ '/tags/' | url }}{{ tag | slug }}/" class="tag tag-sm">{{ tag }}</a>
|
|
23
23
|
{% endfor %}
|
|
24
24
|
</div>
|
|
25
25
|
{% endif %}
|
package/defaults/pages/index.njk
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<section class="section">
|
|
10
10
|
<div class="section-header">
|
|
11
11
|
<h2 class="section-title">Latest Posts</h2>
|
|
12
|
-
<a href="/blog/" class="section-link">View all →</a>
|
|
12
|
+
<a href="{{ '/blog/' | url }}" class="section-link">View all →</a>
|
|
13
13
|
</div>
|
|
14
14
|
|
|
15
15
|
<div class="post-list">
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
{% if post.tags and post.tags.length %}
|
|
24
24
|
<span class="post-card-tags">
|
|
25
25
|
{% for tag in post.tags | limit(3) %}
|
|
26
|
-
<a href="/tags/{{ tag | slug }}/" class="tag tag-sm">{{ tag }}</a>
|
|
26
|
+
<a href="{{ '/tags/' | url }}{{ tag | slug }}/" class="tag tag-sm">{{ tag }}</a>
|
|
27
27
|
{% endfor %}
|
|
28
28
|
</span>
|
|
29
29
|
{% endif %}
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
<section class="section">
|
|
41
41
|
<div class="section-header">
|
|
42
42
|
<h2 class="section-title">Recent Notes</h2>
|
|
43
|
-
<a href="/notes/" class="section-link">View all →</a>
|
|
43
|
+
<a href="{{ '/notes/' | url }}" class="section-link">View all →</a>
|
|
44
44
|
</div>
|
|
45
45
|
|
|
46
46
|
<div class="notes-grid">
|
package/defaults/pages/notes.njk
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{% if note.tags and note.tags.length %}
|
|
18
18
|
<div class="note-item-tags">
|
|
19
19
|
{% for tag in note.tags %}
|
|
20
|
-
<a href="/tags/{{ tag | slug }}/" class="tag tag-sm">{{ tag }}</a>
|
|
20
|
+
<a href="{{ '/tags/' | url }}{{ tag | slug }}/" class="tag tag-sm">{{ tag }}</a>
|
|
21
21
|
{% endfor %}
|
|
22
22
|
</div>
|
|
23
23
|
{% endif %}
|
package/defaults/pages/tag.njk
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
{% if post.tags and post.tags.length %}
|
|
22
22
|
<div class="post-card-tags">
|
|
23
23
|
{% for t in post.tags %}
|
|
24
|
-
<a href="/tags/{{ t | slug }}/" class="tag tag-sm{% if t | slug == tag.slug %} active{% endif %}">{{ t }}</a>
|
|
24
|
+
<a href="{{ '/tags/' | url }}{{ t | slug }}/" class="tag tag-sm{% if t | slug == tag.slug %} active{% endif %}">{{ t }}</a>
|
|
25
25
|
{% endfor %}
|
|
26
26
|
</div>
|
|
27
27
|
{% endif %}
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
{% include "pagination.njk" %}
|
|
36
36
|
|
|
37
37
|
<nav class="page-nav">
|
|
38
|
-
<a href="/tags/" class="btn btn-secondary">← All Tags</a>
|
|
38
|
+
<a href="{{ '/tags/' | url }}" class="btn btn-secondary">← All Tags</a>
|
|
39
39
|
</nav>
|
|
40
40
|
{% endblock %}
|
|
41
41
|
|
package/defaults/pages/tags.njk
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
{% for tag in allTags %}
|
|
15
15
|
<section class="tag-section" id="{{ tag.slug }}">
|
|
16
16
|
<h2 class="tag-section-title">
|
|
17
|
-
<a href="/tags/{{ tag.slug }}/">{{ tag.name }}</a>
|
|
17
|
+
<a href="{{ '/tags/' | url }}{{ tag.slug }}/">{{ tag.name }}</a>
|
|
18
18
|
<span class="tag-section-count">({{ tag.count }})</span>
|
|
19
19
|
</h2>
|
|
20
20
|
<ul class="tag-posts">
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
</li>
|
|
26
26
|
{% endfor %}
|
|
27
27
|
{% if tag.count > 5 %}
|
|
28
|
-
<li><a href="/tags/{{ tag.slug }}/" class="more-link">View all {{ tag.count }} →</a></li>
|
|
28
|
+
<li><a href="{{ '/tags/' | url }}{{ tag.slug }}/" class="more-link">View all {{ tag.count }} →</a></li>
|
|
29
29
|
{% endif %}
|
|
30
30
|
</ul>
|
|
31
31
|
</section>
|
package/lib/build.js
CHANGED
|
@@ -42,13 +42,14 @@ function renderContentItem(env, item, siteData) {
|
|
|
42
42
|
*/
|
|
43
43
|
function renderPaginatedPages(env, siteData, baseUrl, outputBase, templateName, extraData = {}) {
|
|
44
44
|
const { paginatedCollections } = siteData;
|
|
45
|
+
const basePath = siteData.config.site.basePath || '';
|
|
45
46
|
|
|
46
47
|
// Get all posts for the main blog listing
|
|
47
48
|
const posts = siteData.collections.posts || [];
|
|
48
49
|
const pages = paginate(posts, siteData.config.pagination.size);
|
|
49
50
|
|
|
50
51
|
for (const page of pages) {
|
|
51
|
-
const pagination = getPaginationUrls(baseUrl, page);
|
|
52
|
+
const pagination = getPaginationUrls(baseUrl, page, basePath);
|
|
52
53
|
|
|
53
54
|
const html = renderTemplate(env, templateName, {
|
|
54
55
|
...siteData,
|
|
@@ -72,6 +73,7 @@ function renderPaginatedPages(env, siteData, baseUrl, outputBase, templateName,
|
|
|
72
73
|
*/
|
|
73
74
|
function renderTagPages(env, siteData) {
|
|
74
75
|
const { tags, allTags, config } = siteData;
|
|
76
|
+
const basePath = config.site.basePath || '';
|
|
75
77
|
|
|
76
78
|
// Render main tags listing page
|
|
77
79
|
const tagsHtml = renderTemplate(env, 'tags.njk', {
|
|
@@ -86,7 +88,7 @@ function renderTagPages(env, siteData) {
|
|
|
86
88
|
const baseUrl = `/tags/${tagSlug}/`;
|
|
87
89
|
|
|
88
90
|
for (const page of tagPages) {
|
|
89
|
-
const pagination = getPaginationUrls(baseUrl, page);
|
|
91
|
+
const pagination = getPaginationUrls(baseUrl, page, basePath);
|
|
90
92
|
|
|
91
93
|
const html = renderTemplate(env, 'tag.njk', {
|
|
92
94
|
...siteData,
|
|
@@ -144,6 +146,7 @@ function renderBlogListing(env, siteData) {
|
|
|
144
146
|
function renderNotesListing(env, siteData) {
|
|
145
147
|
const { config, collections } = siteData;
|
|
146
148
|
const notes = collections.notes || [];
|
|
149
|
+
const basePath = config.site.basePath || '';
|
|
147
150
|
|
|
148
151
|
if (notes.length === 0) return;
|
|
149
152
|
|
|
@@ -151,7 +154,7 @@ function renderNotesListing(env, siteData) {
|
|
|
151
154
|
const pages = paginate(notes, config.pagination.size);
|
|
152
155
|
|
|
153
156
|
for (const page of pages) {
|
|
154
|
-
const pagination = getPaginationUrls('/notes/', page);
|
|
157
|
+
const pagination = getPaginationUrls('/notes/', page, basePath);
|
|
155
158
|
|
|
156
159
|
const html = renderTemplate(env, 'notes.njk', {
|
|
157
160
|
...siteData,
|
package/lib/collections.js
CHANGED
|
@@ -79,18 +79,22 @@ export function paginate(items, pageSize = 10) {
|
|
|
79
79
|
|
|
80
80
|
/**
|
|
81
81
|
* Generate pagination URLs
|
|
82
|
+
* @param {string} baseUrl - The base URL path (without basePath)
|
|
83
|
+
* @param {object} pagination - Pagination object
|
|
84
|
+
* @param {string} basePath - Optional basePath for subpath hosting
|
|
82
85
|
*/
|
|
83
|
-
export function getPaginationUrls(baseUrl, pagination) {
|
|
86
|
+
export function getPaginationUrls(baseUrl, pagination, basePath = '') {
|
|
87
|
+
const prefixedBaseUrl = basePath + baseUrl;
|
|
84
88
|
return {
|
|
85
89
|
...pagination,
|
|
86
90
|
url: pagination.pageNumber === 1
|
|
87
|
-
?
|
|
88
|
-
: `${
|
|
91
|
+
? prefixedBaseUrl
|
|
92
|
+
: `${prefixedBaseUrl}page/${pagination.pageNumber}/`,
|
|
89
93
|
previousUrl: pagination.previousPage
|
|
90
|
-
? (pagination.previousPage === 1 ?
|
|
94
|
+
? (pagination.previousPage === 1 ? prefixedBaseUrl : `${prefixedBaseUrl}page/${pagination.previousPage}/`)
|
|
91
95
|
: null,
|
|
92
96
|
nextUrl: pagination.nextPage
|
|
93
|
-
? `${
|
|
97
|
+
? `${prefixedBaseUrl}page/${pagination.nextPage}/`
|
|
94
98
|
: null
|
|
95
99
|
};
|
|
96
100
|
}
|
package/lib/config.js
CHANGED
|
@@ -93,6 +93,14 @@ export function loadConfig(rootDir = process.cwd()) {
|
|
|
93
93
|
// Merge user config with defaults
|
|
94
94
|
const config = deepMerge(defaultConfig, userConfig);
|
|
95
95
|
|
|
96
|
+
// Extract basePath from site URL (e.g., "https://example.org/test" -> "/test")
|
|
97
|
+
try {
|
|
98
|
+
const siteUrl = new URL(config.site.url);
|
|
99
|
+
config.site.basePath = siteUrl.pathname.replace(/\/$/, '') || '';
|
|
100
|
+
} catch (e) {
|
|
101
|
+
config.site.basePath = '';
|
|
102
|
+
}
|
|
103
|
+
|
|
96
104
|
// Add computed paths
|
|
97
105
|
config.rootDir = rootDir;
|
|
98
106
|
config.inputDir = join(rootDir, config.input);
|
package/lib/content.js
CHANGED
|
@@ -262,7 +262,9 @@ export function loadCollection(config, collectionName) {
|
|
|
262
262
|
.replace(':month', String(item.date.getMonth() + 1).padStart(2, '0'))
|
|
263
263
|
.replace(':day', String(item.date.getDate()).padStart(2, '0'));
|
|
264
264
|
|
|
265
|
-
|
|
265
|
+
// Prepend basePath for subpath hosting support
|
|
266
|
+
const basePath = config.site.basePath || '';
|
|
267
|
+
item.url = basePath + permalink;
|
|
266
268
|
item.outputPath = join(config.outputDir, permalink, 'index.html');
|
|
267
269
|
|
|
268
270
|
return item;
|
package/lib/templates.js
CHANGED
|
@@ -170,6 +170,22 @@ function jsonFilter(obj, spaces = 2) {
|
|
|
170
170
|
return JSON.stringify(obj, null, spaces);
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Create a URL filter that prepends the basePath
|
|
175
|
+
*/
|
|
176
|
+
function createUrlFilter(basePath) {
|
|
177
|
+
return function urlFilter(path) {
|
|
178
|
+
if (!path) return basePath || '/';
|
|
179
|
+
// If path is already absolute with protocol, return as-is
|
|
180
|
+
if (path.startsWith('http://') || path.startsWith('https://')) {
|
|
181
|
+
return path;
|
|
182
|
+
}
|
|
183
|
+
// Ensure path starts with /
|
|
184
|
+
const normalizedPath = path.startsWith('/') ? path : '/' + path;
|
|
185
|
+
return (basePath || '') + normalizedPath;
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
173
189
|
/**
|
|
174
190
|
* Create and configure the Nunjucks environment
|
|
175
191
|
*/
|
|
@@ -214,6 +230,9 @@ export function createTemplateEngine(config) {
|
|
|
214
230
|
env.addFilter('withTag', withTagFilter);
|
|
215
231
|
env.addFilter('json', jsonFilter);
|
|
216
232
|
|
|
233
|
+
// Add URL filter with basePath support
|
|
234
|
+
env.addFilter('url', createUrlFilter(config.site.basePath));
|
|
235
|
+
|
|
217
236
|
return env;
|
|
218
237
|
}
|
|
219
238
|
|