@turnipxenon/pineapple 2.4.31 → 2.4.33

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.
@@ -4,9 +4,8 @@
4
4
  <option name="autoReloadType" value="SELECTIVE" />
5
5
  </component>
6
6
  <component name="ChangeListManager">
7
- <list default="true" id="accb6ba2-c343-4f84-ad30-6e2d71eceee5" name="Changes" comment="Set queryParams based on index and pageSize">
8
- <change afterPath="$PROJECT_DIR$/src/lib/components/navigation_component/index.ts" afterDir="false" />
9
- <change beforePath="$PROJECT_DIR$/src/lib/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib/index.ts" afterDir="false" />
7
+ <list default="true" id="accb6ba2-c343-4f84-ad30-6e2d71eceee5" name="Changes" comment="Migrate from relying on json instead of comments for meta">
8
+ <change beforePath="$PROJECT_DIR$/package.json" beforeDir="false" afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
10
9
  </list>
11
10
  <option name="SHOW_DIALOG" value="false" />
12
11
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
@@ -43,8 +42,8 @@
43
42
  <option value="CSS File" />
44
43
  <option value="+page" />
45
44
  <option value="NavigationComponent" />
46
- <option value="TypeScript File" />
47
45
  <option value="NavigationControl" />
46
+ <option value="TypeScript File" />
48
47
  </list>
49
48
  </option>
50
49
  </component>
@@ -85,40 +84,40 @@
85
84
  <option name="hideEmptyMiddlePackages" value="true" />
86
85
  <option name="showLibraryContents" value="true" />
87
86
  </component>
