astro-accelerator-utils 0.0.33 → 0.0.35

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/index.d.mts CHANGED
@@ -5,5 +5,7 @@ import * as PostPaging from "./lib/postPaging.mjs";
5
5
  import * as Cache from "./lib/cache.mjs";
6
6
  import * as Dates from "./lib/dates.mjs";
7
7
  import * as Markdown from "./lib/markdown.mjs";
8
+ import * as Navigation from "./lib/navigation.mjs";
9
+ import * as Taxonomy from "./lib/taxonomy.mjs";
8
10
  import * as Urls from "./lib/urls.mjs";
9
- export { PostQueries, PostFiltering, PostOrdering, PostPaging, Cache, Dates, Markdown, Urls };
11
+ export { PostQueries, PostFiltering, PostOrdering, PostPaging, Cache, Dates, Markdown, Navigation, Taxonomy, Urls };
package/index.mjs CHANGED
@@ -5,6 +5,8 @@ import * as PostPaging from './lib/postPaging.mjs';
5
5
  import * as Cache from './lib/cache.mjs';
6
6
  import * as Dates from './lib/dates.mjs';
7
7
  import * as Markdown from './lib/markdown.mjs';
8
+ import * as Navigation from './lib/navigation.mjs';
9
+ import * as Taxonomy from './lib/taxonomy.mjs';
8
10
  import * as Urls from './lib/urls.mjs';
9
11
 
