@turnipxenon/pineapple 4.0.0 → 4.1.1
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/modules/parsnip/ParsnipBlockChildren.svelte +37 -0
- package/dist/modules/parsnip/ParsnipBlockChildren.svelte.d.ts +8 -0
- package/dist/modules/parsnip/ParsnipEmbedWikilink.svelte +19 -0
- package/dist/modules/parsnip/ParsnipEmbedWikilink.svelte.d.ts +15 -0
- package/dist/modules/parsnip/ParsnipEntry.d.ts +7 -0
- package/dist/modules/parsnip/ParsnipEntry.js +1 -0
- package/dist/modules/parsnip/ParsnipHeading.svelte +21 -0
- package/dist/modules/parsnip/ParsnipHeading.svelte.d.ts +7 -0
- package/dist/modules/parsnip/ParsnipList.svelte +24 -0
- package/dist/modules/parsnip/ParsnipList.svelte.d.ts +7 -0
- package/dist/modules/parsnip/ParsnipOverall.d.ts +42 -0
- package/dist/modules/parsnip/ParsnipOverall.js +1 -0
- package/dist/modules/parsnip/ParsnipParagraph.svelte +10 -0
- package/dist/modules/parsnip/ParsnipParagraph.svelte.d.ts +7 -0
- package/dist/modules/parsnip/ParsnipPhrasingChildren.svelte +26 -0
- package/dist/modules/parsnip/ParsnipPhrasingChildren.svelte.d.ts +7 -0
- package/dist/modules/parsnip/ParsnipWikilink.svelte +20 -0
- package/dist/modules/parsnip/ParsnipWikilink.svelte.d.ts +16 -0
- package/dist/modules/parsnip/index.d.ts +3 -0
- package/dist/modules/parsnip/index.js +3 -0
- package/dist/modules/parsnip/route-util/ParsnipBlog.svelte +28 -0
- package/dist/modules/parsnip/route-util/ParsnipBlog.svelte.d.ts +7 -0
- package/dist/modules/parsnip/route-util/menuPageServerLoad.d.ts +6 -0
- package/dist/modules/parsnip/route-util/menuPageServerLoad.js +14 -0
- package/dist/modules/parsnip/route-util/slugPageServerLoad.d.ts +8 -0
- package/dist/modules/parsnip/route-util/slugPageServerLoad.js +24 -0
- package/dist/paraglide/runtime.d.ts +1 -1
- package/dist/styles/app.css +11 -1
- package/dist/styles/turnip-theme.css +6 -1
- package/dist/ui/modules/NavigationMenu/NavigationControl.svelte +10 -10
- package/dist/ui/modules/NavigationMenu/NavigationMenu.svelte +43 -13
- package/dist/ui/modules/NavigationMenu/NavigationMenu.svelte.d.ts +3 -0
- package/dist/ui/modules/NavigationMenu/PageMeta.js +3 -0
- package/dist/ui/templates/blog_template/blog-template.css +0 -4
- package/dist/util/env-getter.d.ts +2 -0
- package/dist/util/env-getter.js +2 -0
- package/package.json +8 -2
- 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 @@
|
|
|
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,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,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,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,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:
|
|
300
|
+
export const isServer: boolean;
|
|
301
301
|
/**
|
|
302
302
|
* Get the current locale.
|
|
303
303
|
*
|
package/dist/styles/app.css
CHANGED
|
@@ -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:
|
|
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
|
}
|
|
@@ -339,3 +343,4 @@ p {
|
|
|
339
343
|
@theme {
|
|
340
344
|
--color-secondary-0: oklch(99% 0.02 38.38deg);
|
|
341
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 {
|
|
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,8 @@
|
|
|
18
24
|
compareFn?: undefined | ParsePageMetaCompareFn;
|
|
19
25
|
pageSize?: number;
|
|
20
26
|
currentIndex?: number;
|
|
27
|
+
parsnipOverall?: ParsnipOverall;
|
|
28
|
+
parsnipBasePath?: string;
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
let {
|
|
@@ -30,10 +38,31 @@
|
|
|
30
38
|
allowUpperControl = true,
|
|
31
39
|
compareFn = undefined,
|
|
32
40
|
pageSize = $bindable(5),
|
|
33
|
-
currentIndex = $bindable(0)
|
|
41
|
+
currentIndex = $bindable(0),
|
|
42
|
+
parsnipOverall = undefined,
|
|
43
|
+
parsnipBasePath = '',
|
|
34
44
|
}: Props = $props();
|
|
35
45
|
|
|
36
|
-
const
|
|
46
|
+
const fileBasedList = parsePageMeta(fileList, jsonList, imageMap, compareFn);
|
|
47
|
+
const parsnipBasedList = parsnipOverall?.files.map(pf => {
|
|
48
|
+
const meta: PageMeta = {
|
|
49
|
+
title: pf.basename,
|
|
50
|
+
nestedPages: [],
|
|
51
|
+
relativeLink: `${parsnipBasePath}${pf.slug}`,
|
|
52
|
+
tags: pf.tags,
|
|
53
|
+
imageUrl: pf.preview ? `${parsnipOverall.baseUrl}/${pf.preview}` : undefined,
|
|
54
|
+
datePublished: pf.stat.ctime ? new Date(pf.stat.ctime).toISOString().split("T")[0] : undefined,
|
|
55
|
+
lastUpdated: pf.stat.mtime ? new Date(pf.stat.mtime).toISOString().split("T")[0] : undefined
|
|
56
|
+
};
|
|
57
|
+
return meta;
|
|
58
|
+
}) ?? [];
|
|
59
|
+
const pageFlatList = fileBasedList.concat(parsnipBasedList);
|
|
60
|
+
|
|
61
|
+
if (compareFn) {
|
|
62
|
+
pageFlatList.sort(compareFn);
|
|
63
|
+
} else {
|
|
64
|
+
pageFlatList.sort(DefaultPageMetaSorter);
|
|
65
|
+
}
|
|
37
66
|
|
|
38
67
|
let visiblePages = $derived(pageFlatList.slice(currentIndex * pageSize, (currentIndex * pageSize) + pageSize));
|
|
39
68
|
</script>
|
|
@@ -60,8 +89,9 @@
|
|
|
60
89
|
<div class="navigation-component">
|
|
61
90
|
<!-- all the misc routes-->
|
|
62
91
|
{#each visiblePages as pageMeta (pageMeta.title)}
|
|
63
|
-
{@const fullPath
|
|
64
|
-
|
|
92
|
+
{@const fullPath = `${parentSubpath}${pageMeta.relativeLink}`}
|
|
93
|
+
<!-- thank you so much to https://www.reddit.com/r/sveltejs/comments/yoe6in/comment/jvaj1ez -->
|
|
94
|
+
<a href={localizeHref(fullPath)} class="card-anchor a-as-btn" data-sveltekit-reload>
|
|
65
95
|
<PinyaCard
|
|
66
96
|
widthClass="w-full"
|
|
67
97
|
className="navigation-element"
|
|
@@ -89,7 +119,7 @@
|
|
|
89
119
|
|
|
90
120
|
{#if visiblePages.length === 0}
|
|
91
121
|
<PinyaCard>
|
|
92
|
-
|
|
122
|
+
<p class="default-card">Sorry, no content was found</p>
|
|
93
123
|
</PinyaCard>
|
|
94
124
|
{/if}
|
|
95
125
|
</div>
|
|
@@ -167,7 +197,7 @@
|
|
|
167
197
|
flex-direction: column;
|
|
168
198
|
max-width: 1000px;
|
|
169
199
|
width: 100%;
|
|
170
|
-
|
|
200
|
+
gap: 1lh;
|
|
171
201
|
}
|
|
172
202
|
|
|
173
203
|
.tag-container {
|
|
@@ -175,23 +205,23 @@
|
|
|
175
205
|
}
|
|
176
206
|
|
|
177
207
|
a.card-anchor {
|
|
178
|
-
|
|
208
|
+
filter: none;
|
|
179
209
|
}
|
|
180
210
|
|
|
181
211
|
:global(.navigation-element) {
|
|
182
|
-
|
|
212
|
+
transition: 0.3s;
|
|
183
213
|
}
|
|
184
214
|
|
|
185
215
|
:global(.navigation-element:hover) {
|
|
186
216
|
transform: scale(1.02);
|
|
187
|
-
|
|
217
|
+
box-shadow: 10px 5px 5px rgba(49, 8, 0, 0.25);
|
|
188
218
|
}
|
|
189
219
|
|
|
190
220
|
:global(.dark .navigation-element:hover) {
|
|
191
|
-
|
|
221
|
+
box-shadow: 10px 5px 5px rgba(16, 0, 0, 0.35);
|
|
192
222
|
}
|
|
193
223
|
|
|
194
224
|
h2 {
|
|
195
|
-
|
|
225
|
+
text-align: start;
|
|
196
226
|
}
|
|
197
|
-
</style>
|
|
227
|
+
</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,8 @@ interface Props {
|
|
|
13
14
|
compareFn?: undefined | ParsePageMetaCompareFn;
|
|
14
15
|
pageSize?: number;
|
|
15
16
|
currentIndex?: number;
|
|
17
|
+
parsnipOverall?: ParsnipOverall;
|
|
18
|
+
parsnipBasePath?: string;
|
|
16
19
|
}
|
|
17
20
|
declare const NavigationMenu: import("svelte").Component<Props, {}, "currentIndex" | "pageSize">;
|
|
18
21
|
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();
|
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.
|
|
4
|
+
"version": "4.1.1",
|
|
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",
|
package/src/lib/styles/app.css
CHANGED
|
@@ -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 */
|