88
- <component name="PropertiesComponent"><![CDATA[{
89
- "keyToString": {
90
- "DefaultHtmlFileTemplate": "HTML File",
91
- "RunOnceActivity.OpenProjectViewOnStart": "true",
92
- "RunOnceActivity.ShowReadmeOnStart": "true",
93
- "WebServerToolWindowFactoryState": "false",
94
- "git-widget-placeholder": "turnip/navigation",
95
- "ignore.virus.scanning.warn.message": "true",
96
- "last_opened_file_path": "C:/Users/Pumpkin/Projects/Web/pineapple/src/lib/components/navigation_component",
97
- "list.type.of.created.stylesheet": "CSS",
98
- "node.js.detected.package.eslint": "true",
99
- "node.js.detected.package.tslint": "true",
100
- "node.js.selected.package.eslint": "(autodetect)",
101
- "node.js.selected.package.tslint": "(autodetect)",
102
- "nodejs_interpreter_path": "node",
103
- "nodejs_package_manager_path": "yarn",
104
- "npm.build.executor": "Run",
105
- "npm.dev (1).executor": "Run",
106
- "npm.dev --open.executor": "Run",
107
- "npm.dev offline.executor": "Run",
108
- "npm.dev-offline.executor": "Run",
109
- "npm.dev.executor": "Run",
110
- "settings.editor.selected.configurable": "preferences.pluginManager",
111
- "ts.external.directory.path": "C:\\Users\\Pumpkin\\Projects\\Web\\pineapple\\node_modules\\typescript\\lib",
112
- "vue.rearranger.settings.migration": "true"
87
+ <component name="PropertiesComponent">{
88
+ &quot;keyToString&quot;: {
89
+ &quot;DefaultHtmlFileTemplate&quot;: &quot;HTML File&quot;,
90
+ &quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
91
+ &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
92
+ &quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
93
+ &quot;git-widget-placeholder&quot;: &quot;turnip/navigation&quot;,
94
+ &quot;ignore.virus.scanning.warn.message&quot;: &quot;true&quot;,
95
+ &quot;last_opened_file_path&quot;: &quot;C:/Users/Pumpkin/Projects/Web/pineapple/src/routes/(pineapple)/pineapple/(extra-pages)/page2&quot;,
96
+ &quot;list.type.of.created.stylesheet&quot;: &quot;CSS&quot;,
97
+ &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
98
+ &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
99
+ &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
100
+ &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
101
+ &quot;nodejs_interpreter_path&quot;: &quot;node&quot;,
102
+ &quot;nodejs_package_manager_path&quot;: &quot;yarn&quot;,
103
+ &quot;npm.build.executor&quot;: &quot;Run&quot;,
104
+ &quot;npm.dev (1).executor&quot;: &quot;Run&quot;,
105
+ &quot;npm.dev --open.executor&quot;: &quot;Run&quot;,
106
+ &quot;npm.dev offline.executor&quot;: &quot;Run&quot;,
107
+ &quot;npm.dev-offline.executor&quot;: &quot;Run&quot;,
108
+ &quot;npm.dev.executor&quot;: &quot;Run&quot;,
109
+ &quot;settings.editor.selected.configurable&quot;: &quot;preferences.pluginManager&quot;,
110
+ &quot;ts.external.directory.path&quot;: &quot;C:\\Users\\Pumpkin\\Projects\\Web\\pineapple\\node_modules\\typescript\\lib&quot;,
111
+ &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
113
112
  }
114
- }]]></component>
113
+ }</component>
115
114
  <component name="RecentsManager">
116
115
  <key name="CopyFile.RECENT_KEYS">
116
+ <recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\(extra-pages)\page2" />
117
117
  <recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\lib\components\navigation_component" />
118
118
  <recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\page3\page7\(test_layout)\page8" />
119
119
  <recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\page3\page7" />
120
120
  <recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\page3" />
121
- <recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\page3\page5" />
122
121
  </key>
123
122
  <key name="MoveFile.RECENT_KEYS">
124
123
  <recent name="C:\Users\Pumpkin\Projects\Web\pineapple\src\routes\(pineapple)\pineapple\(extra-pages)" />
@@ -241,31 +240,9 @@
241
240
  <workItem from="1711471654056" duration="635000" />
242
241
  <workItem from="1711472302524" duration="9738000" />
243
242
  <workItem from="1711482094100" duration="5506000" />
244
- <workItem from="1711487798169" duration="92000" />
245
- </task>
246
- <task id="LOCAL-00059" summary="Add data-nosnippet">
247
- <option name="closed" value="true" />
248
- <created>1710305409664</created>
249
- <option name="number" value="00059" />
250
- <option name="presentableId" value="LOCAL-00059" />
251
- <option name="project" value="LOCAL" />
252
- <updated>1710305409664</updated>
253
- </task>
254
- <task id="LOCAL-00060" summary="Fix wrong link in migrante">
255
- <option name="closed" value="true" />
256
- <created>1710305826429</created>
257
- <option name="number" value="00060" />
258
- <option name="presentableId" value="LOCAL-00060" />
259
- <option name="project" value="LOCAL" />
260
- <updated>1710305826429</updated>
261
- </task>
262
- <task id="LOCAL-00061" summary="Reorganize directories to make Pineapple as default layout but still overrideable by Seaweed">
263
- <option name="closed" value="true" />
264
- <created>1710373523715</created>
265
- <option name="number" value="00061" />
266
- <option name="presentableId" value="LOCAL-00061" />
267
- <option name="project" value="LOCAL" />
268
- <updated>1710373523715</updated>
243
+ <workItem from="1711487798169" duration="264000" />
244
+ <workItem from="1711488375110" duration="856000" />
245
+ <workItem from="1711490061858" duration="2823000" />
269
246
  </task>
270
247
  <task id="LOCAL-00062" summary="Improve text contrast in dark mode">
271
248
  <option name="closed" value="true" />
@@ -635,7 +612,31 @@
635
612
  <option name="project" value="LOCAL" />
636
613
  <updated>1711487464414</updated>
637
614
  </task>
638
- <option name="localTasksCounter" value="108" />
615
+ <task id="LOCAL-00108" summary="Export NavigationComponent">
616
+ <option name="closed" value="true" />
617
+ <created>1711487908874</created>
618
+ <option name="number" value="00108" />
619
+ <option name="presentableId" value="LOCAL-00108" />
620
+ <option name="project" value="LOCAL" />
621
+ <updated>1711487908874</updated>
622
+ </task>
623
+ <task id="LOCAL-00109" summary="Add a way to hide an entry in NavigationComponent">
624
+ <option name="closed" value="true" />
625
+ <created>1711489071463</created>
626
+ <option name="number" value="00109" />
627
+ <option name="presentableId" value="LOCAL-00109" />
628
+ <option name="project" value="LOCAL" />
629
+ <updated>1711489071463</updated>
630
+ </task>
631
+ <task id="LOCAL-00110" summary="Migrate from relying on json instead of comments for meta">
632
+ <option name="closed" value="true" />
633
+ <created>1711492747330</created>
634
+ <option name="number" value="00110" />
635
+ <option name="presentableId" value="LOCAL-00110" />
636
+ <option name="project" value="LOCAL" />
637
+ <updated>1711492747331</updated>
638
+ </task>
639
+ <option name="localTasksCounter" value="111" />
639
640
  <servers />
640
641
  </component>
641
642
  <component name="TypeScriptGeneratedFilesManager">
@@ -693,9 +694,6 @@
693
694
  </option>
694
695
  </component>
695
696
  <component name="VcsManagerConfiguration">
696
- <MESSAGE value="Fix default card postcss style" />
697
- <MESSAGE value="Adjust turnip fab button color" />
698
- <MESSAGE value="Replace btn-group postcss class with turnip-menu&#10;&#10;There is postcss defined class called btn-group which has styles that have !important, which I accidentally used not knowing it exists, and it overrides whatever styles I apply on my class" />
699
697
  <MESSAGE value="Add external link warning stub" />
700
698
  <MESSAGE value="Refactor Game Section to separate component" />
701
699
  <MESSAGE value="Refactor GameSection out of SeaweedTemplate" />
@@ -718,6 +716,9 @@
718
716
  <MESSAGE value="Add Navigation control" />
719
717
  <MESSAGE value="Move NavigationControl to a component" />
720
718
  <MESSAGE value="Set queryParams based on index and pageSize" />
721
- <option name="LAST_COMMIT_MESSAGE" value="Set queryParams based on index and pageSize" />
719
+ <MESSAGE value="Export NavigationComponent" />
720
+ <MESSAGE value="Add a way to hide an entry in NavigationComponent" />
721
+ <MESSAGE value="Migrate from relying on json instead of comments for meta" />
722
+ <option name="LAST_COMMIT_MESSAGE" value="Migrate from relying on json instead of comments for meta" />
722
723
  </component>
723
724
  </project>
@@ -3,37 +3,39 @@ import { Card, createGoToFunction } from "../..";
3
3
  import { parsePageMeta } from "./PageMeta";
4
4
  export let title = void 0;
5
5
  export let fileList;
6
+ export let jsonList;
7
+ export let imageMap = /* @__PURE__ */ new Map();
6
8
  export let parentSubpath;
7
- export let compareFn;
9
+ export let compareFn = void 0;
8
10
  export let pageSize = 5;
9
11
  export let currentIndex = 0;
10
- const pageFlatList = parsePageMeta(fileList, compareFn);
12
+ const pageFlatList = parsePageMeta(fileList, jsonList, imageMap, compareFn);
11
13
  $:
12
14
  visiblePages = pageFlatList.slice(currentIndex * pageSize, currentIndex * pageSize + pageSize);
13
15
  </script>
14
16
 
15
17
  <div class="navigation-wrapper">
18
+ {#if (title)}
19
+ <Card>
20
+ <h1 slot="content" class="default-card navigation-title">
21
+ {title}
22
+ </h1>
23
+ </Card>
24
+ {/if}
16
25
 
17
26
  <NavigationControl bind:currentIndex={currentIndex}
18
27
  bind:contentLength={pageFlatList.length}
19
28
  bind:pageSize={pageSize}></NavigationControl>
20
29
 
21
30
  <div class="navigation-component">
22
- {#if (title)}
23
- <Card>
24
- <h1 slot="content" class="default-card navigation-title">
25
- {title}
26
- </h1>
27
- </Card>
28
- {/if}
29
31
  <!-- all the misc routes-->
30
32
  {#each visiblePages as pageMeta}
31
33
  {@const fullPath=`${parentSubpath}${pageMeta.relativeLink}`}
32
34
  <button class="navigation-element"
33
35
  title={fullPath}
34
36
  on:click={createGoToFunction(fullPath)}>
35
- {#if pageMeta.image}
36
- <img src={pageMeta.image} alt={pageMeta.imageAlt ?? "placeholder alt text please replace me or report me!"} />
37
+ {#if pageMeta.imageUrl}
38
+ <img src={pageMeta.imageUrl} alt={pageMeta.imageAlt ?? "placeholder alt text please replace me or report me!"} />
37
39
  {/if}
38
40
  <section class="blurb-text">
39
41
  <h2>{pageMeta.title}</h2>
@@ -4,10 +4,12 @@ declare const __propDef: {
4
4
  props: {
5
5
  title?: string | undefined;
6
6
  fileList: Record<string, unknown>;
7
+ jsonList: Record<string, unknown>;
8
+ imageMap?: Map<string, string> | undefined;
7
9
  /**
8
10
  * Should include a slash before and after the path
9
11
  */ parentSubpath: string;
10
- compareFn: undefined | ParsePageMetaCompareFn;
12
+ compareFn?: undefined | ParsePageMetaCompareFn;
11
13
  pageSize?: number | undefined;
12
14
  currentIndex?: number | undefined;
13
15
  };
@@ -4,14 +4,31 @@ export interface PageMeta {
4
4
  title: string;
5
5
  tags: string[];
6
6
  /**
7
- * Images are only limited to absolute paths (includes files in static folder)
7
+ * imageID is an ID that NavigationComponent can use to identify imported images
8
+ *
9
+ * To use imageID:
10
+ * 1. Add the imageID entry to the meta.json for the page
11
+ * 2. Create a typescript file with the variable ImageMap: Map<string, string>
12
+ * 3. Add a new entry with your imageID as key, and the image url as the value. Since this is
13
+ * Typescript, you can use import ImageUrl from "./path.png" as you would normally do.
14
+ * 4. Add ImageMap as an argument to your NavigationComponent.
15
+ * Overall, this involves four files
16
+ * - Your navigation page: ./+page.svelte
17
+ * - Your image map typescript: ImageMap.ts
18
+ * - The page you want with an image represented in the navigation: ./topic1/+page.svelte
19
+ * - The meta for that page: ./topic1/meta.json
8
20
  */
9
- image?: string;
21
+ imageID?: string;
22
+ /**
23
+ * imageURL is only limited to absolute paths (includes files in static folder)
24
+ */
25
+ imageUrl?: string;
10
26
  imageAlt?: string;
11
27
  description?: string;
12
28
  datePublished?: string;
13
29
  lastUpdated?: string;
14
30
  shouldGroup?: boolean;
31
+ shouldHide?: boolean;
15
32
  }
16
33
  /**
17
34
  * todo: doc
@@ -20,4 +37,4 @@ export interface PageMeta {
20
37
  */
21
38
  export declare const findPageMetaParent: (parentList: PageMeta[], child: PageMeta) => boolean;
22
39
  export type ParsePageMetaCompareFn = ((a: PageMeta, b: PageMeta) => number);
23
- export declare const parsePageMeta: (fileList: Record<string, unknown>, compareFn?: ParsePageMetaCompareFn) => PageMeta[];
40
+ export declare const parsePageMeta: (fileList: Record<string, unknown>, jsonList: Record<string, unknown>, imageMap: Map<string, string>, compareFn?: ParsePageMetaCompareFn) => PageMeta[];
@@ -18,10 +18,27 @@ export const findPageMetaParent = (parentList, child) => {
18
18
  });
19
19
  return isChild;
20
20
  };
21
- export const parsePageMeta = (fileList, compareFn) => {
21
+ export const parsePageMeta = (fileList, jsonList, imageMap, compareFn) => {
22
22
  const pageFlatList = [];
23
23
  // save for the future
24
24
  // let pageGroupedList: PageMeta[] = [];
25
+ const jsonMap = new Map();
26
+ Object.keys(jsonList).forEach(path => {
27
+ const pathParts = path.split("/");
28
+ pathParts.pop();
29
+ // get title
30
+ // const title = pathParts[pathParts.length - 1].replaceAll("-", " ");
31
+ // get url path
32
+ const subPath = pathParts.filter(s => {
33
+ return s !== "." && s.indexOf("(") !== 0;
34
+ });
35
+ try {
36
+ jsonMap.set(subPath.join("/"), JSON.parse(jsonList[path].default));
37
+ }
38
+ catch (e) {
39
+ console.error(`Error parsing json at: ${path}: ${e}`);
40
+ }
41
+ });
25
42
  for (const path in fileList) {
26
43
  const pathParts = path.split("/");
27
44
  pathParts.pop();
@@ -40,22 +57,21 @@ export const parsePageMeta = (fileList, compareFn) => {
40
57
  nestedPages: []
41
58
  // todo: transform the data in server.ts?
42
59
  };
43
- const body = fileList[path].default;
44
- // let metadata : undefined | Map<string, string | string[]>;
45
- if (body.startsWith("<!--")) {
46
- // todo: absorb more metadata
47
- const metadata = JSON.parse(body.slice("<!--".length, body.indexOf("-->")));
60
+ const metadata = jsonMap.get(meta.relativeLink);
61
+ if (metadata) {
48
62
  meta.title = metadata["title"] ?? meta.title;
49
- meta.tags = metadata["tags"];
63
+ meta.tags = metadata["tags"] ?? [];
50
64
  meta.description = metadata["description"];
51
65
  meta.datePublished = metadata["datePublished"];
52
66
  meta.lastUpdated = metadata["lastUpdated"];
53
67
  meta.shouldGroup = metadata["shouldGroup"];
54
- meta.image = metadata["image"];
55
- if (meta.image) {
68
+ meta.shouldHide = metadata["shouldHide"];
69
+ meta.imageID = metadata["imageID"];
70
+ meta.imageUrl = imageMap.get(meta.imageID) ?? metadata["imageUrl"];
71
+ if (meta.imageUrl) {
56
72
  meta.imageAlt = metadata["imageAlt"];
57
73
  if (!meta.imageAlt) {
58
- console.warn(`Accessibility issues: image alt missing for image ${meta.image}`);
74
+ console.warn(`Accessibility issues: image alt missing for image ${meta.imageUrl}`);
59
75
  }
60
76
  }
61
77
  }
@@ -63,6 +79,7 @@ export const parsePageMeta = (fileList, compareFn) => {
63
79
  }
64
80
  pageFlatList.sort((a, b) => a.relativeLink.localeCompare(b.relativeLink));
65
81
  // find groupings
82
+ // grouping should be BEFORE the external sort
66
83
  // todo: we don't even have use for this yet!
67
84
  // pageFlatList.forEach(p => {
68
85
  // if (!findPageMetaParent(pageGroupedList, p)) {
@@ -21,7 +21,7 @@ export const options = {
21
21
  app: ({ head, body, assets, nonce, env }) => "<!DOCTYPE html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<link rel=\"icon\" href=\"" + assets + "/favicon.png\" />\n\t\t<meta name=\"viewport\" content=\"width=device-width\" />\n\t\t" + head + "\n\t</head>\n\n\t<body data-sveltekit-preload-data=\"hover\" data-theme=\"crimson\">\n\t\t<div style=\"display: contents\" class=\"h-full overflow-hidden\">" + body + "</div>\n\t</body>\n</html>\n",
22
22
  error: ({ status, message }) => "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<title>" + message + "</title>\n\n\t\t<style>\n\t\t\tbody {\n\t\t\t\t--bg: white;\n\t\t\t\t--fg: #222;\n\t\t\t\t--divider: #ccc;\n\t\t\t\tbackground: var(--bg);\n\t\t\t\tcolor: var(--fg);\n\t\t\t\tfont-family:\n\t\t\t\t\tsystem-ui,\n\t\t\t\t\t-apple-system,\n\t\t\t\t\tBlinkMacSystemFont,\n\t\t\t\t\t'Segoe UI',\n\t\t\t\t\tRoboto,\n\t\t\t\t\tOxygen,\n\t\t\t\t\tUbuntu,\n\t\t\t\t\tCantarell,\n\t\t\t\t\t'Open Sans',\n\t\t\t\t\t'Helvetica Neue',\n\t\t\t\t\tsans-serif;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tjustify-content: center;\n\t\t\t\theight: 100vh;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t.error {\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t\tmax-width: 32rem;\n\t\t\t\tmargin: 0 1rem;\n\t\t\t}\n\n\t\t\t.status {\n\t\t\t\tfont-weight: 200;\n\t\t\t\tfont-size: 3rem;\n\t\t\t\tline-height: 1;\n\t\t\t\tposition: relative;\n\t\t\t\ttop: -0.05rem;\n\t\t\t}\n\n\t\t\t.message {\n\t\t\t\tborder-left: 1px solid var(--divider);\n\t\t\t\tpadding: 0 0 0 1rem;\n\t\t\t\tmargin: 0 0 0 1rem;\n\t\t\t\tmin-height: 2.5rem;\n\t\t\t\tdisplay: flex;\n\t\t\t\talign-items: center;\n\t\t\t}\n\n\t\t\t.message h1 {\n\t\t\t\tfont-weight: 400;\n\t\t\t\tfont-size: 1em;\n\t\t\t\tmargin: 0;\n\t\t\t}\n\n\t\t\t@media (prefers-color-scheme: dark) {\n\t\t\t\tbody {\n\t\t\t\t\t--bg: #222;\n\t\t\t\t\t--fg: #ddd;\n\t\t\t\t\t--divider: #666;\n\t\t\t\t}\n\t\t\t}\n\t\t</style>\n\t</head>\n\t<body>\n\t\t<div class=\"error\">\n\t\t\t<span class=\"status\">" + status + "</span>\n\t\t\t<div class=\"message\">\n\t\t\t\t<h1>" + message + "</h1>\n\t\t\t</div>\n\t\t</div>\n\t</body>\n</html>\n"
23
23
  },
24
- version_hash: "28prrw"
24
+ version_hash: "99eys7"
25
25
  };
26
26
 
27
27
  export async function get_hooks() {
@@ -3,37 +3,39 @@ import { Card, createGoToFunction } from "../..";
3
3
  import { parsePageMeta } from "./PageMeta";
4
4
  export let title = void 0;
5
5
  export let fileList;
6
+ export let jsonList;
7
+ export let imageMap = /* @__PURE__ */ new Map();
6
8
  export let parentSubpath;
7
- export let compareFn;
9
+ export let compareFn = void 0;
8
10
  export let pageSize = 5;
9
11
  export let currentIndex = 0;
10
- const pageFlatList = parsePageMeta(fileList, compareFn);
12
+ const pageFlatList = parsePageMeta(fileList, jsonList, imageMap, compareFn);
11
13
  $:
12
14
  visiblePages = pageFlatList.slice(currentIndex * pageSize, currentIndex * pageSize + pageSize);
13
15
  </script>
14
16
 
15
17
  <div class="navigation-wrapper">
18
+ {#if (title)}
19
+ <Card>
20
+ <h1 slot="content" class="default-card navigation-title">
21
+ {title}
22
+ </h1>
23
+ </Card>
24
+ {/if}
16
25
 
17
26
  <NavigationControl bind:currentIndex={currentIndex}
18
27
  bind:contentLength={pageFlatList.length}
19
28
  bind:pageSize={pageSize}></NavigationControl>
20
29
 
21
30
  <div class="navigation-component">
22
- {#if (title)}
23
- <Card>
24
- <h1 slot="content" class="default-card navigation-title">
25
- {title}
26
- </h1>
27
- </Card>
28
- {/if}
29
31
  <!-- all the misc routes-->
30
32
  {#each visiblePages as pageMeta}
31
33
  {@const fullPath=`${parentSubpath}${pageMeta.relativeLink}`}
32
34
  <button class="navigation-element"
33
35
  title={fullPath}
34
36
  on:click={createGoToFunction(fullPath)}>
35
- {#if pageMeta.image}
36
- <img src={pageMeta.image} alt={pageMeta.imageAlt ?? "placeholder alt text please replace me or report me!"} />
37
+ {#if pageMeta.imageUrl}
38
+ <img src={pageMeta.imageUrl} alt={pageMeta.imageAlt ?? "placeholder alt text please replace me or report me!"} />
37
39
  {/if}
38
40
  <section class="blurb-text">
39
41
  <h2>{pageMeta.title}</h2>
@@ -4,10 +4,12 @@ declare const __propDef: {
4
4
  props: {
5
5
  title?: string | undefined;
6
6
  fileList: Record<string, unknown>;
7
+ jsonList: Record<string, unknown>;
8
+ imageMap?: Map<string, string> | undefined;
7
9
  /**
8
10
  * Should include a slash before and after the path
9
11
  */ parentSubpath: string;
10
- compareFn: undefined | ParsePageMetaCompareFn;
12
+ compareFn?: undefined | ParsePageMetaCompareFn;
11
13
  pageSize?: number | undefined;
12
14
  currentIndex?: number | undefined;
13
15
  };
@@ -4,14 +4,31 @@ export interface PageMeta {
4
4
  title: string;
5
5
  tags: string[];
6
6
  /**
7
- * Images are only limited to absolute paths (includes files in static folder)
7
+ * imageID is an ID that NavigationComponent can use to identify imported images
8
+ *
9
+ * To use imageID:
10
+ * 1. Add the imageID entry to the meta.json for the page
11
+ * 2. Create a typescript file with the variable ImageMap: Map<string, string>
12
+ * 3. Add a new entry with your imageID as key, and the image url as the value. Since this is
13
+ * Typescript, you can use import ImageUrl from "./path.png" as you would normally do.
14
+ * 4. Add ImageMap as an argument to your NavigationComponent.
15
+ * Overall, this involves four files
16
+ * - Your navigation page: ./+page.svelte
17
+ * - Your image map typescript: ImageMap.ts
18
+ * - The page you want with an image represented in the navigation: ./topic1/+page.svelte
19
+ * - The meta for that page: ./topic1/meta.json
8
20
  */
9
- image?: string;
21
+ imageID?: string;
22
+ /**
23
+ * imageURL is only limited to absolute paths (includes files in static folder)
24
+ */
25
+ imageUrl?: string;
10
26
  imageAlt?: string;
11
27
  description?: string;
12
28
  datePublished?: string;
13
29
  lastUpdated?: string;
14
30
  shouldGroup?: boolean;
31
+ shouldHide?: boolean;
15
32
  }
16
33
  /**
17
34
  * todo: doc
@@ -20,4 +37,4 @@ export interface PageMeta {
20
37
  */
21
38
  export declare const findPageMetaParent: (parentList: PageMeta[], child: PageMeta) => boolean;
22
39
  export type ParsePageMetaCompareFn = ((a: PageMeta, b: PageMeta) => number);
23
- export declare const parsePageMeta: (fileList: Record<string, unknown>, compareFn?: ParsePageMetaCompareFn) => PageMeta[];
40
+ export declare const parsePageMeta: (fileList: Record<string, unknown>, jsonList: Record<string, unknown>, imageMap: Map<string, string>, compareFn?: ParsePageMetaCompareFn) => PageMeta[];
@@ -18,10 +18,27 @@ export const findPageMetaParent = (parentList, child) => {
18
18
  });
19
19
  return isChild;
20
20
  };
21
- export const parsePageMeta = (fileList, compareFn) => {
21
+ export const parsePageMeta = (fileList, jsonList, imageMap, compareFn) => {
22
22
  const pageFlatList = [];
23
23
  // save for the future
24
24
  // let pageGroupedList: PageMeta[] = [];
25
+ const jsonMap = new Map();
26
+ Object.keys(jsonList).forEach(path => {
27
+ const pathParts = path.split("/");
28
+ pathParts.pop();
29
+ // get title
30
+ // const title = pathParts[pathParts.length - 1].replaceAll("-", " ");
31
+ // get url path
32
+ const subPath = pathParts.filter(s => {
33
+ return s !== "." && s.indexOf("(") !== 0;
34
+ });
35
+ try {
36
+ jsonMap.set(subPath.join("/"), JSON.parse(jsonList[path].default));
37
+ }
38
+ catch (e) {
39
+ console.error(`Error parsing json at: ${path}: ${e}`);
40
+ }
41
+ });
25
42
  for (const path in fileList) {
26
43
  const pathParts = path.split("/");
27
44
  pathParts.pop();
@@ -40,22 +57,21 @@ export const parsePageMeta = (fileList, compareFn) => {
40
57
  nestedPages: []
41
58
  // todo: transform the data in server.ts?
42
59
  };
43
- const body = fileList[path].default;
44
- // let metadata : undefined | Map<string, string | string[]>;
45
- if (body.startsWith("<!--")) {
46
- // todo: absorb more metadata
47
- const metadata = JSON.parse(body.slice("<!--".length, body.indexOf("-->")));
60
+ const metadata = jsonMap.get(meta.relativeLink);
61
+ if (metadata) {
48
62
  meta.title = metadata["title"] ?? meta.title;
49
- meta.tags = metadata["tags"];
63
+ meta.tags = metadata["tags"] ?? [];
50
64
  meta.description = metadata["description"];
51
65
  meta.datePublished = metadata["datePublished"];
52
66
  meta.lastUpdated = metadata["lastUpdated"];
53
67
  meta.shouldGroup = metadata["shouldGroup"];
54
- meta.image = metadata["image"];
55
- if (meta.image) {
68
+ meta.shouldHide = metadata["shouldHide"];
69
+ meta.imageID = metadata["imageID"];
70
+ meta.imageUrl = imageMap.get(meta.imageID) ?? metadata["imageUrl"];
71
+ if (meta.imageUrl) {
56
72
  meta.imageAlt = metadata["imageAlt"];
57
73
  if (!meta.imageAlt) {
58
- console.warn(`Accessibility issues: image alt missing for image ${meta.image}`);
74
+ console.warn(`Accessibility issues: image alt missing for image ${meta.imageUrl}`);
59
75
  }
60
76
  }
61
77
  }
@@ -63,6 +79,7 @@ export const parsePageMeta = (fileList, compareFn) => {
63
79
  }
64
80
  pageFlatList.sort((a, b) => a.relativeLink.localeCompare(b.relativeLink));
65
81
  // find groupings
82
+ // grouping should be BEFORE the external sort
66
83
  // todo: we don't even have use for this yet!
67
84
  // pageFlatList.forEach(p => {
68
85
  // if (!findPageMetaParent(pageGroupedList, p)) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@turnipxenon/pineapple",
3
3
  "description": "personal package for base styling for other personal projects",
4
- "version": "2.4.31",
4
+ "version": "2.4.33",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
7
7
  "build": "npm run check-requirements && vite build && yarn package",
@@ -5,41 +5,45 @@
5
5
 
6
6
  export let title: string | undefined = undefined;
7
7
  export let fileList: Record<string, unknown>;
8
+ export let jsonList: Record<string, unknown>;
9
+ export let imageMap = new Map<string, string>();
10
+
8
11
  /**
9
12
  * Should include a slash before and after the path
10
13
  */
11
14
  export let parentSubpath: string;
12
- export let compareFn: undefined | ParsePageMetaCompareFn;
15
+
16
+ export let compareFn: undefined | ParsePageMetaCompareFn = undefined;
13
17
  export let pageSize = 5;
14
18
  export let currentIndex = 0;
15
19
 
16
- const pageFlatList = parsePageMeta(fileList, compareFn);
20
+ const pageFlatList = parsePageMeta(fileList, jsonList, imageMap, compareFn);
17
21
 
18
22
  $: visiblePages = pageFlatList.slice(currentIndex * pageSize, (currentIndex * pageSize) + pageSize);
19
23
  </script>
20
24
 
21
25
  <div class="navigation-wrapper">
26
+ {#if (title)}
27
+ <Card>
28
+ <h1 slot="content" class="default-card navigation-title">
29
+ {title}
30
+ </h1>
31
+ </Card>
32
+ {/if}
22
33
 
23
34
  <NavigationControl bind:currentIndex={currentIndex}
24
35
  bind:contentLength={pageFlatList.length}
25
36
  bind:pageSize={pageSize}></NavigationControl>
26
37
 
27
38
  <div class="navigation-component">
28
- {#if (title)}
29
- <Card>
30
- <h1 slot="content" class="default-card navigation-title">
31
- {title}
32
- </h1>
33
- </Card>
34
- {/if}
35
39
  <!-- all the misc routes-->
36
40
  {#each visiblePages as pageMeta}
37
41
  {@const fullPath=`${parentSubpath}${pageMeta.relativeLink}`}
38
42
  <button class="navigation-element"
39
43
  title={fullPath}
40
44
  on:click={createGoToFunction(fullPath)}>
41
- {#if pageMeta.image}
42
- <img src={pageMeta.image} alt={pageMeta.imageAlt ?? "placeholder alt text please replace me or report me!"} />
45
+ {#if pageMeta.imageUrl}
46
+ <img src={pageMeta.imageUrl} alt={pageMeta.imageAlt ?? "placeholder alt text please replace me or report me!"} />
43
47
  {/if}
44
48
  <section class="blurb-text">
45
49
  <h2>{pageMeta.title}</h2>
@@ -1,4 +1,4 @@
1
- import type { RawGlob } from "$pkg";
1
+ import type { RawGlob } from "$pkg/util/util";
2
2
 
3
3
  export interface PageMeta {
4
4
  // generated meta
@@ -10,14 +10,32 @@ export interface PageMeta {
10
10
  tags: string[];
11
11
 
12
12
  /**
13
- * Images are only limited to absolute paths (includes files in static folder)
13
+ * imageID is an ID that NavigationComponent can use to identify imported images
14
+ *
15
+ * To use imageID:
16
+ * 1. Add the imageID entry to the meta.json for the page
17
+ * 2. Create a typescript file with the variable ImageMap: Map<string, string>
18
+ * 3. Add a new entry with your imageID as key, and the image url as the value. Since this is
19
+ * Typescript, you can use import ImageUrl from "./path.png" as you would normally do.
20
+ * 4. Add ImageMap as an argument to your NavigationComponent.
21
+ * Overall, this involves four files
22
+ * - Your navigation page: ./+page.svelte
23
+ * - Your image map typescript: ImageMap.ts
24
+ * - The page you want with an image represented in the navigation: ./topic1/+page.svelte
25
+ * - The meta for that page: ./topic1/meta.json
14
26
  */
15
- image?: string;
27
+ imageID?: string;
28
+
29
+ /**
30
+ * imageURL is only limited to absolute paths (includes files in static folder)
31
+ */
32
+ imageUrl?: string;
16
33
  imageAlt?: string;
17
34
  description?: string;
18
35
  datePublished?: string;
19
36
  lastUpdated?: string;
20
37
  shouldGroup?: boolean;
38
+ shouldHide?: boolean;
21
39
  }
22
40
 
23
41
  /**
@@ -47,10 +65,32 @@ export const findPageMetaParent = (parentList: PageMeta[], child: PageMeta): boo
47
65
  export type ParsePageMetaCompareFn = ((a: PageMeta, b: PageMeta) => number);
48
66
 
49
67
  export const parsePageMeta = (fileList: Record<string, unknown>,
68
+ jsonList: Record<string, unknown>,
69
+ imageMap: Map<string, string>,
50
70
  compareFn?: ParsePageMetaCompareFn): PageMeta[] => {
51
71
  const pageFlatList: PageMeta[] = [];
52
72
  // save for the future
53
73
  // let pageGroupedList: PageMeta[] = [];
74
+ const jsonMap = new Map<string, { [k: string]: unknown }>();
75
+ Object.keys(jsonList).forEach(path => {
76
+ const pathParts = path.split("/");
77
+ pathParts.pop();
78
+
79
+ // get title
80
+ // const title = pathParts[pathParts.length - 1].replaceAll("-", " ");
81
+
82
+ // get url path
83
+ const subPath = pathParts.filter(s => {
84
+ return s !== "." && s.indexOf("(") !== 0;
85
+ });
86
+
87
+ try {
88
+ jsonMap.set(subPath.join("/"), JSON.parse((jsonList[path] as RawGlob).default));
89
+ } catch (e) {
90
+ console.error(`Error parsing json at: ${path}: ${e}`);
91
+ }
92
+
93
+ });
54
94
 
55
95
  for (const path in fileList) {
56
96
  const pathParts = path.split("/");
@@ -76,25 +116,26 @@ export const parsePageMeta = (fileList: Record<string, unknown>,
76
116
  };
77
117
 
78
118
 
79
- const body = (fileList[path] as RawGlob).default as string;
80
- // let metadata : undefined | Map<string, string | string[]>;
81
- if (body.startsWith("<!--")) {
82
- // todo: absorb more metadata
83
- const metadata = JSON.parse(body.slice("<!--".length, body.indexOf("-->")));
84
- meta.title = metadata["title"] ?? meta.title;
85
- meta.tags = metadata["tags"];
86
- meta.description = metadata["description"];
87
- meta.datePublished = metadata["datePublished"];
88
- meta.lastUpdated = metadata["lastUpdated"];
119
+ const metadata = jsonMap.get(meta.relativeLink);
120
+ if (metadata) {
121
+ meta.title = metadata["title"] as string ?? meta.title;
122
+ meta.tags = metadata["tags"] as string[] ?? [];
123
+ meta.description = metadata["description"] as string;
124
+ meta.datePublished = metadata["datePublished"] as string;
125
+ meta.lastUpdated = metadata["lastUpdated"] as string;
89
126
  meta.shouldGroup = metadata["shouldGroup"] as boolean;
127
+ meta.shouldHide = metadata["shouldHide"] as boolean;
90
128
 
91
- meta.image = metadata["image"];
92
- if (meta.image) {
93
- meta.imageAlt = metadata["imageAlt"];
129
+ meta.imageID = metadata["imageID"] as string;
130
+ meta.imageUrl = imageMap.get(meta.imageID) ?? metadata["imageUrl"] as string;
131
+
132
+ if (meta.imageUrl) {
133
+ meta.imageAlt = metadata["imageAlt"] as string;
94
134
  if (!meta.imageAlt) {
95
- console.warn(`Accessibility issues: image alt missing for image ${meta.image}`);
135
+ console.warn(`Accessibility issues: image alt missing for image ${meta.imageUrl}`);
96
136
  }
97
137
  }
138
+
98
139
  }
99
140
 
100
141
  pageFlatList.push(meta);
@@ -103,6 +144,7 @@ export const parsePageMeta = (fileList: Record<string, unknown>,
103
144
  pageFlatList.sort((a, b) => a.relativeLink.localeCompare(b.relativeLink));
104
145
 
105
146
  // find groupings
147
+ // grouping should be BEFORE the external sort
106
148
  // todo: we don't even have use for this yet!
107
149
  // pageFlatList.forEach(p => {
108
150
  // if (!findPageMetaParent(pageGroupedList, p)) {
@@ -0,0 +1,5 @@
1
+ import TestImage from "$pkg/assets/characters/ares/ares_yay.webp";
2
+
3
+ export const ImageMap = new Map<string, string>([
4
+ ["testImageID", TestImage]]
5
+ );
@@ -1,8 +1,3 @@
1
- <!--{
2
- "title": "Custom title for page 1",
3
- "image": "/favicon.png",
4
- "tags": ["random"]
5
- }-->
6
1
  <script>
7
2
  import { Card } from "$pkg";
8
3
  import { page } from "$app/stores";
@@ -0,0 +1,5 @@
1
+ {
2
+ "title": "Custom title for page 1",
3
+ "imageUrl": "/favicon.png",
4
+ "tags": ["random"]
5
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "title": "Custom title for page 2!!!",
3
+ "imageID": "testImageID",
4
+ "tags": ["random"]
5
+ }
@@ -4,6 +4,7 @@
4
4
  import TestDialogYarn from "./TestDialog.yarn?raw";
5
5
  import { Card, dialogManager } from "$pkg";
6
6
  import NavigationComponent from "$pkg/components/navigation_component/NavigationComponent.svelte";
7
+ import { ImageMap } from "./(extra-pages)/ImageMap";
7
8
 
8
9
  // region Toast test scripts
9
10
  let testingQueueNumber = 1;
@@ -29,7 +30,8 @@
29
30
 
30
31
 
31
32
  // todo: fix fragile relative reference to the root
32
- const fileList = import.meta.glob("./**/+page.svelte", { query: "?raw", eager: true });
33
+ const fileList = import.meta.glob("./**/+page.svelte", { query: "?raw" });
34
+ const jsonList = import.meta.glob("./**/meta.json", { query: "?raw", eager: true });
33
35
  </script>
34
36
 
35
37
  <div class="pineapple-container">
@@ -54,6 +56,8 @@
54
56
 
55
57
  <NavigationComponent title="Navigation Component Test"
56
58
  fileList={fileList}
59
+ jsonList={jsonList}
60
+ imageMap={ImageMap}
57
61
  parentSubpath="/pineapple/">
58
62
  </NavigationComponent>
59
63
  </div>
package/vite.config.ts CHANGED
@@ -3,5 +3,5 @@ import { defineConfig } from "vite";
3
3
 
4
4
  export default defineConfig({
5
5
  plugins: [sveltekit()],
6
- assetsInclude: ['**/*.yarn']
6
+ assetsInclude: ["**/*.yarn", "**/*.json"]
7
7
  });