@turnipxenon/pineapple 2.4.37 → 2.4.38
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/.idea/shelf/Changes1/shelved.patch +250 -0
- package/.idea/shelf/Changes1.xml +4 -0
- package/.idea/shelf/yarn_scripts/shelved.patch +20 -0
- package/.idea/workspace.xml +46 -46
- package/.svelte-kit/__package__/components/Card.svelte +3 -1
- package/.svelte-kit/__package__/components/Card.svelte.d.ts +1 -0
- package/.svelte-kit/__package__/components/dialog_overlay/DialogOverlay.svelte +9 -11
- package/.svelte-kit/__package__/components/navigation_component/NavigationComponent.svelte +240 -238
- package/.svelte-kit/__package__/components/navigation_component/NavigationControl.svelte +89 -89
- package/.svelte-kit/__package__/components/pineapple/PineappleBaseLayout.svelte +4 -4
- package/.svelte-kit/ambient.d.ts +2 -2
- package/.svelte-kit/generated/server/internal.js +1 -1
- package/dist/components/Card.svelte +3 -1
- package/dist/components/Card.svelte.d.ts +1 -0
- package/dist/components/dialog_overlay/DialogOverlay.svelte +9 -11
- package/dist/components/navigation_component/NavigationComponent.svelte +240 -238
- package/dist/components/navigation_component/NavigationControl.svelte +89 -89
- package/dist/components/pineapple/PineappleBaseLayout.svelte +4 -4
- package/package.json +3 -2
- package/src/lib/components/Card.svelte +4 -1
- package/src/lib/components/dialog_overlay/DialogOverlay.svelte +11 -12
- package/src/lib/components/navigation_component/NavigationComponent.svelte +145 -143
- package/src/lib/components/navigation_component/NavigationControl.svelte +60 -60
- package/src/lib/components/navigation_component/PageMeta.ts +205 -205
- package/src/lib/components/pineapple/PineappleBaseLayout.svelte +4 -4
- package/src/routes/(pineapple)/+layout.svelte +1 -1
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page1/+page.svelte +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page1/meta.json +23 -23
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page2/+page.svelte +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page2/meta.json +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page3/+page.svelte +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page3/page5/+page.svelte +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page3/page5/meta.json +6 -6
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page3/page6/+page.svelte +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page3/page7/(test_layout)/page8/+page.svelte +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page3/page7/(test_layout)/page8/meta.json +6 -6
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page3/page7/+page.svelte +7 -7
- package/src/routes/(pineapple)/pineapple/(extra-pages)/page4/+page.svelte +6 -6
- package/src/routes/(pineapple)/pineapple/(pineapple)/+page.svelte +24 -29
- package/src/routes/(pineapple)/pineapple/{(extra-pages) → (pineapple)}/ImageMap.ts +5 -5
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { onMount } from "svelte";
|
|
3
|
-
|
|
4
|
-
export let currentIndex = 0;
|
|
5
|
-
export let contentLength: number;
|
|
6
|
-
export let pageSize: number;
|
|
7
|
-
|
|
8
|
-
import { Card } from "$pkg";
|
|
9
|
-
import { page } from "$app/stores";
|
|
10
|
-
import { goto } from "$app/navigation";
|
|
11
|
-
|
|
12
|
-
const queryIndex = $page.url.searchParams.get("index");
|
|
13
|
-
if (queryIndex) {
|
|
14
|
-
currentIndex = parseInt(queryIndex) || 0;
|
|
15
|
-
}
|
|
16
|
-
const queryPageSize = $page.url.searchParams.get("pageSize");
|
|
17
|
-
if (queryPageSize) {
|
|
18
|
-
pageSize = parseInt(queryPageSize) || 5;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const movePage = (isNext: boolean) => {
|
|
22
|
-
if (isNext) {
|
|
23
|
-
currentIndex = currentIndex + 1;
|
|
24
|
-
} else {
|
|
25
|
-
currentIndex = currentIndex - 1;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const query = new URLSearchParams($page.url.searchParams.toString());
|
|
29
|
-
query.set("index", currentIndex.toString());
|
|
30
|
-
goto(`?${query.toString()}`);
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
onMount(() => {
|
|
34
|
-
const query = new URLSearchParams($page.url.searchParams.toString());
|
|
35
|
-
query.set("index", currentIndex.toString());
|
|
36
|
-
query.set("pageSize", pageSize.toString());
|
|
37
|
-
goto(`?${query.toString()}`);
|
|
38
|
-
});
|
|
39
|
-
</script>
|
|
40
|
-
|
|
41
|
-
<div class="navigation-control-container">
|
|
42
|
-
<button class="navigation-control-button"
|
|
43
|
-
disabled={currentIndex <= 0}
|
|
44
|
-
on:click={() => {movePage(false)}}>{"<"}</button>
|
|
45
|
-
<Card marginBottom="0"><p slot="content" style="margin: 1em">Page {currentIndex + 1}</p></Card>
|
|
46
|
-
<button class="navigation-control-button"
|
|
47
|
-
disabled={(currentIndex + 1) * pageSize >= contentLength}
|
|
48
|
-
on:click={() => {movePage(true)}}>{">"}</button>
|
|
49
|
-
</div>
|
|
50
|
-
|
|
51
|
-
<style lang="postcss">
|
|
52
|
-
.navigation-control-container {
|
|
53
|
-
display: flex;
|
|
54
|
-
justify-content: space-between;
|
|
55
|
-
margin: 1lh 0;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.navigation-control-button {
|
|
59
|
-
@apply btn variant-filled-secondary;
|
|
60
|
-
}
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { onMount } from "svelte";
|
|
3
|
+
|
|
4
|
+
export let currentIndex = 0;
|
|
5
|
+
export let contentLength: number;
|
|
6
|
+
export let pageSize: number;
|
|
7
|
+
|
|
8
|
+
import { Card } from "$pkg";
|
|
9
|
+
import { page } from "$app/stores";
|
|
10
|
+
import { goto } from "$app/navigation";
|
|
11
|
+
|
|
12
|
+
const queryIndex = $page.url.searchParams.get("index");
|
|
13
|
+
if (queryIndex) {
|
|
14
|
+
currentIndex = parseInt(queryIndex) || 0;
|
|
15
|
+
}
|
|
16
|
+
const queryPageSize = $page.url.searchParams.get("pageSize");
|
|
17
|
+
if (queryPageSize) {
|
|
18
|
+
pageSize = parseInt(queryPageSize) || 5;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const movePage = (isNext: boolean) => {
|
|
22
|
+
if (isNext) {
|
|
23
|
+
currentIndex = currentIndex + 1;
|
|
24
|
+
} else {
|
|
25
|
+
currentIndex = currentIndex - 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const query = new URLSearchParams($page.url.searchParams.toString());
|
|
29
|
+
query.set("index", currentIndex.toString());
|
|
30
|
+
goto(`?${query.toString()}`);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
onMount(() => {
|
|
34
|
+
const query = new URLSearchParams($page.url.searchParams.toString());
|
|
35
|
+
query.set("index", currentIndex.toString());
|
|
36
|
+
query.set("pageSize", pageSize.toString());
|
|
37
|
+
goto(`?${query.toString()}`);
|
|
38
|
+
});
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<div class="navigation-control-container">
|
|
42
|
+
<button class="navigation-control-button"
|
|
43
|
+
disabled={currentIndex <= 0}
|
|
44
|
+
on:click={() => {movePage(false)}}>{"<"}</button>
|
|
45
|
+
<Card marginBottom="0"><p slot="content" style="margin: 1em">Page {currentIndex + 1}</p></Card>
|
|
46
|
+
<button class="navigation-control-button"
|
|
47
|
+
disabled={(currentIndex + 1) * pageSize >= contentLength}
|
|
48
|
+
on:click={() => {movePage(true)}}>{">"}</button>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<style lang="postcss">
|
|
52
|
+
.navigation-control-container {
|
|
53
|
+
display: flex;
|
|
54
|
+
justify-content: space-between;
|
|
55
|
+
margin: 1lh 0;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.navigation-control-button {
|
|
59
|
+
@apply btn variant-filled-secondary;
|
|
60
|
+
}
|
|
61
61
|
</style>
|
|
@@ -1,206 +1,206 @@
|
|
|
1
|
-
import type { RawGlob } from "$pkg/util/util";
|
|
2
|
-
|
|
3
|
-
export interface PageMeta {
|
|
4
|
-
datePublished?: string;
|
|
5
|
-
description?: string;
|
|
6
|
-
|
|
7
|
-
imageAlt?: string; // defaults to directory name
|
|
8
|
-
/**
|
|
9
|
-
* imageID is an ID that NavigationComponent can use to identify imported images
|
|
10
|
-
*
|
|
11
|
-
* To use imageID:
|
|
12
|
-
* 1. Add the imageID entry to the meta.json for the page
|
|
13
|
-
* 2. Create a typescript file with the variable ImageMap: Map<string, string>
|
|
14
|
-
* 3. Add a new entry with your imageID as key, and the image url as the value. Since this is
|
|
15
|
-
* Typescript, you can use import ImageUrl from "./path.png" as you would normally do.
|
|
16
|
-
* 4. Add ImageMap as an argument to your NavigationComponent.
|
|
17
|
-
* Overall, this involves four files
|
|
18
|
-
* - Your navigation page: ./+page.svelte
|
|
19
|
-
* - Your image map typescript: ImageMap.ts
|
|
20
|
-
* - The page you want with an image represented in the navigation: ./topic1/+page.svelte
|
|
21
|
-
* - The meta for that page: ./topic1/meta.json
|
|
22
|
-
*
|
|
23
|
-
* imageID takes precedence over imageURL
|
|
24
|
-
*/
|
|
25
|
-
imageID?: string;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* imageURL is only limited to absolute paths (includes files in static folder)
|
|
29
|
-
*
|
|
30
|
-
* if imageID is defined, this will be ignored
|
|
31
|
-
*/
|
|
32
|
-
imageUrl?: string;
|
|
33
|
-
|
|
34
|
-
lastUpdated?: string;
|
|
35
|
-
nestedPages: PageMeta[];
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* relativeLink is generated automatically. This will be ignored in meta.json.
|
|
39
|
-
*/
|
|
40
|
-
relativeLink: string;
|
|
41
|
-
shouldGroup?: boolean;
|
|
42
|
-
shouldHide?: boolean;
|
|
43
|
-
tags: string[];
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* title defaults to the directory name if it's an empty string.
|
|
47
|
-
*/
|
|
48
|
-
title: string;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* todo: doc
|
|
53
|
-
* @param parentList
|
|
54
|
-
* @param child
|
|
55
|
-
*/
|
|
56
|
-
export const findPageMetaParent = (parentList: PageMeta[], child: PageMeta): boolean => {
|
|
57
|
-
let isChild = false;
|
|
58
|
-
|
|
59
|
-
parentList.every(parent => {
|
|
60
|
-
if (child.relativeLink.startsWith(`${parent.relativeLink}/`)) {
|
|
61
|
-
const isNestedChild = findPageMetaParent(parent.nestedPages, child);
|
|
62
|
-
if (!isNestedChild) {
|
|
63
|
-
parent.nestedPages.push(child);
|
|
64
|
-
}
|
|
65
|
-
isChild = true;
|
|
66
|
-
return false;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return true;
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
return isChild;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export type ParsePageMetaCompareFn = ((a: PageMeta, b: PageMeta) => number);
|
|
76
|
-
|
|
77
|
-
export const parsePageMeta = (fileList: Record<string, unknown>,
|
|
78
|
-
jsonList: Record<string, unknown>,
|
|
79
|
-
imageMap: Map<string, string>,
|
|
80
|
-
compareFn?: ParsePageMetaCompareFn): PageMeta[] => {
|
|
81
|
-
const pageFlatList: PageMeta[] = [];
|
|
82
|
-
// save for the future
|
|
83
|
-
// let pageGroupedList: PageMeta[] = [];
|
|
84
|
-
const jsonMap = new Map<string, { [k: string]: unknown }>();
|
|
85
|
-
Object.keys(jsonList).forEach(path => {
|
|
86
|
-
const pathEnd = path.split("../").pop() as string;
|
|
87
|
-
const pathParts = pathEnd.split("/");
|
|
88
|
-
pathParts.pop();
|
|
89
|
-
|
|
90
|
-
// get url path
|
|
91
|
-
const subPath = pathParts.filter(s => {
|
|
92
|
-
return s !== "." && s.indexOf("(") !== 0;
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
try {
|
|
96
|
-
jsonMap.set(subPath.join("/"), JSON.parse((jsonList[path] as RawGlob).default));
|
|
97
|
-
} catch (e) {
|
|
98
|
-
console.error(`Error parsing json at: ${path}: ${e}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
for (const path in fileList) {
|
|
104
|
-
const pathEnd = path.split("../").pop() as string;
|
|
105
|
-
const pathParts = pathEnd.split("/");
|
|
106
|
-
pathParts.pop();
|
|
107
|
-
|
|
108
|
-
// get title
|
|
109
|
-
const title = pathParts[pathParts.length - 1].replaceAll("-", " ");
|
|
110
|
-
|
|
111
|
-
// get url path
|
|
112
|
-
const subPath = pathParts.filter(s => {
|
|
113
|
-
return s !== "." && s.indexOf("(") !== 0;
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// todo: consider
|
|
118
|
-
// subPath.unshift("/misc");
|
|
119
|
-
const meta: PageMeta = {
|
|
120
|
-
relativeLink: subPath.join("/"),
|
|
121
|
-
title,
|
|
122
|
-
tags: [],
|
|
123
|
-
nestedPages: []
|
|
124
|
-
// todo: transform the data in server.ts?
|
|
125
|
-
};
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
const metadata = jsonMap.get(meta.relativeLink);
|
|
129
|
-
if (metadata) {
|
|
130
|
-
meta.title = metadata["title"] as string ?? meta.title;
|
|
131
|
-
meta.tags = metadata["tags"] as string[] ?? [];
|
|
132
|
-
meta.description = metadata["description"] as string;
|
|
133
|
-
meta.datePublished = metadata["datePublished"] as string;
|
|
134
|
-
meta.lastUpdated = metadata["lastUpdated"] as string;
|
|
135
|
-
meta.shouldGroup = metadata["shouldGroup"] as boolean;
|
|
136
|
-
meta.shouldHide = metadata["shouldHide"] as boolean;
|
|
137
|
-
|
|
138
|
-
meta.imageID = metadata["imageID"] as string;
|
|
139
|
-
meta.imageUrl = imageMap.get(meta.imageID) ?? metadata["imageUrl"] as string;
|
|
140
|
-
|
|
141
|
-
if (meta.imageUrl) {
|
|
142
|
-
meta.imageAlt = metadata["imageAlt"] as string;
|
|
143
|
-
if (!meta.imageAlt) {
|
|
144
|
-
console.warn(`Accessibility issues: image alt missing for image ${meta.imageUrl}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (meta.shouldHide) {
|
|
150
|
-
continue;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
pageFlatList.push(meta);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
pageFlatList.sort((a, b) => a.relativeLink.localeCompare(b.relativeLink));
|
|
157
|
-
|
|
158
|
-
// find groupings
|
|
159
|
-
// grouping should be BEFORE the external sort
|
|
160
|
-
// todo: we don't even have use for this yet!
|
|
161
|
-
// pageFlatList.forEach(p => {
|
|
162
|
-
// if (!findPageMetaParent(pageGroupedList, p)) {
|
|
163
|
-
// pageGroupedList.push(p);
|
|
164
|
-
// }
|
|
165
|
-
// });
|
|
166
|
-
|
|
167
|
-
if (compareFn) {
|
|
168
|
-
pageFlatList.sort(compareFn);
|
|
169
|
-
} else {
|
|
170
|
-
pageFlatList.sort(DefaultPageMetaSorter);
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
return pageFlatList;
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
const AWins = -1;
|
|
177
|
-
const BWins = 1;
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* Prioritizes, in order, recently lastUpdated or datePublished, has description, then title
|
|
181
|
-
*
|
|
182
|
-
* @param a
|
|
183
|
-
* @param b
|
|
184
|
-
* @constructor
|
|
185
|
-
*/
|
|
186
|
-
export const DefaultPageMetaSorter: ParsePageMetaCompareFn = (a, b) => {
|
|
187
|
-
const aDate = a.lastUpdated || a.datePublished;
|
|
188
|
-
const bDate = b.lastUpdated || b.datePublished;
|
|
189
|
-
|
|
190
|
-
if (aDate && !bDate) {
|
|
191
|
-
return AWins;
|
|
192
|
-
} else if (!aDate && bDate) {
|
|
193
|
-
return BWins;
|
|
194
|
-
} else if (aDate && bDate) {
|
|
195
|
-
// we invert the value because we want the dates to be in descending order
|
|
196
|
-
return -aDate.localeCompare(bDate);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
if (a.description && !b.description) {
|
|
200
|
-
return AWins;
|
|
201
|
-
} else if (!a.description && b.description) {
|
|
202
|
-
return BWins;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return a.title.localeCompare(b.title);
|
|
1
|
+
import type { RawGlob } from "$pkg/util/util";
|
|
2
|
+
|
|
3
|
+
export interface PageMeta {
|
|
4
|
+
datePublished?: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
|
|
7
|
+
imageAlt?: string; // defaults to directory name
|
|
8
|
+
/**
|
|
9
|
+
* imageID is an ID that NavigationComponent can use to identify imported images
|
|
10
|
+
*
|
|
11
|
+
* To use imageID:
|
|
12
|
+
* 1. Add the imageID entry to the meta.json for the page
|
|
13
|
+
* 2. Create a typescript file with the variable ImageMap: Map<string, string>
|
|
14
|
+
* 3. Add a new entry with your imageID as key, and the image url as the value. Since this is
|
|
15
|
+
* Typescript, you can use import ImageUrl from "./path.png" as you would normally do.
|
|
16
|
+
* 4. Add ImageMap as an argument to your NavigationComponent.
|
|
17
|
+
* Overall, this involves four files
|
|
18
|
+
* - Your navigation page: ./+page.svelte
|
|
19
|
+
* - Your image map typescript: ImageMap.ts
|
|
20
|
+
* - The page you want with an image represented in the navigation: ./topic1/+page.svelte
|
|
21
|
+
* - The meta for that page: ./topic1/meta.json
|
|
22
|
+
*
|
|
23
|
+
* imageID takes precedence over imageURL
|
|
24
|
+
*/
|
|
25
|
+
imageID?: string;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* imageURL is only limited to absolute paths (includes files in static folder)
|
|
29
|
+
*
|
|
30
|
+
* if imageID is defined, this will be ignored
|
|
31
|
+
*/
|
|
32
|
+
imageUrl?: string;
|
|
33
|
+
|
|
34
|
+
lastUpdated?: string;
|
|
35
|
+
nestedPages: PageMeta[];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* relativeLink is generated automatically. This will be ignored in meta.json.
|
|
39
|
+
*/
|
|
40
|
+
relativeLink: string;
|
|
41
|
+
shouldGroup?: boolean;
|
|
42
|
+
shouldHide?: boolean;
|
|
43
|
+
tags: string[];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* title defaults to the directory name if it's an empty string.
|
|
47
|
+
*/
|
|
48
|
+
title: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* todo: doc
|
|
53
|
+
* @param parentList
|
|
54
|
+
* @param child
|
|
55
|
+
*/
|
|
56
|
+
export const findPageMetaParent = (parentList: PageMeta[], child: PageMeta): boolean => {
|
|
57
|
+
let isChild = false;
|
|
58
|
+
|
|
59
|
+
parentList.every(parent => {
|
|
60
|
+
if (child.relativeLink.startsWith(`${parent.relativeLink}/`)) {
|
|
61
|
+
const isNestedChild = findPageMetaParent(parent.nestedPages, child);
|
|
62
|
+
if (!isNestedChild) {
|
|
63
|
+
parent.nestedPages.push(child);
|
|
64
|
+
}
|
|
65
|
+
isChild = true;
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return true;
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return isChild;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export type ParsePageMetaCompareFn = ((a: PageMeta, b: PageMeta) => number);
|
|
76
|
+
|
|
77
|
+
export const parsePageMeta = (fileList: Record<string, unknown>,
|
|
78
|
+
jsonList: Record<string, unknown>,
|
|
79
|
+
imageMap: Map<string, string>,
|
|
80
|
+
compareFn?: ParsePageMetaCompareFn): PageMeta[] => {
|
|
81
|
+
const pageFlatList: PageMeta[] = [];
|
|
82
|
+
// save for the future
|
|
83
|
+
// let pageGroupedList: PageMeta[] = [];
|
|
84
|
+
const jsonMap = new Map<string, { [k: string]: unknown }>();
|
|
85
|
+
Object.keys(jsonList).forEach(path => {
|
|
86
|
+
const pathEnd = path.split("../").pop() as string;
|
|
87
|
+
const pathParts = pathEnd.split("/");
|
|
88
|
+
pathParts.pop();
|
|
89
|
+
|
|
90
|
+
// get url path
|
|
91
|
+
const subPath = pathParts.filter(s => {
|
|
92
|
+
return s !== "." && s.indexOf("(") !== 0;
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
jsonMap.set(subPath.join("/"), JSON.parse((jsonList[path] as RawGlob).default));
|
|
97
|
+
} catch (e) {
|
|
98
|
+
console.error(`Error parsing json at: ${path}: ${e}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
for (const path in fileList) {
|
|
104
|
+
const pathEnd = path.split("../").pop() as string;
|
|
105
|
+
const pathParts = pathEnd.split("/");
|
|
106
|
+
pathParts.pop();
|
|
107
|
+
|
|
108
|
+
// get title
|
|
109
|
+
const title = pathParts[pathParts.length - 1].replaceAll("-", " ");
|
|
110
|
+
|
|
111
|
+
// get url path
|
|
112
|
+
const subPath = pathParts.filter(s => {
|
|
113
|
+
return s !== "." && s.indexOf("(") !== 0;
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
// todo: consider
|
|
118
|
+
// subPath.unshift("/misc");
|
|
119
|
+
const meta: PageMeta = {
|
|
120
|
+
relativeLink: subPath.join("/"),
|
|
121
|
+
title,
|
|
122
|
+
tags: [],
|
|
123
|
+
nestedPages: []
|
|
124
|
+
// todo: transform the data in server.ts?
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
const metadata = jsonMap.get(meta.relativeLink);
|
|
129
|
+
if (metadata) {
|
|
130
|
+
meta.title = metadata["title"] as string ?? meta.title;
|
|
131
|
+
meta.tags = metadata["tags"] as string[] ?? [];
|
|
132
|
+
meta.description = metadata["description"] as string;
|
|
133
|
+
meta.datePublished = metadata["datePublished"] as string;
|
|
134
|
+
meta.lastUpdated = metadata["lastUpdated"] as string;
|
|
135
|
+
meta.shouldGroup = metadata["shouldGroup"] as boolean;
|
|
136
|
+
meta.shouldHide = metadata["shouldHide"] as boolean;
|
|
137
|
+
|
|
138
|
+
meta.imageID = metadata["imageID"] as string;
|
|
139
|
+
meta.imageUrl = imageMap.get(meta.imageID) ?? metadata["imageUrl"] as string;
|
|
140
|
+
|
|
141
|
+
if (meta.imageUrl) {
|
|
142
|
+
meta.imageAlt = metadata["imageAlt"] as string;
|
|
143
|
+
if (!meta.imageAlt) {
|
|
144
|
+
console.warn(`Accessibility issues: image alt missing for image ${meta.imageUrl}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (meta.shouldHide) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
pageFlatList.push(meta);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
pageFlatList.sort((a, b) => a.relativeLink.localeCompare(b.relativeLink));
|
|
157
|
+
|
|
158
|
+
// find groupings
|
|
159
|
+
// grouping should be BEFORE the external sort
|
|
160
|
+
// todo: we don't even have use for this yet!
|
|
161
|
+
// pageFlatList.forEach(p => {
|
|
162
|
+
// if (!findPageMetaParent(pageGroupedList, p)) {
|
|
163
|
+
// pageGroupedList.push(p);
|
|
164
|
+
// }
|
|
165
|
+
// });
|
|
166
|
+
|
|
167
|
+
if (compareFn) {
|
|
168
|
+
pageFlatList.sort(compareFn);
|
|
169
|
+
} else {
|
|
170
|
+
pageFlatList.sort(DefaultPageMetaSorter);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return pageFlatList;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const AWins = -1;
|
|
177
|
+
const BWins = 1;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Prioritizes, in order, recently lastUpdated or datePublished, has description, then title
|
|
181
|
+
*
|
|
182
|
+
* @param a
|
|
183
|
+
* @param b
|
|
184
|
+
* @constructor
|
|
185
|
+
*/
|
|
186
|
+
export const DefaultPageMetaSorter: ParsePageMetaCompareFn = (a, b) => {
|
|
187
|
+
const aDate = a.lastUpdated || a.datePublished;
|
|
188
|
+
const bDate = b.lastUpdated || b.datePublished;
|
|
189
|
+
|
|
190
|
+
if (aDate && !bDate) {
|
|
191
|
+
return AWins;
|
|
192
|
+
} else if (!aDate && bDate) {
|
|
193
|
+
return BWins;
|
|
194
|
+
} else if (aDate && bDate) {
|
|
195
|
+
// we invert the value because we want the dates to be in descending order
|
|
196
|
+
return -aDate.localeCompare(bDate);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (a.description && !b.description) {
|
|
200
|
+
return AWins;
|
|
201
|
+
} else if (!a.description && b.description) {
|
|
202
|
+
return BWins;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return a.title.localeCompare(b.title);
|
|
206
206
|
};
|
|
@@ -149,8 +149,8 @@
|
|
|
149
149
|
|
|
150
150
|
.default-page-container {
|
|
151
151
|
@apply flex justify-center items-center;
|
|
152
|
-
|
|
153
|
-
|
|
152
|
+
width: 100%;
|
|
153
|
+
padding: 1lh clamp(8px, 10vw, 2em);
|
|
154
154
|
flex-direction: column;
|
|
155
155
|
z-index: 0;
|
|
156
156
|
}
|
|
@@ -201,7 +201,7 @@
|
|
|
201
201
|
bottom: var(--fab-margin);
|
|
202
202
|
width: 4em;
|
|
203
203
|
border-radius: 50%;
|
|
204
|
-
|
|
204
|
+
z-index: 100;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
.fab > img {
|
|
@@ -217,6 +217,6 @@
|
|
|
217
217
|
}
|
|
218
218
|
|
|
219
219
|
.turnip-icon {
|
|
220
|
-
|
|
220
|
+
margin: 4px;
|
|
221
221
|
}
|
|
222
222
|
</style>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { Card } from "$pkg";
|
|
3
|
-
import { page } from "$app/stores";
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<Card>
|
|
7
|
-
<h1 slot="content" class="default-card">{$page.url}</h1>
|
|
1
|
+
<script>
|
|
2
|
+
import { Card } from "$pkg";
|
|
3
|
+
import { page } from "$app/stores";
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<Card>
|
|
7
|
+
<h1 slot="content" class="default-card">{$page.url}</h1>
|
|
8
8
|
</Card>
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
{
|
|
2
|
-
"datePublished": "2023-01-01",
|
|
3
|
-
"description": "random description but look at Ares! Let's try out a long-ish text to see how things would wrap and all that. I don't know what else to say. Please stream Umpah Umpah.",
|
|
4
|
-
"imageAlt": "Image of Ares being excited",
|
|
5
|
-
"imageID": "testImageID",
|
|
6
|
-
"imageURL": "./favicon.png/?q=imageIDTakesPrecedence",
|
|
7
|
-
"lastUpdated": "2023-02-02",
|
|
8
|
-
"shouldGroup": false,
|
|
9
|
-
"shouldHide": false,
|
|
10
|
-
"tags": [
|
|
11
|
-
"random",
|
|
12
|
-
"random8",
|
|
13
|
-
"random2",
|
|
14
|
-
"random5",
|
|
15
|
-
"random5",
|
|
16
|
-
"random5",
|
|
17
|
-
"random5",
|
|
18
|
-
"random5",
|
|
19
|
-
"random5",
|
|
20
|
-
"random5",
|
|
21
|
-
"random4"
|
|
22
|
-
],
|
|
23
|
-
"title": "Custom title for page 1!!!"
|
|
1
|
+
{
|
|
2
|
+
"datePublished": "2023-01-01",
|
|
3
|
+
"description": "random description but look at Ares! Let's try out a long-ish text to see how things would wrap and all that. I don't know what else to say. Please stream Umpah Umpah.",
|
|
4
|
+
"imageAlt": "Image of Ares being excited",
|
|
5
|
+
"imageID": "testImageID",
|
|
6
|
+
"imageURL": "./favicon.png/?q=imageIDTakesPrecedence",
|
|
7
|
+
"lastUpdated": "2023-02-02",
|
|
8
|
+
"shouldGroup": false,
|
|
9
|
+
"shouldHide": false,
|
|
10
|
+
"tags": [
|
|
11
|
+
"random",
|
|
12
|
+
"random8",
|
|
13
|
+
"random2",
|
|
14
|
+
"random5",
|
|
15
|
+
"random5",
|
|
16
|
+
"random5",
|
|
17
|
+
"random5",
|
|
18
|
+
"random5",
|
|
19
|
+
"random5",
|
|
20
|
+
"random5",
|
|
21
|
+
"random4"
|
|
22
|
+
],
|
|
23
|
+
"title": "Custom title for page 1!!!"
|
|
24
24
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<script>
|
|
2
|
-
import { Card } from "$pkg";
|
|
3
|
-
import { page } from "$app/stores";
|
|
4
|
-
</script>
|
|
5
|
-
|
|
6
|
-
<Card>
|
|
7
|
-
<h1 slot="content" class="default-card">{$page.url}</h1>
|
|
1
|
+
<script>
|
|
2
|
+
import { Card } from "$pkg";
|
|
3
|
+
import { page } from "$app/stores";
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<Card>
|
|
7
|
+
<h1 slot="content" class="default-card">{$page.url}</h1>
|
|
8
8
|
</Card>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
{
|
|
2
|
-
"lastUpdated": "2024-03-03",
|
|
3
|
-
"title": "Custom title for page 2",
|
|
4
|
-
"imageUrl": "/favicon.png",
|
|
5
|
-
"tags": [
|
|
6
|
-
"random"
|
|
7
|
-
]
|
|
1
|
+
{
|
|
2
|
+
"lastUpdated": "2024-03-03",
|
|
3
|
+
"title": "Custom title for page 2",
|
|
4
|
+
"imageUrl": "/favicon.png",
|
|
5
|
+
"tags": [
|
|
6
|
+
"random"
|
|
7
|
+
]
|
|
8
8
|
}
|