@turnipxenon/pineapple 4.0.0-alpha.3 → 4.1.0

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.
Files changed (40) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +1 -0
  3. package/dist/modules/parsnip/ParsnipBlockChildren.svelte +37 -0
  4. package/dist/modules/parsnip/ParsnipBlockChildren.svelte.d.ts +8 -0
  5. package/dist/modules/parsnip/ParsnipEmbedWikilink.svelte +19 -0
  6. package/dist/modules/parsnip/ParsnipEmbedWikilink.svelte.d.ts +15 -0
  7. package/dist/modules/parsnip/ParsnipEntry.d.ts +7 -0
  8. package/dist/modules/parsnip/ParsnipEntry.js +1 -0
  9. package/dist/modules/parsnip/ParsnipHeading.svelte +21 -0
  10. package/dist/modules/parsnip/ParsnipHeading.svelte.d.ts +7 -0
  11. package/dist/modules/parsnip/ParsnipList.svelte +24 -0
  12. package/dist/modules/parsnip/ParsnipList.svelte.d.ts +7 -0
  13. package/dist/modules/parsnip/ParsnipOverall.d.ts +42 -0
  14. package/dist/modules/parsnip/ParsnipOverall.js +1 -0
  15. package/dist/modules/parsnip/ParsnipParagraph.svelte +10 -0
  16. package/dist/modules/parsnip/ParsnipParagraph.svelte.d.ts +7 -0
  17. package/dist/modules/parsnip/ParsnipPhrasingChildren.svelte +26 -0
  18. package/dist/modules/parsnip/ParsnipPhrasingChildren.svelte.d.ts +7 -0
  19. package/dist/modules/parsnip/ParsnipWikilink.svelte +20 -0
  20. package/dist/modules/parsnip/ParsnipWikilink.svelte.d.ts +16 -0
  21. package/dist/modules/parsnip/index.d.ts +3 -0
  22. package/dist/modules/parsnip/index.js +3 -0
  23. package/dist/modules/parsnip/route-util/ParsnipBlog.svelte +28 -0
  24. package/dist/modules/parsnip/route-util/ParsnipBlog.svelte.d.ts +7 -0
  25. package/dist/modules/parsnip/route-util/menuPageServerLoad.d.ts +6 -0
  26. package/dist/modules/parsnip/route-util/menuPageServerLoad.js +14 -0
  27. package/dist/modules/parsnip/route-util/slugPageServerLoad.d.ts +8 -0
  28. package/dist/modules/parsnip/route-util/slugPageServerLoad.js +24 -0
  29. package/dist/paraglide/runtime.d.ts +1 -1
  30. package/dist/styles/app.css +11 -1
  31. package/dist/styles/turnip-theme.css +10 -1
  32. package/dist/ui/modules/NavigationMenu/NavigationControl.svelte +10 -10
  33. package/dist/ui/modules/NavigationMenu/NavigationMenu.svelte +41 -13
  34. package/dist/ui/modules/NavigationMenu/NavigationMenu.svelte.d.ts +2 -0
  35. package/dist/ui/modules/NavigationMenu/PageMeta.js +3 -0
  36. package/dist/ui/templates/blog_template/blog-template.css +0 -4
  37. package/dist/util/env-getter.d.ts +2 -0
  38. package/dist/util/env-getter.js +2 -0
  39. package/package.json +8 -2
  40. package/src/lib/styles/app.css +11 -1
package/dist/index.d.ts CHANGED
@@ -12,3 +12,4 @@ export type { IDialogManager } from "./components/dialog_manager/IDialogManager"
12
12
  export { default as BlogTemplate } from "./ui/templates/blog_template/BlogTemplate.svelte";
13
13
  export { default as DialogOverlay } from "./ui/modules/dialog_overlay/DialogOverlay.svelte";
14
14
  export { dialogManager } from "./components/dialog_manager/DialogManager";
15
+ export * from "./modules/parsnip/index";
package/dist/index.js CHANGED
@@ -12,3 +12,4 @@ export * from "./api/index";
12
12
  export { default as BlogTemplate } from "./ui/templates/blog_template/BlogTemplate.svelte";
13
13
  export { default as DialogOverlay } from "./ui/modules/dialog_overlay/DialogOverlay.svelte";
14
14
  export { dialogManager } from "./components/dialog_manager/DialogManager";
