astro-accelerator 0.0.28 → 0.0.30
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 +2 -2
- package/src/config.ts +15 -50
- package/src/data/footer.ts +1 -1
- package/src/data/navigation.ts +1 -1
- package/src/pages/articles/[page].astro +2 -3
- package/src/pages/articles/feed.xml.ts +2 -3
- package/src/pages/authors/[author]/[page].astro +3 -5
- package/src/pages/category/[category]/[page].astro +2 -3
- package/src/pages/report/missing-banner.astro +1 -2
- package/src/pages/report/missing-meta.astro +1 -2
- package/src/pages/report/missing-pubdate.astro +1 -2
- package/src/pages/report/oldest-content.astro +1 -2
- package/src/pages/report/taxonomy.astro +7 -6
- package/src/pages/search.json.ts +2 -3
- package/src/pages/tag/[tag]/[page].astro +2 -3
- package/src/themes/accelerator/components/ArticleList.astro +2 -3
- package/src/themes/accelerator/components/Authors.astro +1 -2
- package/src/themes/accelerator/components/AuthorsMini.astro +1 -2
- package/src/themes/accelerator/components/Breadcrumbs.astro +2 -3
- package/src/themes/accelerator/components/Footer.astro +3 -2
- package/src/themes/accelerator/components/FooterItem.astro +1 -1
- package/src/themes/accelerator/components/Header.astro +1 -2
- package/src/themes/accelerator/components/HtmlHead.astro +2 -3
- package/src/themes/accelerator/components/Navigation.astro +4 -2
- package/src/themes/accelerator/components/NavigationBar.astro +4 -2
- package/src/themes/accelerator/components/NavigationItem.astro +1 -1
- package/src/themes/accelerator/components/Related.astro +1 -2
- package/src/themes/accelerator/components/Taxonomy.astro +3 -2
- package/src/themes/accelerator/layouts/Author.astro +1 -2
- package/src/themes/accelerator/layouts/Default.astro +4 -4
- package/src/themes/accelerator/utilities/TempNavPage.ts +10 -0
- package/src/themes/accelerator/utilities/Breadcrumbs.ts +0 -26
- package/src/themes/accelerator/utilities/Footer.ts +0 -172
- package/src/themes/accelerator/utilities/Markdown.ts +0 -30
- package/src/themes/accelerator/utilities/NavPage.ts +0 -64
- package/src/themes/accelerator/utilities/Navigation.ts +0 -78
- package/src/themes/accelerator/utilities/NavigationTypes.ts +0 -18
- package/src/themes/accelerator/utilities/PageLinks.ts +0 -70
- package/src/themes/accelerator/utilities/PageQueries.ts +0 -56
- package/src/themes/accelerator/utilities/Taxonomy.ts +0 -115
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.0.
|
|
2
|
+
"version": "0.0.30",
|
|
3
3
|
"author": "Steve Fenton",
|
|
4
4
|
"name": "astro-accelerator",
|
|
5
5
|
"description": "A super-lightweight, accessible, SEO-friendly starter project for Astro",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@squoosh/lib": "^0.4.0",
|
|
28
28
|
"astro": "^1.6.6",
|
|
29
|
-
"astro-accelerator-utils": "^0.0.
|
|
29
|
+
"astro-accelerator-utils": "^0.0.43",
|
|
30
30
|
"hast-util-from-selector": "^2.0.0",
|
|
31
31
|
"remark-directive": "^2.0.1"
|
|
32
32
|
},
|
package/src/config.ts
CHANGED
|
@@ -1,65 +1,30 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Config } from 'astro-accelerator-utils';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
lang: 'en',
|
|
14
|
-
locale: 'en-GB',
|
|
15
|
-
dir: 'ltr'
|
|
16
|
-
},
|
|
17
|
-
search: {
|
|
18
|
-
fallbackUrl: 'https://www.google.com/search',
|
|
19
|
-
fallbackSite: 'q',
|
|
20
|
-
fallbackQuery: 'q',
|
|
21
|
-
},
|
|
22
|
-
pageSize: 2,
|
|
23
|
-
/*
|
|
24
|
-
Refers to "pages in the middle" of the automatically generated links:
|
|
25
|
-
- Prev
|
|
26
|
-
- First Page
|
|
27
|
-
- (A number of links, defined below)
|
|
28
|
-
- Last Page
|
|
29
|
-
- Next
|
|
30
|
-
*/
|
|
31
|
-
pageLinks: 3,
|
|
32
|
-
rssLimit: 20,
|
|
33
|
-
dateOptions: {
|
|
34
|
-
weekday: 'long',
|
|
35
|
-
year: 'numeric',
|
|
36
|
-
month: 'long',
|
|
37
|
-
day: 'numeric',
|
|
38
|
-
},
|
|
39
|
-
featureFlags: {
|
|
40
|
-
codeBlocks: ['copy'],
|
|
41
|
-
figures: ['enlarge'],
|
|
42
|
-
youTubeLinks: ['embed'],
|
|
43
|
-
},
|
|
44
|
-
images: {
|
|
45
|
-
contentSize: '(max-width: 860px) 100vw, 620px',
|
|
46
|
-
listerSize: '(max-width: 860px) 90vw, 350px',
|
|
47
|
-
authorSize: '50px',
|
|
48
|
-
}
|
|
49
|
-
};
|
|
3
|
+
const SITE = Config.getDefault();
|
|
4
|
+
SITE.owner = 'Steve Fenton';
|
|
5
|
+
SITE.url = 'https://astro.stevefenton.co.uk';
|
|
6
|
+
SITE.feedUrl = '/articles/feed.xml';
|
|
7
|
+
SITE.title= 'Astro Accelerator';
|
|
8
|
+
SITE.description = 'An Astro quick start project.';
|
|
9
|
+
SITE.themeColor = '#222255';
|
|
10
|
+
SITE.defaultLanguage = 'en';
|
|
11
|
+
SITE.default.locale = 'en-GB';
|
|
12
|
+
SITE.pageSize = 2; // Allows testing of paging
|
|
50
13
|
|
|
51
14
|
// Default image for OG: Tags
|
|
52
|
-
|
|
15
|
+
const OPEN_GRAPH = {
|
|
53
16
|
image: {
|
|
54
17
|
src: '/img/surface-accessories.png',
|
|
55
18
|
alt: 'Alt text for image goes here',
|
|
56
19
|
}
|
|
57
20
|
};
|
|
58
21
|
|
|
59
|
-
|
|
22
|
+
const HEADER_SCRIPTS = `
|
|
60
23
|
<!-- HEADER SCRIPTS -->
|
|
61
24
|
`.trim();
|
|
62
25
|
|
|
26
|
+
export { SITE, OPEN_GRAPH, HEADER_SCRIPTS }
|
|
27
|
+
|
|
63
28
|
export type Frontmatter = {
|
|
64
29
|
layout: string;
|
|
65
30
|
title: string;
|
package/src/data/footer.ts
CHANGED
package/src/data/navigation.ts
CHANGED
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// warning: This file is overwritten by Astro Accelerator
|
|
3
3
|
|
|
4
4
|
// For listing all articles in this folder
|
|
5
|
+
import { Cache, PostFiltering, PostOrdering, PostPaging } from 'astro-accelerator-utils';
|
|
5
6
|
import { Translations, Lang } from '@util/Languages';
|
|
6
7
|
import type { Page, MarkdownInstance } from 'astro';
|
|
7
8
|
import { Frontmatter, SITE } from '@config';
|
|
8
|
-
import { getPageLinks } from '@util/PageLinks';
|
|
9
|
-
import { Cache, PostFiltering, PostOrdering } from 'astro-accelerator-utils';
|
|
10
9
|
import Default from 'src/layouts/Default.astro';
|
|
11
10
|
import ArticleList from '@components/ArticleList.astro';
|
|
12
11
|
import Paging from '@components/Paging.astro';
|
|
@@ -68,7 +67,7 @@ export async function getStaticPaths({ paginate }: any) {
|
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
// Page Links
|
|
71
|
-
const pageLinks = getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
70
|
+
const pageLinks = PostPaging.getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
72
71
|
---
|
|
73
72
|
<Default frontmatter={ frontmatter } headings={ headings }>
|
|
74
73
|
<h2>{ _(Translations.articles.page_title).replace('{n}', page.currentPage.toString())}</h2>
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// Generates an ATOM feed of recent posts
|
|
4
4
|
import { SITE } from '@config';
|
|
5
|
-
import { PostFiltering, Urls } from 'astro-accelerator-utils';
|
|
6
|
-
import { getTextFrom } from '@util/Markdown';
|
|
5
|
+
import { Markdown, PostFiltering, Urls } from 'astro-accelerator-utils';
|
|
7
6
|
|
|
8
7
|
async function getData() {
|
|
9
8
|
//@ts-ignore
|
|
@@ -15,7 +14,7 @@ async function getData() {
|
|
|
15
14
|
const article: any = await allArticles[path]();
|
|
16
15
|
|
|
17
16
|
if (PostFiltering.isListable(article)) {
|
|
18
|
-
article.frontmatter.title = await getTextFrom(article.frontmatter.title ?? '');
|
|
17
|
+
article.frontmatter.title = await Markdown.getTextFrom(article.frontmatter.title ?? '');
|
|
19
18
|
|
|
20
19
|
articles.push({
|
|
21
20
|
url: article.url,
|
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
// warning: This file is overwritten by Astro Accelerator
|
|
3
3
|
|
|
4
4
|
// For listing all articles in this folder
|
|
5
|
+
import { Cache, PostFiltering, PostOrdering, PostQueries, PostPaging } from 'astro-accelerator-utils';
|
|
5
6
|
import { Translations, Lang } from '@util/Languages';
|
|
6
7
|
import type { Page, MarkdownInstance } from 'astro';
|
|
7
8
|
import { SITE, Frontmatter } from '@config';
|
|
8
|
-
import { getPageLinks } from '@util/PageLinks';
|
|
9
|
-
import { Cache, PostFiltering, PostOrdering } from 'astro-accelerator-utils';
|
|
10
|
-
import { getAuthorInfo } from '@util/PageQueries';
|
|
11
9
|
import Default from '@layouts/Default.astro';
|
|
12
10
|
import ArticleList from '@components/ArticleList.astro';
|
|
13
11
|
import Paging from '@components/Paging.astro';
|
|
@@ -16,7 +14,7 @@ const lang = SITE.default.lang;
|
|
|
16
14
|
const currentUrl = new URL(Astro.request.url);
|
|
17
15
|
const slug = currentUrl.pathname.split('/')[2];
|
|
18
16
|
|
|
19
|
-
let authorInfo = await getAuthorInfo(slug);
|
|
17
|
+
let authorInfo = await PostQueries.getAuthorInfo(slug);
|
|
20
18
|
|
|
21
19
|
const frontmatter = authorInfo.frontmatter as Frontmatter;
|
|
22
20
|
|
|
@@ -88,7 +86,7 @@ export async function getStaticPaths({ paginate }: any) {
|
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
// Page Links
|
|
91
|
-
const pageLinks = getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
89
|
+
const pageLinks = PostPaging.getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
92
90
|
---
|
|
93
91
|
<Default frontmatter={ frontmatter } headings={ headings }>
|
|
94
92
|
<h2>{ _(Translations.articles.page_title).replace('{n}', page.currentPage.toString())}</h2>
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// warning: This file is overwritten by Astro Accelerator
|
|
3
3
|
|
|
4
4
|
// For listing by frontmatter.categories
|
|
5
|
+
import { Cache, PostFiltering, PostOrdering, PostPaging } from 'astro-accelerator-utils';
|
|
5
6
|
import { Translations, Lang } from '@util/Languages';
|
|
6
7
|
import type { Page, MarkdownInstance } from 'astro';
|
|
7
8
|
import { SITE, Frontmatter } from '@config';
|
|
8
|
-
import { getPageLinks } from '@util/PageLinks';
|
|
9
|
-
import { Cache, PostFiltering, PostOrdering } from 'astro-accelerator-utils';
|
|
10
9
|
import Default from 'src/layouts/Default.astro';
|
|
11
10
|
import ArticleList from '@components/ArticleList.astro';
|
|
12
11
|
import Paging from '@components/Paging.astro';
|
|
@@ -92,7 +91,7 @@ export async function getStaticPaths({ paginate }: any) {
|
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
// Page Links
|
|
95
|
-
const pageLinks = getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
94
|
+
const pageLinks = PostPaging.getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
96
95
|
---
|
|
97
96
|
<Default frontmatter={ frontmatter } headings={ headings }>
|
|
98
97
|
<h2>{ _(Translations.articles.page_title).replace('{n}', page.currentPage.toString())}</h2>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { PostQueries, PostOrdering } from 'astro-accelerator-utils';
|
|
3
|
-
import { fetchPages } from '@util/PageQueries';
|
|
4
3
|
|
|
5
4
|
// Logic
|
|
6
|
-
const allPages = await PostQueries.getPages(
|
|
5
|
+
const allPages = await PostQueries.getPages();
|
|
7
6
|
const missingBanner = allPages.filter(p => p.frontmatter.bannerImage == null && p.frontmatter.layout != 'src/layouts/Redirect.astro');
|
|
8
7
|
const pageCount = missingBanner.length;
|
|
9
8
|
const pages = missingBanner.sort(PostOrdering.sortByPubDateDesc).slice(0, Math.min(50, pageCount));
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { PostQueries, PostOrdering } from 'astro-accelerator-utils';
|
|
3
|
-
import { fetchPages } from '@util/PageQueries';
|
|
4
3
|
|
|
5
4
|
// Logic
|
|
6
|
-
const allPages = await PostQueries.getPages(
|
|
5
|
+
const allPages = await PostQueries.getPages();
|
|
7
6
|
const missingMeta = allPages.filter(p => (p.frontmatter.keywords == null || p.frontmatter.description == null) && p.frontmatter.layout != 'src/layouts/Redirect.astro');
|
|
8
7
|
const pageCount = missingMeta.length;
|
|
9
8
|
const pages = missingMeta.sort(PostOrdering.sortByPubDateDesc).slice(0, Math.min(50, pageCount));
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { PostQueries } from 'astro-accelerator-utils';
|
|
3
|
-
import { fetchPages } from '@util/PageQueries';
|
|
4
3
|
|
|
5
4
|
// Logic
|
|
6
|
-
const allPages = await PostQueries.getPages(
|
|
5
|
+
const allPages = await PostQueries.getPages();
|
|
7
6
|
const missingMeta = allPages.filter(p => (p.frontmatter.pubDate == null && p.frontmatter.layout != 'src/layouts/Redirect.astro'));
|
|
8
7
|
const pageCount = missingMeta.length;
|
|
9
8
|
const pages = missingMeta.slice(0, Math.min(50, pageCount));
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { PostQueries, PostOrdering } from 'astro-accelerator-utils';
|
|
3
|
-
import { fetchPages } from '@util/PageQueries';
|
|
4
3
|
|
|
5
4
|
// Logic
|
|
6
|
-
const allPages = await PostQueries.getPages(
|
|
5
|
+
const allPages = await PostQueries.getPages();
|
|
7
6
|
const pageCount = allPages.length;
|
|
8
7
|
const pages = allPages.sort(PostOrdering.sortByModDate).slice(0, Math.min(50, pageCount));
|
|
9
8
|
---
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { Taxonomy } from 'astro-accelerator-utils';
|
|
2
3
|
import { Lang } from '@util/Languages';
|
|
3
|
-
|
|
4
|
-
import {
|
|
4
|
+
import { Translations } from '@util/Languages';
|
|
5
|
+
import { SITE } from '@config';
|
|
5
6
|
|
|
6
7
|
// Lang
|
|
7
8
|
const _ = Lang('en');
|
|
8
9
|
|
|
9
10
|
// Logic
|
|
10
11
|
|
|
11
|
-
const links = taxonomyLinks(_);
|
|
12
|
-
const taxonomy = await getTaxonomy();
|
|
12
|
+
const links = Taxonomy.taxonomyLinks(Translations, _, SITE);
|
|
13
|
+
const taxonomy = await Taxonomy.getTaxonomy();
|
|
13
14
|
---
|
|
14
15
|
<!doctype html>
|
|
15
16
|
<html>
|
|
@@ -27,14 +28,14 @@ const taxonomy = await getTaxonomy();
|
|
|
27
28
|
<th>Count</th>
|
|
28
29
|
</tr>
|
|
29
30
|
</thead>
|
|
30
|
-
{taxonomy.categories.sort(sortByTitle).map(t =>
|
|
31
|
+
{taxonomy.categories.sort(Taxonomy.sortByTitle).map(t =>
|
|
31
32
|
<tr>
|
|
32
33
|
<td>{ links.category }</td>
|
|
33
34
|
<td><a href={ links.getCategoryLink(t.title) }>{ t.title }</a></td>
|
|
34
35
|
<td>{ t.count }</td>
|
|
35
36
|
</tr>
|
|
36
37
|
)}
|
|
37
|
-
{taxonomy.tags.sort(sortByTitle).map(t =>
|
|
38
|
+
{taxonomy.tags.sort(Taxonomy.sortByTitle).map(t =>
|
|
38
39
|
<tr>
|
|
39
40
|
<td>{ links.tag }</td>
|
|
40
41
|
<td><a href={ links.getTagLink(t.title) }>{ t.title }</a></td>
|
package/src/pages/search.json.ts
CHANGED
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import type { MarkdownInstance } from 'astro';
|
|
4
4
|
import { SITE } from '@config';
|
|
5
|
-
import { PostFiltering, Urls } from 'astro-accelerator-utils';
|
|
6
|
-
import { getTextFrom } from '@util/Markdown';
|
|
5
|
+
import { Markdown, PostFiltering, Urls } from 'astro-accelerator-utils';
|
|
7
6
|
|
|
8
7
|
const getData = async () => {
|
|
9
8
|
//@ts-ignore
|
|
@@ -24,7 +23,7 @@ const getData = async () => {
|
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
const headings = await page.getHeadings();
|
|
27
|
-
const title = await getTextFrom(page.frontmatter.title ?? '');
|
|
26
|
+
const title = await Markdown.getTextFrom(page.frontmatter.title ?? '');
|
|
28
27
|
|
|
29
28
|
items.push({
|
|
30
29
|
title: title,
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
// warning: This file is overwritten by Astro Accelerator
|
|
3
3
|
|
|
4
4
|
// For listing by frontmatter.tags
|
|
5
|
+
import {Cache, PostFiltering, PostOrdering, PostPaging } from 'astro-accelerator-utils';
|
|
5
6
|
import { Translations, Lang } from '@util/Languages';
|
|
6
7
|
import type { Page, MarkdownInstance } from 'astro';
|
|
7
8
|
import { SITE, Frontmatter } from '@config';
|
|
8
|
-
import { getPageLinks } from '@util/PageLinks';
|
|
9
|
-
import {Cache, PostFiltering, PostOrdering } from 'astro-accelerator-utils';
|
|
10
9
|
import Default from 'src/layouts/Default.astro';
|
|
11
10
|
import ArticleList from '@components/ArticleList.astro';
|
|
12
11
|
import Paging from '@components/Paging.astro';
|
|
@@ -92,7 +91,7 @@ export async function getStaticPaths({ paginate }: any) {
|
|
|
92
91
|
}
|
|
93
92
|
|
|
94
93
|
// Page Links
|
|
95
|
-
const pageLinks = getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
94
|
+
const pageLinks = PostPaging.getPageLinks(SITE.pageLinks, page.lastPage, page.currentPage, page.url.current);
|
|
96
95
|
---
|
|
97
96
|
<Default frontmatter={ frontmatter } headings={ headings }>
|
|
98
97
|
<h2>{ _(Translations.articles.page_title).replace('{n}', page.currentPage.toString())}</h2>
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { Markdown, Urls } from 'astro-accelerator-utils';
|
|
2
3
|
import type { MarkdownInstance } from 'astro';
|
|
3
|
-
import { Urls } from 'astro-accelerator-utils';
|
|
4
4
|
import { SITE, Frontmatter } from '@config';
|
|
5
5
|
import { getImageInfo } from '@util/custom-markdown.mjs';
|
|
6
|
-
import { getTextFrom } from '@util/Markdown';
|
|
7
6
|
import AuthorsMini from '@components/AuthorsMini.astro';
|
|
8
7
|
|
|
9
8
|
|
|
@@ -40,7 +39,7 @@ for (let p of posts) {
|
|
|
40
39
|
: null
|
|
41
40
|
};
|
|
42
41
|
|
|
43
|
-
item.frontmatter.title = await getTextFrom(p.frontmatter.title);
|
|
42
|
+
item.frontmatter.title = await Markdown.getTextFrom(p.frontmatter.title);
|
|
44
43
|
|
|
45
44
|
articles.push(item)
|
|
46
45
|
}
|
|
@@ -3,7 +3,6 @@ import { Dates, Urls, PostQueries } from 'astro-accelerator-utils';
|
|
|
3
3
|
import { SITE, Frontmatter } from '@config';
|
|
4
4
|
import { Translations, Lang } from '@util/Languages';
|
|
5
5
|
import { getImageInfo } from '@util/custom-markdown.mjs';
|
|
6
|
-
import { fetchPages } from '@util/PageQueries';
|
|
7
6
|
|
|
8
7
|
// Properties
|
|
9
8
|
type Props = {
|
|
@@ -16,7 +15,7 @@ const { lang, frontmatter } = Astro.props as Props;
|
|
|
16
15
|
const _ = Lang(lang);
|
|
17
16
|
|
|
18
17
|
// Logic
|
|
19
|
-
const authorList = await PostQueries.getAuthors(
|
|
18
|
+
const authorList = await PostQueries.getAuthors(frontmatter);
|
|
20
19
|
|
|
21
20
|
// Get image info
|
|
22
21
|
const authorImage = authorList?.image?.src
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { Dates, PostQueries } from 'astro-accelerator-utils';
|
|
3
3
|
import { SITE, Frontmatter } from '@config';
|
|
4
4
|
import { Translations, Lang } from '@util/Languages';;
|
|
5
|
-
import { fetchPages } from '@util/PageQueries';
|
|
6
5
|
|
|
7
6
|
// Properties
|
|
8
7
|
type Props = {
|
|
@@ -15,7 +14,7 @@ const { lang, frontmatter } = Astro.props as Props;
|
|
|
15
14
|
const _ = Lang(lang);
|
|
16
15
|
|
|
17
16
|
// Logic
|
|
18
|
-
const authorList = await PostQueries.getAuthors(
|
|
17
|
+
const authorList = await PostQueries.getAuthors(frontmatter);
|
|
19
18
|
---
|
|
20
19
|
{authorList.writers.length > 0 &&
|
|
21
20
|
<div class="post-meta">
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { Urls } from 'astro-accelerator-utils';
|
|
2
|
+
import { Urls, PostQueries } from 'astro-accelerator-utils';
|
|
3
3
|
import { SITE, Frontmatter } from '@config';
|
|
4
4
|
import { Translations, Lang } from '@util/Languages';
|
|
5
|
-
import { getBreadcrumbs } from '@util/Breadcrumbs';
|
|
6
5
|
|
|
7
6
|
// Properties
|
|
8
7
|
type Props = {
|
|
@@ -17,7 +16,7 @@ const _ = Lang(lang);
|
|
|
17
16
|
|
|
18
17
|
// Logic
|
|
19
18
|
const currentUrl = new URL(Astro.request.url);
|
|
20
|
-
const navPages = await getBreadcrumbs(currentUrl);
|
|
19
|
+
const navPages = await PostQueries.getBreadcrumbs(currentUrl, SITE);
|
|
21
20
|
---
|
|
22
21
|
<nav class="site-breadcrumbs" aria-label={ _(Translations.aria.breadcrumbs) }>
|
|
23
22
|
<ol vocab="http://schema.org/" typeof="BreadcrumbList">
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { FooterMenu } from 'astro-accelerator-utils';
|
|
2
3
|
import { SITE, Frontmatter } from '@config';
|
|
3
4
|
import { Translations, Lang } from '@util/Languages';
|
|
4
|
-
import {
|
|
5
|
+
import { menu } from 'src/data/footer';
|
|
5
6
|
import FooterItem from '@components/FooterItem.astro';
|
|
6
7
|
|
|
7
8
|
// Properties
|
|
@@ -17,7 +18,7 @@ const _ = Lang(lang);
|
|
|
17
18
|
|
|
18
19
|
// Logic
|
|
19
20
|
const currentUrl = new URL(Astro.request.url);
|
|
20
|
-
const pages = await getMenu(currentUrl,
|
|
21
|
+
const pages = await FooterMenu.getMenu(currentUrl, _, Translations, SITE, menu);
|
|
21
22
|
---
|
|
22
23
|
<footer class="site-footer" id="site-footer">
|
|
23
24
|
<div class="footer-columns">
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { Urls, PostQueries, PostFiltering } from 'astro-accelerator-utils';
|
|
3
3
|
import { SITE, Frontmatter } from '@config';
|
|
4
4
|
import { Translations, Lang } from '@util/Languages';
|
|
5
|
-
import { fetchPages } from '@util/PageQueries';
|
|
6
5
|
|
|
7
6
|
// Properties
|
|
8
7
|
type Props = {
|
|
@@ -16,7 +15,7 @@ const { lang } = Astro.props as Props;
|
|
|
16
15
|
const _ = Lang(lang);
|
|
17
16
|
|
|
18
17
|
// Logic
|
|
19
|
-
const search = (await PostQueries.getPages(
|
|
18
|
+
const search = (await PostQueries.getPages(PostFiltering.isSearch))[0] ?? null;
|
|
20
19
|
|
|
21
20
|
---
|
|
22
21
|
<header class="site-header">
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
|
-
import { Urls } from 'astro-accelerator-utils';
|
|
2
|
+
import { Markdown, Urls } from 'astro-accelerator-utils';
|
|
3
3
|
import { SITE, OPEN_GRAPH, HEADER_SCRIPTS, Frontmatter } from '@config';
|
|
4
|
-
import { getTextFrom } from '@util/Markdown';
|
|
5
4
|
|
|
6
5
|
// Properties
|
|
7
6
|
type Props = {
|
|
@@ -17,7 +16,7 @@ const imageAlt = frontmatter.bannerImage?.alt ?? OPEN_GRAPH.image.alt;
|
|
|
17
16
|
const robots = frontmatter.robots ?? 'index, follow';
|
|
18
17
|
const canonicalImageSrc = new URL(imageSrc, Astro.site);
|
|
19
18
|
const canonicalURL = Urls.addSlashToUrl(new URL(Astro.url.pathname, Astro.site + SITE.subfolder));
|
|
20
|
-
const socialTitle = await getTextFrom(frontmatter.title);
|
|
19
|
+
const socialTitle = await Markdown.getTextFrom(frontmatter.title);
|
|
21
20
|
const title = `${ socialTitle } | ${ SITE.title }`;
|
|
22
21
|
---
|
|
23
22
|
<head>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { Navigation } from 'astro-accelerator-utils';
|
|
2
3
|
import { Translations, Lang } from '@util/Languages';
|
|
3
|
-
import { getMenu } from '@util/Navigation';
|
|
4
4
|
import NavigationItem from '@components/NavigationItem.astro';
|
|
5
|
+
import { SITE } from '@config';
|
|
6
|
+
import { menu } from '@data/navigation';
|
|
5
7
|
|
|
6
8
|
// Properties
|
|
7
9
|
type Props = {
|
|
@@ -14,7 +16,7 @@ const _ = Lang(lang);
|
|
|
14
16
|
|
|
15
17
|
// Logic
|
|
16
18
|
const currentUrl = new URL(Astro.request.url);
|
|
17
|
-
const pages = await getMenu(currentUrl);
|
|
19
|
+
const pages = await Navigation.getMenu(currentUrl, SITE, menu);
|
|
18
20
|
---
|
|
19
21
|
<nav class="site-nav" id="site-nav" aria-label={ _(Translations.aria.site_navigation) }>
|
|
20
22
|
<h2 class="site-nav-title">{ _(Translations.navigation.title) }</h2>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { Navigation } from 'astro-accelerator-utils';
|
|
2
3
|
import { Translations, Lang } from '@util/Languages';
|
|
3
|
-
import {
|
|
4
|
+
import { SITE } from '@config';
|
|
5
|
+
import { menu } from '@data/navigation';
|
|
4
6
|
|
|
5
7
|
// Properties
|
|
6
8
|
type Props = {
|
|
@@ -13,7 +15,7 @@ const _ = Lang(lang);
|
|
|
13
15
|
|
|
14
16
|
// Logic
|
|
15
17
|
const currentUrl = new URL(Astro.request.url);
|
|
16
|
-
const pages = await getMenu(currentUrl);
|
|
18
|
+
const pages = await Navigation.getMenu(currentUrl, SITE, menu);
|
|
17
19
|
---
|
|
18
20
|
<nav class="site-nav-bar" id="site-nav" aria-label={ _(Translations.aria.site_navigation) }>
|
|
19
21
|
<h2 class="site-nav-title">{ _(Translations.navigation.title) }</h2>
|
|
@@ -3,7 +3,6 @@ import { SITE, Frontmatter } from '@config';
|
|
|
3
3
|
import type { MarkdownInstance } from 'astro';
|
|
4
4
|
import { Urls, PostQueries, PostFiltering, PostOrdering } from 'astro-accelerator-utils';
|
|
5
5
|
import { getImageInfo } from '@util/custom-markdown.mjs'
|
|
6
|
-
import { fetchPages } from '@util/PageQueries';
|
|
7
6
|
|
|
8
7
|
import AuthorsMini from '@components/AuthorsMini.astro';
|
|
9
8
|
|
|
@@ -20,7 +19,7 @@ let posts: MarkdownInstance<Record<string, any>>[] = [];
|
|
|
20
19
|
const parentCagory = (frontmatter.categories ?? [null])[0];
|
|
21
20
|
|
|
22
21
|
if (parentCagory != null) {
|
|
23
|
-
const allPages = await PostQueries.getPages(
|
|
22
|
+
const allPages = await PostQueries.getPages(PostFiltering.isListable)
|
|
24
23
|
const allPosts = allPages
|
|
25
24
|
.filter(p => p.frontmatter.title != frontmatter.title && p.frontmatter.categories && p.frontmatter.categories.includes(parentCagory))
|
|
26
25
|
.sort(PostOrdering.sortByPubDateDesc)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
|
+
import { Taxonomy } from 'astro-accelerator-utils';
|
|
2
3
|
import type { Frontmatter } from '@config';
|
|
3
4
|
import { Translations, Lang } from '@util/Languages';
|
|
4
|
-
import {
|
|
5
|
+
import { SITE } from '@config';
|
|
5
6
|
|
|
6
7
|
// Properties
|
|
7
8
|
type Props = {
|
|
@@ -17,7 +18,7 @@ const _ = Lang(lang);
|
|
|
17
18
|
const categories = frontmatter.categories ?? [];
|
|
18
19
|
const tags = frontmatter.tags ?? [];
|
|
19
20
|
|
|
20
|
-
const links = taxonomyLinks(_);
|
|
21
|
+
const links = Taxonomy.taxonomyLinks(Translations, _, SITE);
|
|
21
22
|
const hasTaxonomy = (categories.length + tags.length) > 0;
|
|
22
23
|
---
|
|
23
24
|
{hasTaxonomy && (
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { PostQueries } from 'astro-accelerator-utils';
|
|
3
3
|
import { SITE, Frontmatter } from '@config';
|
|
4
4
|
import { Translations, Lang } from '@util/Languages';
|
|
5
|
-
import { fetchPages } from '@util/PageQueries';
|
|
6
5
|
import Default from './Default.astro';
|
|
7
6
|
import ArticleList from '@components/ArticleList.astro';
|
|
8
7
|
|
|
@@ -18,7 +17,7 @@ const lang = frontmatter.lang ?? SITE.default.lang;
|
|
|
18
17
|
const _ = Lang(lang);
|
|
19
18
|
|
|
20
19
|
// Logic
|
|
21
|
-
const authorPages = await PostQueries.getPages(
|
|
20
|
+
const authorPages = await PostQueries.getPages(p => p.frontmatter.authors?.indexOf(frontmatter.id) > -1)
|
|
22
21
|
---
|
|
23
22
|
<Default frontmatter={ frontmatter } headings={ headings }>
|
|
24
23
|
<slot />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
import {
|
|
3
|
-
import { getInlineHtmlFrom } from '@util/Markdown';
|
|
2
|
+
import { Markdown } from 'astro-accelerator-utils';
|
|
4
3
|
|
|
4
|
+
import { SITE, Frontmatter } from '@config';
|
|
5
5
|
import Head from '@components/HtmlHead.astro';
|
|
6
6
|
import Header from '@components/Header.astro';
|
|
7
7
|
import Footer from '@components/Footer.astro';
|
|
@@ -22,9 +22,9 @@ const { frontmatter, headings } = Astro.props as Props;
|
|
|
22
22
|
const lang = frontmatter.lang ?? SITE.default.lang;
|
|
23
23
|
const textDirection = frontmatter.dir ?? SITE.default.dir;
|
|
24
24
|
|
|
25
|
-
const title = await getInlineHtmlFrom(frontmatter.title ?? SITE.title);
|
|
25
|
+
const title = await Markdown.getInlineHtmlFrom(frontmatter.title ?? SITE.title);
|
|
26
26
|
const subtitle = frontmatter.subtitle
|
|
27
|
-
? await getInlineHtmlFrom(frontmatter.subtitle)
|
|
27
|
+
? await Markdown.getInlineHtmlFrom(frontmatter.subtitle)
|
|
28
28
|
: null;
|
|
29
29
|
|
|
30
30
|
const site_url = SITE.url;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { PostQueries } from 'astro-accelerator-utils';
|
|
2
|
-
import { fetchPages } from '@util/PageQueries';
|
|
3
|
-
import { mapNavPage, setCurrentPage, popMatchingPage } from '@util/NavPage';
|
|
4
|
-
|
|
5
|
-
import type { NavPage } from '@util/NavigationTypes';
|
|
6
|
-
|
|
7
|
-
export async function getBreadcrumbs (currentUrl: URL) {
|
|
8
|
-
const allPages = await PostQueries.getPages(fetchPages);
|
|
9
|
-
|
|
10
|
-
const pathParts = currentUrl.pathname.split('/');
|
|
11
|
-
const navPages: NavPage[] = [];
|
|
12
|
-
let path = '';
|
|
13
|
-
|
|
14
|
-
pathParts.forEach((part) => {
|
|
15
|
-
path += part.length > 0 ? '/' + part : '';
|
|
16
|
-
const match = popMatchingPage(allPages, path);
|
|
17
|
-
|
|
18
|
-
if (match) {
|
|
19
|
-
navPages.push(mapNavPage(match));
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
setCurrentPage(navPages, currentUrl);
|
|
24
|
-
|
|
25
|
-
return navPages;
|
|
26
|
-
}
|
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
// Data file `navigation.ts`
|
|
2
|
-
import { Cache } from 'astro-accelerator-utils';
|
|
3
|
-
import { menu } from 'src/data/footer';
|
|
4
|
-
import { Translations, Lang, TranslationProvider } from '@util/Languages';
|
|
5
|
-
import { SITE } from '@config';
|
|
6
|
-
import { setCurrentPage } from '@util/NavPage';
|
|
7
|
-
import { NavPage, isNavPage } from '@util/NavigationTypes';
|
|
8
|
-
import { getTaxonomy, taxonomyLinks, TaxonomyLinks } from '@util/Taxonomy';
|
|
9
|
-
|
|
10
|
-
export async function getMenu (currentUrl: URL, lang: string) {
|
|
11
|
-
const key = 'Footer__getMenu_' + lang;
|
|
12
|
-
const _ = Lang(lang);
|
|
13
|
-
const links = taxonomyLinks(_);
|
|
14
|
-
let pages: NavPage[] = await Cache.getItem(key);
|
|
15
|
-
|
|
16
|
-
if (pages == null) {
|
|
17
|
-
pages = [];
|
|
18
|
-
for (let i = 0; i < menu.length; i++) {
|
|
19
|
-
const item = menu[i];
|
|
20
|
-
if (isNavPage(item)) {
|
|
21
|
-
pages.push(item);
|
|
22
|
-
} else {
|
|
23
|
-
switch (item) {
|
|
24
|
-
case 'tags':
|
|
25
|
-
const tags = await getTags(links, _, lang);
|
|
26
|
-
for (let j = 0; j < tags.length; j++) {
|
|
27
|
-
pages.push(tags[j]);
|
|
28
|
-
}
|
|
29
|
-
break;
|
|
30
|
-
case 'toptags':
|
|
31
|
-
const toptags = await getTopTags(links, _, lang);
|
|
32
|
-
for (let j = 0; j < toptags.length; j++) {
|
|
33
|
-
pages.push(toptags[j]);
|
|
34
|
-
}
|
|
35
|
-
break;
|
|
36
|
-
case 'categories':
|
|
37
|
-
const categories = await getCategories(links, _, lang);
|
|
38
|
-
for (let j = 0; j < categories.length; j++) {
|
|
39
|
-
pages.push(categories[j]);
|
|
40
|
-
}
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Cache the result
|
|
47
|
-
await Cache.setItem(key, pages);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
setCurrentPage(pages, currentUrl);
|
|
51
|
-
|
|
52
|
-
return pages;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export async function getCategories (links: TaxonomyLinks, _: TranslationProvider, lang: string) {
|
|
56
|
-
|
|
57
|
-
const key = 'Footer__getCategories_' + lang;
|
|
58
|
-
let pageHierarchy: NavPage[] = await Cache.getItem(key);
|
|
59
|
-
|
|
60
|
-
if (pageHierarchy == null) {
|
|
61
|
-
const category = _(Translations.articles.category) ?? 'category';
|
|
62
|
-
const categoryTitle = _(Translations.articles.category_title) ?? 'Categories';
|
|
63
|
-
const categoryLink = `${SITE.subfolder}/${category}/`;
|
|
64
|
-
|
|
65
|
-
let order = 0;
|
|
66
|
-
|
|
67
|
-
const taxonomy = await getTaxonomy();
|
|
68
|
-
|
|
69
|
-
pageHierarchy = [{
|
|
70
|
-
title: categoryTitle,
|
|
71
|
-
url: categoryLink,
|
|
72
|
-
ariaCurrent: false,
|
|
73
|
-
isOpen: false,
|
|
74
|
-
order: 1,
|
|
75
|
-
children: taxonomy.categories.map(item => {
|
|
76
|
-
return {
|
|
77
|
-
title: item.title,
|
|
78
|
-
url: links.getCategoryLink(item.title),
|
|
79
|
-
ariaCurrent: false,
|
|
80
|
-
isOpen: false,
|
|
81
|
-
order: ++order,
|
|
82
|
-
children: []
|
|
83
|
-
};
|
|
84
|
-
})
|
|
85
|
-
}];
|
|
86
|
-
|
|
87
|
-
// Cache the result
|
|
88
|
-
await Cache.setItem(key, pageHierarchy);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return pageHierarchy;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export async function getTags (links: TaxonomyLinks, _: TranslationProvider, lang: string) {
|
|
95
|
-
|
|
96
|
-
const key = 'Footer__getTags_' + lang;
|
|
97
|
-
let pageHierarchy: NavPage[] = await Cache.getItem(key);
|
|
98
|
-
|
|
99
|
-
if (pageHierarchy == null) {
|
|
100
|
-
const _ = Lang(lang);
|
|
101
|
-
const tag = _(Translations.articles.tag) ?? 'tag';
|
|
102
|
-
const tagTitle = _(Translations.articles.tag_title) ?? 'Tags';
|
|
103
|
-
const tagLink = `${SITE.subfolder}/${tag}/`;
|
|
104
|
-
|
|
105
|
-
let order = 0;
|
|
106
|
-
|
|
107
|
-
const taxonomy = await getTaxonomy();
|
|
108
|
-
|
|
109
|
-
pageHierarchy = [{
|
|
110
|
-
title: tagTitle,
|
|
111
|
-
url: tagLink,
|
|
112
|
-
ariaCurrent: false,
|
|
113
|
-
isOpen: false,
|
|
114
|
-
order: 1,
|
|
115
|
-
children: taxonomy.tags.map(item => {
|
|
116
|
-
return {
|
|
117
|
-
title: item.title,
|
|
118
|
-
url: links.getTagLink(item.title),
|
|
119
|
-
ariaCurrent: false,
|
|
120
|
-
isOpen: false,
|
|
121
|
-
order: ++order,
|
|
122
|
-
children: []
|
|
123
|
-
};
|
|
124
|
-
})
|
|
125
|
-
}];
|
|
126
|
-
|
|
127
|
-
// Cache the result
|
|
128
|
-
await Cache.setItem(key, pageHierarchy);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
return pageHierarchy;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export async function getTopTags (links: TaxonomyLinks, _: TranslationProvider, lang: string) {
|
|
135
|
-
|
|
136
|
-
const key = 'Footer__getTopTags_' + lang;
|
|
137
|
-
let pageHierarchy: NavPage[] = await Cache.getItem(key);
|
|
138
|
-
|
|
139
|
-
if (pageHierarchy == null) {
|
|
140
|
-
const _ = Lang(lang);
|
|
141
|
-
const tag = _(Translations.articles.tag) ?? 'tag';
|
|
142
|
-
const tagTitle = _(Translations.articles.tag_title) ?? 'Tags';
|
|
143
|
-
const tagLink = `${SITE.subfolder}/${tag}/`;
|
|
144
|
-
|
|
145
|
-
let order = 0;
|
|
146
|
-
|
|
147
|
-
const taxonomy = await getTaxonomy();
|
|
148
|
-
|
|
149
|
-
pageHierarchy = [{
|
|
150
|
-
title: tagTitle,
|
|
151
|
-
url: tagLink,
|
|
152
|
-
ariaCurrent: false,
|
|
153
|
-
isOpen: false,
|
|
154
|
-
order: 1,
|
|
155
|
-
children: taxonomy.topTags.map(item => {
|
|
156
|
-
return {
|
|
157
|
-
title: item.title,
|
|
158
|
-
url: links.getTagLink(item.title),
|
|
159
|
-
ariaCurrent: false,
|
|
160
|
-
isOpen: false,
|
|
161
|
-
order: ++order,
|
|
162
|
-
children: []
|
|
163
|
-
};
|
|
164
|
-
})
|
|
165
|
-
}];
|
|
166
|
-
|
|
167
|
-
// Cache the result
|
|
168
|
-
await Cache.setItem(key, pageHierarchy);
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return pageHierarchy;
|
|
172
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { unified } from 'unified';
|
|
2
|
-
import remarkParse from 'remark-parse';
|
|
3
|
-
import remarkRehype from 'remark-rehype'
|
|
4
|
-
import rehypeStringify from 'rehype-stringify';
|
|
5
|
-
|
|
6
|
-
export async function getInlineHtmlFrom(markdown: string): Promise<string> {
|
|
7
|
-
let html = await getHtmlFrom(markdown);
|
|
8
|
-
|
|
9
|
-
// There may be a better way to unwrap this... maybe a visitor
|
|
10
|
-
if (html.substring(0, 3) == '<p>' && html.substring(html.length - 4) == '</p>') {
|
|
11
|
-
html = html.substring(3, html.length - 4);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
return html;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function getHtmlFrom(markdown: string): Promise<string> {
|
|
18
|
-
const vfile = await unified()
|
|
19
|
-
.use(remarkParse)
|
|
20
|
-
.use(remarkRehype)
|
|
21
|
-
.use(rehypeStringify)
|
|
22
|
-
.process(markdown)
|
|
23
|
-
|
|
24
|
-
return String(vfile);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function getTextFrom(markdown: string): Promise<string> {
|
|
28
|
-
const html = await getInlineHtmlFrom(markdown);
|
|
29
|
-
return html.replace(/<.*?>/g, '');
|
|
30
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { SITE } from '@config';
|
|
2
|
-
import type { MarkdownInstance } from 'astro';
|
|
3
|
-
import type { NavPage } from './NavigationTypes';
|
|
4
|
-
|
|
5
|
-
import { Urls } from 'astro-accelerator-utils';
|
|
6
|
-
|
|
7
|
-
export function mapNavPage (page: MarkdownInstance<Record<string, any>>) {
|
|
8
|
-
|
|
9
|
-
let url = page.url == null || (page.url ?? '').length == 0
|
|
10
|
-
? '/'
|
|
11
|
-
: page.url;
|
|
12
|
-
|
|
13
|
-
// Send visitors straight to the first page
|
|
14
|
-
if (page.frontmatter.paged) {
|
|
15
|
-
url += '/1/';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
url = Urls.addSlashToAddress(url, SITE);
|
|
19
|
-
|
|
20
|
-
if (page.frontmatter.layout == 'src/layouts/Redirect.astro') {
|
|
21
|
-
// Skips past the redirect
|
|
22
|
-
url = page.frontmatter.redirect;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const entry: NavPage = {
|
|
26
|
-
section: page.frontmatter.navSection ?? page.frontmatter.navTitle ?? page.frontmatter.title,
|
|
27
|
-
title: page.frontmatter.navTitle ?? page.frontmatter.title,
|
|
28
|
-
url: url,
|
|
29
|
-
order: page.frontmatter.navOrder,
|
|
30
|
-
children: [],
|
|
31
|
-
// These are later set to the correct value, but not now as we want to cache
|
|
32
|
-
isOpen: false,
|
|
33
|
-
ariaCurrent: false,
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
return entry;
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export function setCurrentPage (pages: NavPage[], currentUrl: URL) {
|
|
40
|
-
pages.forEach(p => {
|
|
41
|
-
p.isOpen = currentUrl.pathname.startsWith(p.url);
|
|
42
|
-
p.ariaCurrent = p.url == currentUrl.pathname ? 'page': false;
|
|
43
|
-
if (p.children) setCurrentPage(p.children, currentUrl);
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function popMatchingPage (allPages: MarkdownInstance<Record<string, any>>[], search: string) {
|
|
48
|
-
const numberToRemove = 1;
|
|
49
|
-
let indexToRemove = -1;
|
|
50
|
-
let match = null;
|
|
51
|
-
|
|
52
|
-
for (let i = 0; i < allPages.length; i++) {
|
|
53
|
-
if (allPages[i].url == search) {
|
|
54
|
-
indexToRemove = i;
|
|
55
|
-
match = allPages[i];
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (match) {
|
|
60
|
-
allPages.splice(indexToRemove, numberToRemove);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
return match;
|
|
64
|
-
};
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
// Data file `navigation.ts`
|
|
2
|
-
import { menu } from 'src/data/navigation';
|
|
3
|
-
|
|
4
|
-
import { PostQueries, PostFiltering, Cache } from 'astro-accelerator-utils';
|
|
5
|
-
import { mapNavPage, setCurrentPage } from '@util/NavPage';
|
|
6
|
-
import { NavPage, isNavPage } from '@util/NavigationTypes';
|
|
7
|
-
import { getTopLevelPages, fetchPages } from '@util/PageQueries';
|
|
8
|
-
|
|
9
|
-
export async function getMenu (currentUrl: URL) {
|
|
10
|
-
const key = 'Navigation__getMenu';
|
|
11
|
-
let pages: NavPage[] = await Cache.getItem(key);
|
|
12
|
-
|
|
13
|
-
if (pages == null) {
|
|
14
|
-
pages = [];
|
|
15
|
-
for (let i = 0; i < menu.length; i++) {
|
|
16
|
-
const item = menu[i];
|
|
17
|
-
if (isNavPage(item)) {
|
|
18
|
-
pages.push(item);
|
|
19
|
-
} else {
|
|
20
|
-
const p = await getNavigation(currentUrl);
|
|
21
|
-
for (let j = 0; j < p.length; j++) {
|
|
22
|
-
pages.push(p[j]);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Cache the result
|
|
28
|
-
await Cache.setItem(key, pages);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
setCurrentPage(pages, currentUrl);
|
|
32
|
-
|
|
33
|
-
return pages;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function getNavigation (currentUrl: URL) {
|
|
37
|
-
|
|
38
|
-
const key = 'Navigation__getNavigation';
|
|
39
|
-
let pageHierarchy: NavPage[] = await Cache.getItem(key);
|
|
40
|
-
|
|
41
|
-
if (pageHierarchy == null) {
|
|
42
|
-
const topLevelPages = await getTopLevelPages(PostFiltering.showInMenu);
|
|
43
|
-
const allPages = await PostQueries.getPages(fetchPages, PostFiltering.showInMenu);
|
|
44
|
-
|
|
45
|
-
pageHierarchy = topLevelPages
|
|
46
|
-
.map(mapNavPage)
|
|
47
|
-
.sort((a, b) => a.order - b.order);
|
|
48
|
-
|
|
49
|
-
const pageList: NavPage[] = allPages.map(mapNavPage);
|
|
50
|
-
|
|
51
|
-
for (let i = 0; i < pageHierarchy.length; i++) {
|
|
52
|
-
const page = pageHierarchy[i];
|
|
53
|
-
|
|
54
|
-
if (i > 0) {
|
|
55
|
-
// Don't add children to first link (Home)
|
|
56
|
-
page.children = pageList
|
|
57
|
-
.filter((mp) =>
|
|
58
|
-
page.url != '/'
|
|
59
|
-
&& mp.url != page.url
|
|
60
|
-
&& mp.url.startsWith(page.url)
|
|
61
|
-
)
|
|
62
|
-
.sort((mp) => mp.order);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (page.children.length > 0) {
|
|
66
|
-
const ownChild = structuredClone(page);
|
|
67
|
-
ownChild.order = -1;
|
|
68
|
-
ownChild.children = [];
|
|
69
|
-
page.children.push(ownChild);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Cache the result
|
|
74
|
-
await Cache.setItem(key, pageHierarchy);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return pageHierarchy;
|
|
78
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export type NavPage = {
|
|
2
|
-
section?: string;
|
|
3
|
-
title: string;
|
|
4
|
-
url: string;
|
|
5
|
-
order: number;
|
|
6
|
-
isOpen: boolean;
|
|
7
|
-
ariaCurrent: 'page' | false;
|
|
8
|
-
children: NavPage[];
|
|
9
|
-
rel?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function isNavPage (item: NavPage | 'auto' | 'tags' | 'toptags' | 'categories') : item is NavPage {
|
|
13
|
-
if (typeof item === 'string' && ['auto', 'tags', 'toptags', 'categories'].includes(item)) {
|
|
14
|
-
return false;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return true;
|
|
18
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
export type Link = {
|
|
2
|
-
title: string;
|
|
3
|
-
url: string;
|
|
4
|
-
ariaCurrent: 'page' | false;
|
|
5
|
-
class: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export function getPageLinks(limit: number, numberOfPages: number, currentPage: number, url: string) {
|
|
9
|
-
const pageLinks: Link[] = [];
|
|
10
|
-
|
|
11
|
-
let start = 0;
|
|
12
|
-
let end = numberOfPages;
|
|
13
|
-
|
|
14
|
-
if (numberOfPages > limit) {
|
|
15
|
-
start = (currentPage - (limit - 1) / 2) - 1;
|
|
16
|
-
if (start < 0) {
|
|
17
|
-
start = 0;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
end = (start + limit);
|
|
21
|
-
if (end > numberOfPages) {
|
|
22
|
-
end = numberOfPages;
|
|
23
|
-
start = numberOfPages - limit;
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
if (start == 1) {
|
|
28
|
-
pageLinks.push({
|
|
29
|
-
title: '1',
|
|
30
|
-
url: url.replace('/' + currentPage, '/' + 1),
|
|
31
|
-
ariaCurrent: false,
|
|
32
|
-
class: ''
|
|
33
|
-
});
|
|
34
|
-
} else if (start > 1) {
|
|
35
|
-
pageLinks.push({
|
|
36
|
-
title: '1',
|
|
37
|
-
url: url.replace('/' + currentPage, '/' + 1),
|
|
38
|
-
ariaCurrent: false,
|
|
39
|
-
class: 'paging-collapse-after'
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
for (let i = start; i < end; i++) {
|
|
44
|
-
const userPage = i + 1;
|
|
45
|
-
pageLinks.push({
|
|
46
|
-
title: userPage.toString(),
|
|
47
|
-
url: url.replace('/' + currentPage, '/' + userPage),
|
|
48
|
-
ariaCurrent: userPage == currentPage ? 'page' : false,
|
|
49
|
-
class: ''
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (end < (numberOfPages - 1)) {
|
|
54
|
-
pageLinks.push({
|
|
55
|
-
title: numberOfPages.toString(),
|
|
56
|
-
url: url.replace('/' + currentPage, '/' + numberOfPages),
|
|
57
|
-
ariaCurrent: false,
|
|
58
|
-
class: 'paging-collapse-before'
|
|
59
|
-
});
|
|
60
|
-
} else if (end < numberOfPages) {
|
|
61
|
-
pageLinks.push({
|
|
62
|
-
title: numberOfPages.toString(),
|
|
63
|
-
url: url.replace('/' + currentPage, '/' + numberOfPages),
|
|
64
|
-
ariaCurrent: false,
|
|
65
|
-
class: ''
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return pageLinks;
|
|
70
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import type { MarkdownInstance } from "astro";
|
|
2
|
-
import { SITE } from '@config';
|
|
3
|
-
import { Cache, PostQueries, PostFiltering } from 'astro-accelerator-utils';
|
|
4
|
-
|
|
5
|
-
export function fetchPages(): MarkdownInstance<Record<string, any>>[] {
|
|
6
|
-
return import.meta.glob<any>("../../../pages/**/*.md", { eager: true }) as MarkdownInstance<Record<string, any>>[];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export type PagePredicate = (value: MarkdownInstance<Record<string, any>>, index: number, array: MarkdownInstance<Record<string, any>>[]) => boolean;
|
|
10
|
-
|
|
11
|
-
export async function getTopLevelPages (filter?: PagePredicate | null): Promise<MarkdownInstance<Record<string,any>>[]> {
|
|
12
|
-
const key = 'PageQueries__getTopLevelPages';
|
|
13
|
-
let allPages: MarkdownInstance<Record<string, any>>[] = await Cache.getItem(key);
|
|
14
|
-
|
|
15
|
-
if (allPages == null) {
|
|
16
|
-
allPages = await PostQueries.getPages(fetchPages);
|
|
17
|
-
|
|
18
|
-
const isRoot = SITE.subfolder.length == 0;
|
|
19
|
-
const expectedDepth = isRoot ? 1 : 2;
|
|
20
|
-
allPages = allPages.filter(p => {
|
|
21
|
-
const depth = (p.url ?? '/').split('/').length - 1;
|
|
22
|
-
return depth == expectedDepth
|
|
23
|
-
|| (depth == (expectedDepth - 1) && p.file.includes(SITE.subfolder.toLowerCase() + '.md'));
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
await Cache.setItem(key, allPages);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (filter == null) {
|
|
30
|
-
return allPages;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return allPages.filter(filter);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export async function getAuthorInfo (slug: string) {
|
|
37
|
-
const cacheKey = 'Global__author_info';
|
|
38
|
-
|
|
39
|
-
let authorInfo = await Cache.getItem(cacheKey);
|
|
40
|
-
|
|
41
|
-
if (authorInfo == null) {
|
|
42
|
-
const allPages = await PostQueries.getPages(fetchPages);
|
|
43
|
-
|
|
44
|
-
const author = allPages
|
|
45
|
-
.filter(PostFiltering.isAuthor)
|
|
46
|
-
.filter(x => x.url?.split('/')[2] == slug)[0];
|
|
47
|
-
|
|
48
|
-
authorInfo = {
|
|
49
|
-
frontmatter: author.frontmatter
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
await Cache.setItem(cacheKey, authorInfo);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return authorInfo;
|
|
56
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { Cache, Urls, PostQueries } from 'astro-accelerator-utils';
|
|
2
|
-
import type { Entry } from '@util/Languages';
|
|
3
|
-
import { Translations } from '@util/Languages';
|
|
4
|
-
import { SITE } from '@config';
|
|
5
|
-
import { fetchPages } from '@util/PageQueries';
|
|
6
|
-
import type { MarkdownInstance } from 'astro-accelerator-utils/types/Astro';
|
|
7
|
-
|
|
8
|
-
type TaxonomyEntry = {
|
|
9
|
-
title: string;
|
|
10
|
-
count: number;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
type Taxonomy = {
|
|
14
|
-
tags: TaxonomyEntry[];
|
|
15
|
-
topTags: TaxonomyEntry[];
|
|
16
|
-
categories: TaxonomyEntry[];
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export function sortByTitle (a: TaxonomyEntry, b: TaxonomyEntry) {
|
|
20
|
-
if ( a.title < b.title ){
|
|
21
|
-
return -1;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
if ( a.title > b.title ){
|
|
25
|
-
return 1;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return 0;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type TaxonomyLinks = {
|
|
32
|
-
tag: string;
|
|
33
|
-
category: string;
|
|
34
|
-
getCategoryLink: (category: string) => string;
|
|
35
|
-
getTagLink: (tag: string) => string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function taxonomyLinks(lang: (entry: Entry) => string): TaxonomyLinks {
|
|
39
|
-
const category = lang(Translations.articles.category) ?? 'category';
|
|
40
|
-
const categoryLink = `${SITE.subfolder}/${category}/`;
|
|
41
|
-
|
|
42
|
-
const tag = lang(Translations.articles.tag) ?? 'category';
|
|
43
|
-
const tagLink = `${SITE.subfolder}/${tag}/`;
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
tag: tag,
|
|
47
|
-
category: category,
|
|
48
|
-
getCategoryLink: (category: string) => {
|
|
49
|
-
return Urls.addSlashToAddress(categoryLink + category.toLowerCase().replace(/ /g, '-') + '/1/', SITE);
|
|
50
|
-
},
|
|
51
|
-
getTagLink: (tag: string) => {
|
|
52
|
-
return Urls.addSlashToAddress(tagLink + tag.toLowerCase().replace(/ /g, '-') + '/1/', SITE);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export async function getTaxonomy (): Promise<Taxonomy> {
|
|
59
|
-
const cacheKey = 'Global__taxonomy';
|
|
60
|
-
|
|
61
|
-
let taxonomy: Taxonomy = await Cache.getItem(cacheKey);
|
|
62
|
-
|
|
63
|
-
if (taxonomy == null) {
|
|
64
|
-
const allPages: MarkdownInstance<Record<string, any>>[] = await PostQueries.getPages(fetchPages);
|
|
65
|
-
const tags: { [key: string]: number } = {};
|
|
66
|
-
const cats: { [key: string]: number } = {};
|
|
67
|
-
|
|
68
|
-
// Get taxonomy and counts
|
|
69
|
-
allPages.forEach((p) => {
|
|
70
|
-
p.frontmatter.tags && (p.frontmatter.tags as string[]).forEach(t => {
|
|
71
|
-
tags[t] = (tags[t] ?? 0) + 1;
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
p.frontmatter.categories && (p.frontmatter.categories as string[]).forEach(c => {
|
|
75
|
-
cats[c] = (cats[c] ?? 0) + 1;
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Map into the taxonomy
|
|
80
|
-
taxonomy = {
|
|
81
|
-
tags: Object.keys(tags).sort().map(x => {
|
|
82
|
-
return {
|
|
83
|
-
title: x,
|
|
84
|
-
count: tags[x]
|
|
85
|
-
};
|
|
86
|
-
}),
|
|
87
|
-
topTags: [],
|
|
88
|
-
categories: Object.keys(cats).sort().map(x => {
|
|
89
|
-
return {
|
|
90
|
-
title: x,
|
|
91
|
-
count: cats[x]
|
|
92
|
-
};
|
|
93
|
-
})
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
// Get a list of "top tags" by usage count
|
|
97
|
-
const length = Math.min(taxonomy.categories.length, taxonomy.tags.length);
|
|
98
|
-
taxonomy.topTags = taxonomy.tags
|
|
99
|
-
.sort((a, b) => b.count - a.count)
|
|
100
|
-
.slice(0, length)
|
|
101
|
-
.sort((a, b) => {
|
|
102
|
-
if ( a.title < b.title ){
|
|
103
|
-
return -1;
|
|
104
|
-
}
|
|
105
|
-
if ( a.title > b.title ){
|
|
106
|
-
return 1;
|
|
107
|
-
}
|
|
108
|
-
return 0;
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
await Cache.setItem(cacheKey, taxonomy);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
return taxonomy;
|
|
115
|
-
}
|