10
12
  export {
@@ -15,5 +17,7 @@ export {
15
17
  Cache,
16
18
  Dates,
17
19
  Markdown,
20
+ Navigation,
21
+ Taxonomy,
18
22
  Urls
19
23
  };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * @typedef { import("../types/Site").Site } Site
3
+ * @typedef { import("../types/NavPage").NavPage } NavPage
4
+ */
5
+ /**
6
+ *
7
+ * @param {URL} currentUrl
8
+ * @param {Site} site
9
+ * @returns {Promise<NavPage[]}
10
+ */
11
+ export function getMenu(currentUrl: URL, site: Site): Promise<NavPage[]>;
12
+ /**
13
+ *
14
+ * @param {NavPage | 'auto' | 'tags' | 'toptags' | 'categories'} item
15
+ * @returns {item is NavPage}
16
+ */
17
+ export function isNavPage(item: NavPage | 'auto' | 'tags' | 'toptags' | 'categories'): item is import("../types/NavPage").NavPage;
18
+ /**
19
+ *
20
+ * @param {URL} currentUrl
21
+ * @param {Site} site
22
+ * @returns {Promise<NavPage[]}
23
+ */
24
+ export function getNavigation(currentUrl: URL, site: Site): Promise<NavPage[]>;
25
+ export type Site = import("../types/Site").Site;
26
+ export type NavPage = import("../types/NavPage").NavPage;
@@ -0,0 +1,111 @@
1
+ import * as PostQueries from './postQueries.mjs';
2
+ import * as PostFiltering from './postFiltering.mjs';
3
+ import * as Cache from './cache.mjs';
4
+ import { menu } from '/src/data/navigation';
5
+
6
+ /**
7
+ * @typedef { import("../types/Site").Site } Site
8
+ * @typedef { import("../types/NavPage").NavPage } NavPage
9
+ */
10
+
11
+ /**
12
+ *
13
+ * @param {URL} currentUrl
14
+ * @param {Site} site
15
+ * @returns {Promise<NavPage[]}
16
+ */
17
+ export async function getMenu (currentUrl, site) {
18
+ const key = 'Navigation__getMenu';
19
+
20
+ /** @type {NavPage[]} */
21
+ let pages = await Cache.getItem(key);
22
+
23
+ if (pages == null) {
24
+ pages = [];
25
+ for (let i = 0; i < menu.length; i++) {
26
+ const item = menu[i];
27
+ if (isNavPage(item)) {
28
+ pages.push(item);
29
+ } else {
30
+ const p = await getNavigation(currentUrl, site);
31
+ for (let j = 0; j < p.length; j++) {
32
+ pages.push(p[j]);
33
+ }
34
+ }
35
+ }
36
+
37
+ // Cache the result
38
+ await Cache.setItem(key, pages);
39
+ }
40
+
41
+ PostQueries.setCurrentPage(pages, currentUrl);
42
+
43
+ return pages;
44
+ }
45
+
46
+ /**
47
+ *
48
+ * @param {NavPage | 'auto' | 'tags' | 'toptags' | 'categories'} item
49
+ * @returns {item is NavPage}
50
+ */
51
+ export function isNavPage (item) {
52
+ if (typeof item === 'string' && ['auto', 'tags', 'toptags', 'categories'].includes(item)) {
53
+ return false;
54
+ }
55
+
56
+ return true;
57
+ }
58
+
59
+
60
+ /**
61
+ *
62
+ * @param {URL} currentUrl
63
+ * @param {Site} site
64
+ * @returns {Promise<NavPage[]}
65
+ */
66
+ export async function getNavigation (currentUrl, site) {
67
+
68
+ const key = 'Navigation__getNavigation';
69
+
70
+ /** @type {NavPage[]} */
71
+ let pageHierarchy = await Cache.getItem(key);
72
+
73
+ if (pageHierarchy == null) {
74
+ const topLevelPages = await PostQueries.getTopLevelPages(site, PostFiltering.showInMenu);
75
+ const allPages = await PostQueries.getPages(PostFiltering.showInMenu);
76
+
77
+ pageHierarchy = topLevelPages
78
+ .map(p => PostQueries.mapNavPage(p, site))
79
+ .sort((a, b) => a.order - b.order);
80
+
81
+ /** @type {NavPage[]} */
82
+ const pageList = allPages.map(p => PostQueries.mapNavPage(p, site));
83
+
84
+ for (let i = 0; i < pageHierarchy.length; i++) {
85
+ const page = pageHierarchy[i];
86
+
87
+ if (i > 0) {
88
+ // Don't add children to first link (Home)
89
+ page.children = pageList
90
+ .filter((mp) =>
91
+ page.url != '/'
92
+ && mp.url != page.url
93
+ && mp.url.startsWith(page.url)
94
+ )
95
+ .sort((mp) => mp.order);
96
+ }
97
+
98
+ if (page.children.length > 0) {
99
+ const ownChild = structuredClone(page);
100
+ ownChild.order = -1;
101
+ ownChild.children = [];
102
+ page.children.push(ownChild);
103
+ }
104
+ }
105
+
106
+ // Cache the result
107
+ await Cache.setItem(key, pageHierarchy);
108
+ }
109
+
110
+ return pageHierarchy;
111
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @typedef { import("../types/Taxonomy").Taxonomy } Taxonomy
3
+ * @typedef { import("../types/Taxonomy").TaxonomyEntry } TaxonomyEntry
4
+ * @typedef { import("../types/Taxonomy").TaxonomyLinks } TaxonomyLinks
5
+ * @typedef { import("../types/Astro").MarkdownInstance } MarkdownInstance
6
+ */
7
+ /**
8
+ *
9
+ * @param {TaxonomyEntry} a
10
+ * @param {TaxonomyEntry} b
11
+ * @returns
12
+ */
13
+ export function sortByTitle(a: TaxonomyEntry, b: TaxonomyEntry): 0 | 1 | -1;
14
+ /**
15
+ *
16
+ * @param {any} translations
17
+ * @param {(entry: any) => string} lang
18
+ * @param {Site} site
19
+ * @returns {TaxonomyLinks}
20
+ */
21
+ export function taxonomyLinks(translations: any, lang: (entry: any) => string, site: Site): TaxonomyLinks;
22
+ /**
23
+ *
24
+ * @returns {Promise<Taxonomy}
25
+ */
26
+ export function getTaxonomy(): Promise<Taxonomy>;
27
+ export type Taxonomy = import("../types/Taxonomy").Taxonomy;
28
+ export type TaxonomyEntry = import("../types/Taxonomy").TaxonomyEntry;
29
+ export type TaxonomyLinks = import("../types/Taxonomy").TaxonomyLinks;
30
+ export type MarkdownInstance = import("../types/Astro").MarkdownInstance;
@@ -0,0 +1,121 @@
1
+ import * as Urls from './urls.mjs';
2
+
3
+ /**
4
+ * @typedef { import("../types/Taxonomy").Taxonomy } Taxonomy
5
+ * @typedef { import("../types/Taxonomy").TaxonomyEntry } TaxonomyEntry
6
+ * @typedef { import("../types/Taxonomy").TaxonomyLinks } TaxonomyLinks
7
+ * @typedef { import("../types/Astro").MarkdownInstance } MarkdownInstance
8
+ */
9
+
10
+ /**
11
+ *
12
+ * @param {TaxonomyEntry} a
13
+ * @param {TaxonomyEntry} b
14
+ * @returns
15
+ */
16
+ export function sortByTitle (a, b) {
17
+ if ( a.title < b.title ){
18
+ return -1;
19
+ }
20
+
21
+ if ( a.title > b.title ){
22
+ return 1;
23
+ }
24
+
25
+ return 0;
26
+ }
27
+
28
+ /**
29
+ *
30
+ * @param {any} translations
31
+ * @param {(entry: any) => string} lang
32
+ * @param {Site} site
33
+ * @returns {TaxonomyLinks}
34
+ */
35
+ export function taxonomyLinks(translations, lang, site) {
36
+ const category = lang(translations.articles.category) ?? 'category';
37
+ const categoryLink = `${site.subfolder}/${category}/`;
38
+
39
+ const tag = lang(translations.articles.tag) ?? 'category';
40
+ const tagLink = `${site.subfolder}/${tag}/`;
41
+
42
+ return {
43
+ tag: tag,
44
+ category: category,
45
+ getCategoryLink: (category) => {
46
+ return Urls.addSlashToAddress(categoryLink + category.toLowerCase().replace(/ /g, '-') + '/1/', site);
47
+ },
48
+ getTagLink: (tag) => {
49
+ return Urls.addSlashToAddress(tagLink + tag.toLowerCase().replace(/ /g, '-') + '/1/', site);
50
+ }
51
+ };
52
+ }
53
+
54
+ /**
55
+ *
56
+ * @returns {Promise<Taxonomy}
57
+ */
58
+ export async function getTaxonomy () {
59
+ const cacheKey = 'Global__taxonomy';
60
+
61
+ /** @type {Taxonomy} */
62
+ let taxonomy = await Cache.getItem(cacheKey);
63
+
64
+ if (taxonomy == null) {
65
+ /** @type {MarkdownInstance[]} */
66
+ const allPages = await PostQueries.getPages();
67
+
68
+ /** @type {{ [key: string]: number }} */
69
+ const tags = {};
70
+
71
+ /** @type {{ [key: string]: number }} */
72
+ const cats = {};
73
+
74
+ // Get taxonomy and counts
75
+ allPages.forEach((p) => {
76
+ p.frontmatter.tags && (p.frontmatter.tags).forEach(t => {
77
+ tags[t] = (tags[t] ?? 0) + 1;
78
+ });
79
+
80
+ p.frontmatter.categories && (p.frontmatter.categories).forEach(c => {
81
+ cats[c] = (cats[c] ?? 0) + 1;
82
+ });
83
+ });
84
+
85
+ // Map into the taxonomy
86
+ taxonomy = {
87
+ tags: Object.keys(tags).sort().map(x => {
88
+ return {
89
+ title: x,
90
+ count: tags[x]
91
+ };
92
+ }),
93
+ topTags: [],
94
+ categories: Object.keys(cats).sort().map(x => {
95
+ return {
96
+ title: x,
97
+ count: cats[x]
98
+ };
99
+ })
100
+ };
101
+
102
+ // Get a list of "top tags" by usage count
103
+ const length = Math.min(taxonomy.categories.length, taxonomy.tags.length);
104
+ taxonomy.topTags = taxonomy.tags
105
+ .sort((a, b) => b.count - a.count)
106
+ .slice(0, length)
107
+ .sort((a, b) => {
108
+ if ( a.title < b.title ){
109
+ return -1;
110
+ }
111
+ if ( a.title > b.title ){
112
+ return 1;
113
+ }
114
+ return 0;
115
+ });
116
+
117
+ await Cache.setItem(cacheKey, taxonomy);
118
+ }
119
+
120
+ return taxonomy;
121
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro-accelerator-utils",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "description": "Astro utilities for Astro Accelerator.",
5
5
  "main": "index.mjs",
6
6
  "files": [
@@ -0,0 +1,15 @@
1
+ export interface TaxonomyEntry {
2
+ title: string;
3
+ count: number;
4
+ }
5
+ export interface Taxonomy {
6
+ tags: TaxonomyEntry[];
7
+ topTags: TaxonomyEntry[];
8
+ categories: TaxonomyEntry[];
9
+ }
10
+ export interface TaxonomyLinks {
11
+ tag: string;
12
+ category: string;
13
+ getCategoryLink: (category: string) => string;
14
+ getTagLink: (tag: string) => string;
15
+ }