15
+ export * from "./modules/parsnip/index";
@@ -0,0 +1,37 @@
1
+ <script lang="ts">
2
+ import ParsnipHeading from "./ParsnipHeading.svelte";
3
+ import ParsnipList from "./ParsnipList.svelte";
4
+ import ParsnipParagraph from "./ParsnipParagraph.svelte";
5
+ import ParsnipPhrasingChildren from "./ParsnipPhrasingChildren.svelte";
6
+ import { CodeBlock } from "../../ui/elements/index";
7
+ import type { Content } from "mdast";
8
+ import Self from "./ParsnipBlockChildren.svelte";
9
+
10
+ const { blockChildren, shouldUnwrapParagraph = false }
11
+ : { blockChildren: Content[], shouldUnwrapParagraph?: boolean } = $props();
12
+ </script>
13
+
14
+ {#each blockChildren as child (child)}
15
+ {#if child.type === 'paragraph'}
16
+ {#if shouldUnwrapParagraph}
17
+ <ParsnipPhrasingChildren phrasingChildren={child.children} />
18
+ {:else}
19
+ <ParsnipParagraph paragraph={child} />
20
+ {/if}
21
+ {:else if child.type === 'heading'}
22
+ <ParsnipHeading heading={child} />
23
+ {:else if child.type === 'blockquote'}
24
+ <!-- todo: do advanced things like callout blocks -->
25
+ <blockquote>
26
+ <Self blockChildren={child.children} />
27
+ </blockquote>
28
+ {:else if child.type === 'yaml'}
29
+ <!-- do nothing -->
30
+ {:else if child.type === 'code'}
31
+ <CodeBlock code={child.value} lang={child.lang ?? 'markdown'} />
32
+ {:else if child.type === 'list'}
33
+ <ParsnipList list={child} />
34
+ {:else}
35
+ <p>{JSON.stringify(child, undefined, 2)}</p>
36
+ {/if}
37
+ {/each}
@@ -0,0 +1,8 @@
1
+ import type { Content } from "mdast";
2
+ type $$ComponentProps = {
3
+ blockChildren: Content[];
4
+ shouldUnwrapParagraph?: boolean;
5
+ };
6
+ declare const ParsnipBlockChildren: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type ParsnipBlockChildren = ReturnType<typeof ParsnipBlockChildren>;
8
+ export default ParsnipBlockChildren;
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import { getCmsBaseUrl } from "../../util/env-getter";
3
+
4
+ interface EmbedWikilink {
5
+ type: 'embedWikilink',
6
+ value: string;
7
+ fileAccessor: {
8
+ target: string;
9
+ isEmbed: false;
10
+ basePath: string;
11
+ }
12
+ }
13
+
14
+ const { wikilink } : { wikilink: EmbedWikilink } = $props();
15
+ </script>
16
+
17
+ <!-- todo(turnip): determine appropriate media -->
18
+ <!-- todo(turnip): add alt text -->
19
+ <img src={`${getCmsBaseUrl()}/${wikilink.fileAccessor.basePath}`} alt=""/>
@@ -0,0 +1,15 @@
1
+ interface EmbedWikilink {
2
+ type: 'embedWikilink';
3
+ value: string;
4
+ fileAccessor: {
5
+ target: string;
6
+ isEmbed: false;
7
+ basePath: string;
8
+ };
9
+ }
10
+ type $$ComponentProps = {
11
+ wikilink: EmbedWikilink;
12
+ };
13
+ declare const ParsnipEmbedWikilink: import("svelte").Component<$$ComponentProps, {}, "">;
14
+ type ParsnipEmbedWikilink = ReturnType<typeof ParsnipEmbedWikilink>;
15
+ export default ParsnipEmbedWikilink;
@@ -0,0 +1,7 @@
1
+ import type { ParsnipEntrySummary } from "./ParsnipOverall";
2
+ import type { Root } from "mdast";
3
+ export interface ParsnipEntry extends ParsnipEntrySummary {
4
+ ast: {
5
+ ast: Root;
6
+ };
7
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ <script lang="ts">
2
+ import ParsnipBlockChildren from "./ParsnipBlockChildren.svelte";
3
+ import ParsnipPhrasingChildren from "./ParsnipPhrasingChildren.svelte";
4
+ import type { Heading } from "mdast";
5
+
6
+ const { heading }: { heading: Heading } = $props();
7
+ </script>
8
+
9
+ {#if heading.depth === 1}
10
+ <h2><ParsnipPhrasingChildren phrasingChildren={heading.children}/></h2>
11
+ {:else if heading.depth === 2}
12
+ <h3><ParsnipPhrasingChildren phrasingChildren={heading.children}/></h3>
13
+ {:else if heading.depth === 3}
14
+ <h4><ParsnipPhrasingChildren phrasingChildren={heading.children}/></h4>
15
+ {:else if heading.depth === 4}
16
+ <h5><ParsnipPhrasingChildren phrasingChildren={heading.children}/></h5>
17
+ {:else if heading.depth === 5}
18
+ <h6><ParsnipPhrasingChildren phrasingChildren={heading.children}/></h6>
19
+ {:else if heading.depth === 6}
20
+ <p><ParsnipPhrasingChildren phrasingChildren={heading.children}/></p>
21
+ {/if}
@@ -0,0 +1,7 @@
1
+ import type { Heading } from "mdast";
2
+ type $$ComponentProps = {
3
+ heading: Heading;
4
+ };
5
+ declare const ParsnipHeading: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type ParsnipHeading = ReturnType<typeof ParsnipHeading>;
7
+ export default ParsnipHeading;
@@ -0,0 +1,24 @@
1
+ <script lang="ts">
2
+ import ParsnipBlockChildren from "./ParsnipBlockChildren.svelte";
3
+ import type { List } from "mdast";
4
+
5
+ const { list }: { list: List } = $props();
6
+ </script>
7
+
8
+ {#snippet childList(main: List)}
9
+ {#each main.children as child (child)}
10
+ <li>
11
+ <ParsnipBlockChildren blockChildren={child.children} shouldUnwrapParagraph={true} />
12
+ </li>
13
+ {/each}
14
+ {/snippet}
15
+
16
+ {#if list.ordered}
17
+ <ol>
18
+ {@render childList(list)}
19
+ </ol>
20
+ {:else }
21
+ <ul>
22
+ {@render childList(list)}
23
+ </ul>
24
+ {/if}
@@ -0,0 +1,7 @@
1
+ import type { List } from "mdast";
2
+ type $$ComponentProps = {
3
+ list: List;
4
+ };
5
+ declare const ParsnipList: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type ParsnipList = ReturnType<typeof ParsnipList>;
7
+ export default ParsnipList;
@@ -0,0 +1,42 @@
1
+ export interface SimplifiedEntry {
2
+ /**
3
+ * path to the source of data relative to base blog path
4
+ * acts as our ID
5
+ */
6
+ path: string;
7
+ /**
8
+ * url path we want this particular blog to show up in
9
+ */
10
+ slug: string;
11
+ /**
12
+ * url of preview image relative to base blog path
13
+ */
14
+ preview?: string;
15
+ }
16
+ export interface ParsnipEntrySummary extends SimplifiedEntry {
17
+ /**
18
+ * Name of the markdown file or title
19
+ */
20
+ basename: string;
21
+ name: string;
22
+ tags: string[];
23
+ stat: {
24
+ /**
25
+ * unix time
26
+ */
27
+ ctime: number;
28
+ /**
29
+ * unix time
30
+ */
31
+ mtime: number;
32
+ };
33
+ }
34
+ export interface TagEntry {
35
+ name: string;
36
+ entries: SimplifiedEntry[];
37
+ }
38
+ export interface ParsnipOverall {
39
+ files: ParsnipEntrySummary[];
40
+ tags: TagEntry[];
41
+ baseUrl: string;
42
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,10 @@
1
+ <script lang="ts">
2
+ import ParsnipPhrasingChildren from "./ParsnipPhrasingChildren.svelte";
3
+ import { type Paragraph } from "mdast";
4
+ // <!-- determine if we want to wrap it with p or not -->
5
+ const { paragraph }: { paragraph: Paragraph } = $props();
6
+ </script>
7
+
8
+ <p>
9
+ <ParsnipPhrasingChildren phrasingChildren={paragraph.children} />
10
+ </p>
@@ -0,0 +1,7 @@
1
+ import { type Paragraph } from "mdast";
2
+ type $$ComponentProps = {
3
+ paragraph: Paragraph;
4
+ };
5
+ declare const ParsnipParagraph: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type ParsnipParagraph = ReturnType<typeof ParsnipParagraph>;
7
+ export default ParsnipParagraph;
@@ -0,0 +1,26 @@
1
+ <script lang="ts">
2
+ import ParsnipEmbedWikilink from "./ParsnipEmbedWikilink.svelte";
3
+ import ParsnipWikilink from "./ParsnipWikilink.svelte";
4
+ import { type PhrasingContent } from "mdast";
5
+ import Self from "./ParsnipPhrasingChildren.svelte";
6
+
7
+ const { phrasingChildren }: { phrasingChildren: PhrasingContent[] } = $props();
8
+ </script>
9
+
10
+ {#each phrasingChildren as child (child)}
11
+ {#if child.type === 'text'}
12
+ {child.value}
13
+ {:else if child.type === 'strong'}
14
+ <strong>
15
+ <Self phrasingChildren={child.children} />
16
+ </strong>
17
+ {:else if child.type === 'inlineCode'}
18
+ <code class="inline-code">{child.value}</code>
19
+ {:else if child.type === 'embedWikilink'}
20
+ <ParsnipEmbedWikilink wikilink={child} />
21
+ {:else if child.type === 'wikilink'}
22
+ <ParsnipWikilink wikilink={child} />
23
+ {:else }
24
+ {JSON.stringify(child, undefined, 2)}
25
+ {/if}
26
+ {/each}
@@ -0,0 +1,7 @@
1
+ import { type PhrasingContent } from "mdast";
2
+ type $$ComponentProps = {
3
+ phrasingChildren: PhrasingContent[];
4
+ };
5
+ declare const ParsnipPhrasingChildren: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type ParsnipPhrasingChildren = ReturnType<typeof ParsnipPhrasingChildren>;
7
+ export default ParsnipPhrasingChildren;
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { getWebBaseUrl } from "../../util/env-getter";
3
+
4
+ interface Wikilink {
5
+ type: "wikilink",
6
+ value: string;
7
+ fileAccessor: {
8
+ target: string;
9
+ isEmbed: false;
10
+ basePath: string;
11
+ slug: string;
12
+ }
13
+ }
14
+
15
+ const { wikilink }: { wikilink: Wikilink } = $props();
16
+ </script>
17
+
18
+ <!-- todo(turnip): determine appropriate media -->
19
+ <!-- todo(turnip): add alt text -->
20
+ <a href={`${getWebBaseUrl()}/${wikilink.fileAccessor.slug}`}>{wikilink.fileAccessor.target}</a>
@@ -0,0 +1,16 @@
1
+ interface Wikilink {
2
+ type: "wikilink";
3
+ value: string;
4
+ fileAccessor: {
5
+ target: string;
6
+ isEmbed: false;
7
+ basePath: string;
8
+ slug: string;
9
+ };
10
+ }
11
+ type $$ComponentProps = {
12
+ wikilink: Wikilink;
13
+ };
14
+ declare const ParsnipWikilink: import("svelte").Component<$$ComponentProps, {}, "">;
15
+ type ParsnipWikilink = ReturnType<typeof ParsnipWikilink>;
16
+ export default ParsnipWikilink;
@@ -0,0 +1,3 @@
1
+ export { menuPageServerLoad } from "./route-util/menuPageServerLoad";
2
+ export { slugPageServerLoad } from "./route-util/slugPageServerLoad";
3
+ export { default as ParsnipBlog } from "./route-util/ParsnipBlog.svelte";
@@ -0,0 +1,3 @@
1
+ export { menuPageServerLoad } from "./route-util/menuPageServerLoad";
2
+ export { slugPageServerLoad } from "./route-util/slugPageServerLoad";
3
+ export { default as ParsnipBlog } from "./route-util/ParsnipBlog.svelte";
@@ -0,0 +1,28 @@
1
+ <script lang="ts">
2
+ import { OverridableMeta, type PageMeta } from "../../..";
3
+ import ParsnipBlockChildren from "../ParsnipBlockChildren.svelte";
4
+ import type { ParsnipEntry } from "../ParsnipEntry";
5
+ import BlogTemplate from "../../../ui/templates/blog_template/BlogTemplate.svelte";
6
+
7
+ const { parsnipEntry }: { parsnipEntry: ParsnipEntry } = $props();
8
+
9
+ const pageMeta: PageMeta = $derived({
10
+ nestedPages: [],
11
+ relativeLink: "",
12
+ tags: parsnipEntry.tags,
13
+ title: parsnipEntry.basename,
14
+ datePublished: new Date(parsnipEntry.stat.ctime).toLocaleString(),
15
+ lastUpdated: new Date(parsnipEntry.stat.mtime).toLocaleString()
16
+ });
17
+ </script>
18
+
19
+ <OverridableMeta
20
+ title={parsnipEntry.basename}
21
+ ogTitle={parsnipEntry.basename}
22
+ ogDescription=""
23
+ ogImage={parsnipEntry.preview}
24
+ />
25
+
26
+ <BlogTemplate pageMeta={pageMeta}>
27
+ <ParsnipBlockChildren blockChildren={parsnipEntry.ast.ast.children} />
28
+ </BlogTemplate>
@@ -0,0 +1,7 @@
1
+ import type { ParsnipEntry } from "../ParsnipEntry";
2
+ type $$ComponentProps = {
3
+ parsnipEntry: ParsnipEntry;
4
+ };
5
+ declare const ParsnipBlog: import("svelte").Component<$$ComponentProps, {}, "">;
6
+ type ParsnipBlog = ReturnType<typeof ParsnipBlog>;
7
+ export default ParsnipBlog;
@@ -0,0 +1,6 @@
1
+ import type { ParsnipOverall } from "../ParsnipOverall";
2
+ export declare const menuPageServerLoad: () => Promise<{
3
+ parsnipOverall: ParsnipOverall;
4
+ } | {
5
+ parsnipOverall?: undefined;
6
+ }>;
@@ -0,0 +1,14 @@
1
+ import { getCmsBaseUrl } from "../../../util/env-getter";
2
+ export const menuPageServerLoad = async () => {
3
+ const baseUrl = getCmsBaseUrl();
4
+ const post = await fetch(`${baseUrl}/main.meta.json`);
5
+ if (post.ok) {
6
+ return {
7
+ parsnipOverall: {
8
+ ...(await post.json()),
9
+ baseUrl
10
+ }
11
+ };
12
+ }
13
+ return {};
14
+ };
@@ -0,0 +1,8 @@
1
+ import type { ParsnipEntry } from "../ParsnipEntry";
2
+ export declare const slugPageServerLoad: ({ params }: {
3
+ params: {
4
+ slug: string;
5
+ };
6
+ }) => Promise<{
7
+ parsnipEntry: ParsnipEntry;
8
+ }>;
@@ -0,0 +1,24 @@
1
+ import { getCmsBaseUrl } from "../../../util/env-getter";
2
+ import { error } from "@sveltejs/kit";
3
+ export const slugPageServerLoad = async ({ params }) => {
4
+ const baseUrl = getCmsBaseUrl();
5
+ const mainMeta = await fetch(`${baseUrl}/main.meta.json`);
6
+ if (!mainMeta.ok) {
7
+ error(400, "Not found");
8
+ }
9
+ const parsnipOverall = {
10
+ ...(await mainMeta.json()),
11
+ baseUrl
12
+ };
13
+ const entryMeta = parsnipOverall.files.find(f => f.slug === params.slug);
14
+ if (!entryMeta) {
15
+ error(400, "Not found");
16
+ }
17
+ const entryResponse = await fetch(`${baseUrl}/${entryMeta.path}`);
18
+ if (!entryResponse.ok) {
19
+ error(400, "Not found");
20
+ }
21
+ return {
22
+ parsnipEntry: await entryResponse.json()
23
+ };
24
+ };
@@ -297,7 +297,7 @@ export const urlPatterns: Array<{
297
297
  export let serverAsyncLocalStorage: ParaglideAsyncLocalStorage | undefined;
298
298
  export const disableAsyncLocalStorage: false;
299
299
  export const experimentalMiddlewareLocaleSplitting: false;
300
- export const isServer: any;
300
+ export const isServer: boolean;
301
301
  /**
302
302
  * Get the current locale.
303
303
  *
@@ -81,6 +81,16 @@ html.dark .shiki span {
81
81
  text-decoration: var(--shiki-dark-text-decoration) !important;
82
82
  }
83
83
 
84
+ .inline-code {
85
+ background-color: aliceblue;
86
+ padding: 0.2rem;
87
+ border-radius: 0.2rem;
88
+ }
89
+
90
+ html.dark .inline-code {
91
+ background-color: #303446;
92
+ }
93
+
84
94
  .shiki {
85
95
  span {
86
96
  white-space: pre-wrap;
@@ -138,4 +148,4 @@ pre button.copy {
138
148
  }
139
149
  }
140
150
 
141
- /* endregion shiki copy button */
151
+ /* endregion shiki copy button */
@@ -251,7 +251,7 @@ blockquote {
251
251
  }
252
252
 
253
253
  h1, h2, h3, h4, h5, h6, .fake-h1, .fake-h2, .fake-h3, .fake-h4 {
254
- text-align: center;
254
+ text-align: start;
255
255
  margin-top: 0;
256
256
  font-weight: bolder;
257
257
  color: var(--color-primary-900);
@@ -261,6 +261,10 @@ h1, h2, h3, h4, h5, h6, .fake-h1, .fake-h2, .fake-h3, .fake-h4 {
261
261
  }
262
262
  }
263
263
 
264
+ h1 {
265
+ text-align: center;
266
+ }
267
+
264
268
  h1 + p, h2 + p, h3 + p, h4 + p, h5 + p, h6 + p, .fake-h2 + p, .fake-h3 + p, .fake-h4 + p {
265
269
  margin-top: 0.5lh;
266
270
  }
@@ -328,6 +332,10 @@ ol {
328
332
  list-style: decimal inside;
329
333
  }
330
334
 
335
+ li > ul, li > ol {
336
+ margin-inline-start: 2em;
337
+ }
338
+
331
339
  p {
332
340
  @apply mb-3;
333
341
  }
@@ -335,3 +343,4 @@ p {
335
343
  @theme {
336
344
  --color-secondary-0: oklch(99% 0.02 38.38deg);
337
345
  }
346
+
@@ -16,15 +16,6 @@
16
16
  pageSize = $bindable()
17
17
  }: Props = $props();
18
18
 
19
- const queryIndex = page.url.searchParams.get("index");
20
- if (queryIndex) {
21
- currentIndex = parseInt(queryIndex) || 0;
22
- }
23
- const queryPageSize = page.url.searchParams.get("pageSize");
24
- if (queryPageSize) {
25
- pageSize = parseInt(queryPageSize) || 5;
26
- }
27
-
28
19
  const movePage = (isNext: boolean) => {
29
20
  if (isNext) {
30
21
  currentIndex = currentIndex + 1;
@@ -38,6 +29,15 @@
38
29
  };
39
30
 
40
31
  onMount(() => {
32
+ const queryIndex = page.url.searchParams.get("index");
33
+ if (queryIndex) {
34
+ currentIndex = parseInt(queryIndex) || 0;
35
+ }
36
+ const queryPageSize = page.url.searchParams.get("pageSize");
37
+ if (queryPageSize) {
38
+ pageSize = parseInt(queryPageSize) || 5;
39
+ }
40
+
41
41
  const query = new URLSearchParams(page.url.searchParams.toString());
42
42
  query.set("index", currentIndex.toString());
43
43
  query.set("pageSize", pageSize.toString());
@@ -71,4 +71,4 @@
71
71
  justify-content: space-between;
72
72
  align-items: center;
73
73
  }
74
- </style>
74
+ </style>
@@ -1,6 +1,12 @@
1
1
  <script lang="ts">
2
+ import type { ParsnipOverall } from "../../../modules/parsnip/ParsnipOverall";
2
3
  import NavigationControl from "./NavigationControl.svelte";
3
- import { parsePageMeta, type ParsePageMetaCompareFn } from "./PageMeta";
4
+ import {
5
+ DefaultPageMetaSorter,
6
+ type PageMeta,
7
+ parsePageMeta,
8
+ type ParsePageMetaCompareFn
9
+ } from "./PageMeta";
4
10
  import { PinyaCard } from "../../elements/index";
5
11
  import { localizeHref } from "../../../paraglide/runtime.js";
6
12
 
@@ -18,6 +24,7 @@
18
24
  compareFn?: undefined | ParsePageMetaCompareFn;
19
25
  pageSize?: number;
20
26
  currentIndex?: number;
27
+ parsnipOverall?: ParsnipOverall;
21
28
  }
22
29
 
23
30
  let {
@@ -30,10 +37,30 @@
30
37
  allowUpperControl = true,
31
38
  compareFn = undefined,
32
39
  pageSize = $bindable(5),
33
- currentIndex = $bindable(0)
40
+ currentIndex = $bindable(0),
41
+ parsnipOverall = undefined
34
42
  }: Props = $props();
35
43
 
36
- const pageFlatList = $state(parsePageMeta(fileList, jsonList, imageMap, compareFn));
44
+ const fileBasedList = parsePageMeta(fileList, jsonList, imageMap, compareFn);
45
+ const parsnipBasedList = parsnipOverall?.files.map(pf => {
46
+ const meta: PageMeta = {
47
+ title: pf.basename,
48
+ nestedPages: [],
49
+ relativeLink: pf.slug,
50
+ tags: pf.tags,
51
+ imageUrl: pf.preview ? `${parsnipOverall.baseUrl}/${pf.preview}` : undefined,
52
+ datePublished: pf.stat.ctime ? new Date(pf.stat.ctime).toISOString().split("T")[0] : undefined,
53
+ lastUpdated: pf.stat.mtime ? new Date(pf.stat.mtime).toISOString().split("T")[0] : undefined
54
+ };
55
+ return meta;
56
+ }) ?? [];
57
+ const pageFlatList = fileBasedList.concat(parsnipBasedList);
58
+
59
+ if (compareFn) {
60
+ pageFlatList.sort(compareFn);
61
+ } else {
62
+ pageFlatList.sort(DefaultPageMetaSorter);
63
+ }
37
64
 
38
65
  let visiblePages = $derived(pageFlatList.slice(currentIndex * pageSize, (currentIndex * pageSize) + pageSize));
39
66
  </script>
@@ -60,8 +87,9 @@
60
87
  <div class="navigation-component">
61
88
  <!-- all the misc routes-->
62
89
  {#each visiblePages as pageMeta (pageMeta.title)}
63
- {@const fullPath=`${parentSubpath}${pageMeta.relativeLink}`}
64
- <a href={localizeHref(fullPath)} class="card-anchor a-as-btn">
90
+ {@const fullPath = `${parentSubpath}${pageMeta.relativeLink}`}
91
+ <!-- thank you so much to https://www.reddit.com/r/sveltejs/comments/yoe6in/comment/jvaj1ez -->
92
+ <a href={localizeHref(fullPath)} class="card-anchor a-as-btn" data-sveltekit-reload>
65
93
  <PinyaCard
66
94
  widthClass="w-full"
67
95
  className="navigation-element"
@@ -89,7 +117,7 @@
89
117
 
90
118
  {#if visiblePages.length === 0}
91
119
  <PinyaCard>
92
- <p class="default-card">Sorry, no content was found</p>
120
+ <p class="default-card">Sorry, no content was found</p>
93
121
  </PinyaCard>
94
122
  {/if}
95
123
  </div>
@@ -167,7 +195,7 @@
167
195
  flex-direction: column;
168
196
  max-width: 1000px;
169
197
  width: 100%;
170
- gap: 1lh;
198
+ gap: 1lh;
171
199
  }
172
200
 
173
201
  .tag-container {
@@ -175,23 +203,23 @@
175
203
  }
176
204
 
177
205
  a.card-anchor {
178
- filter: none;
206
+ filter: none;
179
207
  }
180
208
 
181
209
  :global(.navigation-element) {
182
- transition: 0.3s;
210
+ transition: 0.3s;
183
211
  }
184
212
 
185
213
  :global(.navigation-element:hover) {
186
214
  transform: scale(1.02);
187
- box-shadow: 10px 5px 5px rgba(49, 8, 0, 0.25);
215
+ box-shadow: 10px 5px 5px rgba(49, 8, 0, 0.25);
188
216
  }
189
217
 
190
218
  :global(.dark .navigation-element:hover) {
191
- box-shadow: 10px 5px 5px rgba(16, 0, 0, 0.35);
219
+ box-shadow: 10px 5px 5px rgba(16, 0, 0, 0.35);
192
220
  }
193
221
 
194
222
  h2 {
195
- text-align: start;
223
+ text-align: start;
196
224
  }
197
- </style>
225
+ </style>
@@ -1,3 +1,4 @@
1
+ import type { ParsnipOverall } from "../../../modules/parsnip/ParsnipOverall";
1
2
  import { type ParsePageMetaCompareFn } from "./PageMeta";
2
3
  interface Props {
3
4
  fileList: Record<string, unknown>;
@@ -13,6 +14,7 @@ interface Props {
13
14
  compareFn?: undefined | ParsePageMetaCompareFn;
14
15
  pageSize?: number;
15
16
  currentIndex?: number;
17
+ parsnipOverall?: ParsnipOverall;
16
18
  }
17
19
  declare const NavigationMenu: import("svelte").Component<Props, {}, "currentIndex" | "pageSize">;
18
20
  type NavigationMenu = ReturnType<typeof NavigationMenu>;
@@ -39,6 +39,9 @@ export const parsePageMeta = (fileList, jsonList, imageMap, compareFn) => {
39
39
  }
40
40
  });
41
41
  for (const path in fileList) {
42
+ if (path.includes('[...')) {
43
+ continue;
44
+ }
42
45
  const pathEnd = path.split("../").pop();
43
46
  const pathParts = pathEnd.split("/");
44
47
  pathParts.pop();
@@ -1,7 +1,3 @@
1
- .article-content p {
2
- text-indent: 2em;
3
- }
4
-
5
1
  .article-content > * {
6
2
  margin-bottom: 0.5lh;
7
3
  }
@@ -0,0 +1,2 @@
1
+ export declare const getCmsBaseUrl: () => any;
2
+ export declare const getWebBaseUrl: () => any;
@@ -0,0 +1,2 @@
1
+ export const getCmsBaseUrl = () => import.meta.env.VITE_PARSNIP_BASE_URL ?? 'https://gitlab.com/turnipxenon-personal/test-obdisian/-/raw/main';
2
+ export const getWebBaseUrl = () => import.meta.env.VITE_WEB_BASE_URL ?? '/pineapple';
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": "4.0.0-alpha.3",
4
+ "version": "4.1.0",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
7
7
  "build": "vite build && yarn package",
@@ -15,9 +15,12 @@
15
15
  "custom-check": "npx vite-node src/lib/scripts/util/ManualCheckRun.ts",
16
16
  "preview": "vite preview",
17
17
  "prepublishOnly": "yarn package",
18
- "to-dev": "git checkout main && git pull origin main && git branch -d turnip/dev && git checkout -b turnip/dev"
18
+ "to-dev": "git checkout main && git pull origin main && git branch -d turnip/dev && git checkout -b turnip/dev",
19
+ "prepare": "husky"
19
20
  },
20
21
  "devDependencies": {
22
+ "@commitlint/cli": "^19.8.0",
23
+ "@commitlint/config-conventional": "^19.8.0",
21
24
  "@eslint/compat": "^1.2.5",
22
25
  "@eslint/js": "^9.18.0",
23
26
  "@sveltejs/adapter-auto": "^4.0.0",
@@ -27,7 +30,10 @@
27
30
  "eslint-config-prettier": "^10.0.1",
28
31
  "eslint-plugin-svelte": "^3.0.0",
29
32
  "globals": "^16.0.0",
33
+ "husky": "^9.1.7",
30
34
  "madge": "^8.0.0",
35
+ "mdast": "^3.0.0",
36
+ "mdast-util-from-markdown": "^1.0.2",
31
37
  "prettier": "^3.4.2",
32
38
  "prettier-plugin-svelte": "^3.3.3",
33
39
  "prettier-plugin-tailwindcss": "^0.6.11",
@@ -81,6 +81,16 @@ html.dark .shiki span {
81
81
  text-decoration: var(--shiki-dark-text-decoration) !important;
82
82
  }
83
83
 
84
+ .inline-code {
85
+ background-color: aliceblue;
86
+ padding: 0.2rem;
87
+ border-radius: 0.2rem;
88
+ }
89
+
90
+ html.dark .inline-code {
91
+ background-color: #303446;
92
+ }
93
+
84
94
  .shiki {
85
95
  span {
86
96
  white-space: pre-wrap;
@@ -138,4 +148,4 @@ pre button.copy {
138
148
  }
139
149
  }
140
150
 
141
- /* endregion shiki copy button */
151
+ /* endregion shiki copy button */