Mdsvex Posts, posts Api. config
This commit is contained in:
parent
4fa47b2ac3
commit
e4dc0e56cc
|
@ -57,4 +57,7 @@ public/api/vendor
|
|||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/blob-report/
|
||||
/playwright/.cache/
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
import { defineMDSveXConfig as defineConfig } from 'mdsvex';
|
||||
import headings from 'remark-autolink-headings';
|
||||
import remarkExternalLinks from 'remark-external-links';
|
||||
import slug from 'remark-slug';
|
||||
import remarkSetImagePath from './src/lib/utils/remark-set-image-path.js';
|
||||
import remarkLinkWithImageAsOnlyChild from './src/lib/utils/remark-link-with-image-as-only-child.js';
|
||||
import remarkHeadingsPermaLinks from './src/lib/utils/remark-headings-permalinks.js';
|
||||
import { toString } from 'mdast-util-to-string';
|
||||
import rehypeWrap from 'rehype-wrap-all';
|
||||
import rehypeImgSize from 'rehype-img-size';
|
||||
import { h } from 'hastscript';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import remarkToc from 'remark-toc';
|
||||
import getHeadings from './src/lib/utils/get-headings.js';
|
||||
// import { highlightCode } from './src/lib/utils/highlighter.js';
|
||||
|
||||
/** @type {import('mdsvex').MdsvexOptions} */
|
||||
const config = defineConfig({
|
||||
extensions: ['.svelte.md', '.md', '.svx'],
|
||||
smartypants: {
|
||||
dashes: 'oldschool'
|
||||
},
|
||||
// Wait for skeleton to implement Prismjs, for now use <CodeBlock /> in .md files
|
||||
// highlight: {},
|
||||
// layout: {
|
||||
// blog: './src/lib/components/blog/_blog-layout.svelte',
|
||||
// project: './src/lib/components/projects/_project-layout.svelte',
|
||||
// _: './src/lib/components/fallback/_layout.svelte'
|
||||
// },
|
||||
rehypePlugins: [
|
||||
[rehypeWrap, { selector: 'table', wrapper: 'div.overflow-auto' }],
|
||||
[rehypeImgSize, { dir: './static' }],
|
||||
[
|
||||
/** Custom rehype plugin to add loading="lazy" to all images */
|
||||
() => {
|
||||
return (tree) => {
|
||||
visit(tree, 'element', (node) => {
|
||||
if (node.tagName === 'img') {
|
||||
node.properties.loading = 'lazy';
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
]
|
||||
],
|
||||
remarkPlugins: [
|
||||
[remarkToc, { maxDepth: 3, tight: true }][
|
||||
(remarkExternalLinks,
|
||||
{
|
||||
target: '_blank'
|
||||
})
|
||||
],
|
||||
slug,
|
||||
[
|
||||
headings,
|
||||
{
|
||||
behavior: 'append',
|
||||
linkProperties: {},
|
||||
content: function (node) {
|
||||
return [
|
||||
h('span.icon.icon-link header-anchor', {
|
||||
ariaLabel: toString(node) + ' permalink'
|
||||
})
|
||||
];
|
||||
}
|
||||
}
|
||||
],
|
||||
remarkSetImagePath,
|
||||
remarkLinkWithImageAsOnlyChild,
|
||||
remarkHeadingsPermaLinks,
|
||||
getHeadings
|
||||
]
|
||||
});
|
||||
|
||||
export default config;
|
152
package.json
152
package.json
|
@ -1,76 +1,80 @@
|
|||
{
|
||||
"name": "portfolio",
|
||||
"description": "Uses pnpm, svelte, mdsvex",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"homepage": "mattmor.in",
|
||||
"author": "Matthieu Morin",
|
||||
"license": "AGPLv3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/matthieu42morin/Portfolio/"
|
||||
},
|
||||
"packageManager": "pnpm@8.6.6",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"test": "vitest",
|
||||
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
||||
"format": "prettier --plugin-search-dir . --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@skeletonlabs/skeleton": "2.0.0",
|
||||
"@skeletonlabs/tw-plugin": "0.1.0",
|
||||
"@sveltejs/adapter-cloudflare": "^2.3.3",
|
||||
"@sveltejs/kit": "^1.20.4",
|
||||
"@tailwindcss/forms": "0.5.6",
|
||||
"@tailwindcss/typography": "0.5.9",
|
||||
"@types/js-cookie": "^3.0.5",
|
||||
"@types/node": "20.5.7",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"autoprefixer": "10.4.15",
|
||||
"emoji-regex": "^10.3.0",
|
||||
"eslint": "^8.28.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-svelte": "^2.30.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
"postcss": "8.4.29",
|
||||
"prettier": "^2.8.0",
|
||||
"prettier-plugin-svelte": "^2.10.1",
|
||||
"sass": "^1.66.1",
|
||||
"svelte": "^4.0.5",
|
||||
"svelte-check": "^3.4.3",
|
||||
"tailwindcss": "3.3.3",
|
||||
"tslib": "^2.4.1",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.4.2",
|
||||
"vite-plugin-tailwind-purgecss": "0.1.3",
|
||||
"vitest": "^0.34.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "1.5.1",
|
||||
"@threlte/core": "^6.0.10",
|
||||
"@threlte/extras": "^7.0.0",
|
||||
"@yushijinhun/three-minifier-rollup": "^0.4.0",
|
||||
"hastscript": "^8.0.0",
|
||||
"highlight.js": "11.8.0",
|
||||
"linkedom": "^0.15.3",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"mdsvex": "^0.11.0",
|
||||
"prismjs": "^1.29.0",
|
||||
"rehype-img-size": "^1.0.1",
|
||||
"rehype-wrap-all": "^1.1.0",
|
||||
"remark-autolink-headings": "^7.0.1",
|
||||
"remark-external-links": "^9.0.1",
|
||||
"remark-slug": "^7.0.1",
|
||||
"rss": "^1.2.2",
|
||||
"svelte-preprocess": "^5.0.4",
|
||||
"unist-util-visit": "^5.0.0"
|
||||
},
|
||||
"type": "module"
|
||||
"name": "portfolio",
|
||||
"description": "Uses pnpm, svelte, mdsvex",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"private": true,
|
||||
"homepage": "mattmor.in",
|
||||
"author": "Matthieu Morin",
|
||||
"license": "AGPLv3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/matthieu42morin/Portfolio/"
|
||||
},
|
||||
"packageManager": "pnpm@8.6.6",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"test": "vitest",
|
||||
"lint": "prettier --plugin-search-dir . --check . && eslint .",
|
||||
"format": "prettier --plugin-search-dir . --write .",
|
||||
"test-ct": "playwright test -c playwright-ct.config.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/experimental-ct-svelte": "^1.39.0",
|
||||
"@skeletonlabs/skeleton": "2.0.0",
|
||||
"@skeletonlabs/tw-plugin": "0.1.0",
|
||||
"@sveltejs/adapter-cloudflare": "^2.3.3",
|
||||
"@sveltejs/kit": "^1.27.3",
|
||||
"@tailwindcss/forms": "0.5.6",
|
||||
"@tailwindcss/typography": "0.5.9",
|
||||
"@types/js-cookie": "^3.0.5",
|
||||
"@types/node": "20.5.7",
|
||||
"@types/prismjs": "^1.26.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.62.0",
|
||||
"@typescript-eslint/parser": "^5.62.0",
|
||||
"autoprefixer": "10.4.15",
|
||||
"emoji-regex": "^10.3.0",
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-prettier": "^8.10.0",
|
||||
"eslint-plugin-svelte": "^2.34.1",
|
||||
"hastscript": "^8.0.0",
|
||||
"js-cookie": "^3.0.5",
|
||||
"mdast-util-to-string": "^4.0.0",
|
||||
"mdsvex": "^0.11.0",
|
||||
"postcss": "8.4.29",
|
||||
"prettier": "^2.8.8",
|
||||
"prettier-plugin-svelte": "^2.10.1",
|
||||
"rehype-img-size": "^1.0.1",
|
||||
"rehype-wrap-all": "^1.1.0",
|
||||
"remark-autolink-headings": "^7.0.1",
|
||||
"remark-external-links": "^9.0.1",
|
||||
"remark-slug": "^7.0.1",
|
||||
"sass": "^1.69.5",
|
||||
"svelte": "^4.2.2",
|
||||
"svelte-check": "^3.5.2",
|
||||
"tailwindcss": "3.3.3",
|
||||
"tslib": "^2.6.2",
|
||||
"typescript": "^5.2.2",
|
||||
"unist-util-visit": "^5.0.0",
|
||||
"vite": "^4.5.0",
|
||||
"vite-plugin-tailwind-purgecss": "0.1.3",
|
||||
"vitest": "^0.34.6"
|
||||
},
|
||||
"dependencies": {
|
||||
"@floating-ui/dom": "1.5.1",
|
||||
"@threlte/core": "^6.1.0",
|
||||
"@threlte/extras": "^7.5.0",
|
||||
"@yushijinhun/three-minifier-rollup": "^0.4.0",
|
||||
"highlight.js": "11.8.0",
|
||||
"linkedom": "^0.15.6",
|
||||
"prismjs": "^1.29.0",
|
||||
"remark-toc": "^9.0.0",
|
||||
"rss": "^1.2.2",
|
||||
"svelte-preprocess": "^5.0.4"
|
||||
},
|
||||
"type": "module"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
import { defineConfig, devices } from '@playwright/experimental-ct-svelte';
|
||||
|
||||
/**
|
||||
* See https://playwright.dev/docs/test-configuration.
|
||||
*/
|
||||
export default defineConfig({
|
||||
testDir: './',
|
||||
/* The base directory, relative to the config file, for snapshot files created with toMatchSnapshot and toHaveScreenshot. */
|
||||
snapshotDir: './__snapshots__',
|
||||
/* Maximum time one test can run for. */
|
||||
timeout: 10 * 1000,
|
||||
/* Run tests in files in parallel */
|
||||
fullyParallel: true,
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: !!process.env.CI,
|
||||
/* Retry on CI only */
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
/* Opt out of parallel tests on CI. */
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: 'html',
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
trace: 'on-first-retry',
|
||||
|
||||
/* Port to use for Playwright component endpoint. */
|
||||
ctPort: 3100,
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
],
|
||||
});
|
1067
pnpm-lock.yaml
1067
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
|||
<script lang="ts">
|
||||
import { formatDate } from '$src/content/utils';
|
||||
import '$lib/assets/prism-nord.css';
|
||||
|
||||
export let baseUrl: string;
|
||||
export let imagesDirectoryName: string;
|
||||
|
||||
export let date: string = '';
|
||||
export let slug: string = '';
|
||||
export let title: string;
|
||||
export let image: string;
|
||||
export let teaserImage: string;
|
||||
export let tags: string[] = [];
|
||||
</script>
|
||||
|
||||
<article>
|
||||
<div class="flex justify-center mt-4 mb-8">
|
||||
<div class="w-full lg:w-[50rem] leading-[177.7%]">
|
||||
<img
|
||||
src="/images/{imagesDirectoryName}/{slug}/{teaserImage || image}"
|
||||
alt={`${title}`}
|
||||
class="max-h-[540px] rounded-tl-2xl rounded-tr-[1.3rem]"
|
||||
/>
|
||||
<div
|
||||
class="prose prose-img:rounded-tl-2xl prose-img:rounded-tr-[1.3rem] max-w-none text-base"
|
||||
>
|
||||
<p class="{tags && tags.length > 0 ? '!mb-2' : '!mb-2'} mt-8 text-base">
|
||||
{formatDate(date)}
|
||||
</p>
|
||||
{#if tags && tags.length > 0}
|
||||
<div class="flex mb-2 items-center gap-2">
|
||||
{#each tags as tag}
|
||||
<a
|
||||
data-sveltekit-preload-data="hover"
|
||||
href="/blog?{new URLSearchParams({ tag }).toString()}"
|
||||
>
|
||||
<span class="chip variant-ghost-surface">{tag}</span>
|
||||
</a>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<style lang="postcss">
|
||||
.prose :global(nav.toc) {
|
||||
@apply hidden;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,82 @@
|
|||
<script lang="ts">
|
||||
import { isAnExternalLink } from '$lib/utils/helpers';
|
||||
import type { BlogPost } from '$lib/types/blog';
|
||||
|
||||
export let post: BlogPost;
|
||||
export let isMostRecent: boolean = false;
|
||||
export let type: 'blog';
|
||||
export let layout: 'row' | 'column' = 'column';
|
||||
export let published: boolean = true;
|
||||
export let headlineOrder: 'h3' | '' = '';
|
||||
export let badge: string = '';
|
||||
export let textWidth: string = '';
|
||||
|
||||
const generateURL = (href?: string, slug?: string) => {
|
||||
if (href) return href;
|
||||
return `/${type}/${slug}`;
|
||||
};
|
||||
|
||||
$: href = generateURL(post['href'], post.slug);
|
||||
|
||||
$: target = post && post['href'] && isAnExternalLink(post['href']) ? '_blank' : undefined;
|
||||
</script>
|
||||
|
||||
<a
|
||||
{href}
|
||||
{target}
|
||||
data-sveltekit-preload-data="hover"
|
||||
class="card"
|
||||
data-analytics={`{"context":"grid","variant":"preview"}`}
|
||||
>
|
||||
<div class="w-full text-token grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<!-- Detailed -->
|
||||
<a
|
||||
class="card bg-gradient-to-br variant-gradient-tertiary-primary card-hover overflow-hidden"
|
||||
href="/blog/{post.slug}"
|
||||
>
|
||||
<header>
|
||||
<img
|
||||
src="/images/blog/{post.slug}/{post.image}"
|
||||
class="bg-black/50 w-full aspect-[21/9]"
|
||||
alt="Post"
|
||||
/>
|
||||
</header>
|
||||
<div class="p-4 space-y-4">
|
||||
<h6 class="text-2" data-toc-ignore>
|
||||
<div class="items-center flex gap-2">
|
||||
{#if post.tags}
|
||||
{#each post.tags as tag}
|
||||
<span class="chip variant-ghost-surface">{tag}</span>
|
||||
{/each}
|
||||
{/if}
|
||||
</div>
|
||||
</h6>
|
||||
<h3 class="h3" data-toc-ignore>{post.title}</h3>
|
||||
<article>
|
||||
<p>
|
||||
<!-- cspell:disable -->
|
||||
{post.excerpt}
|
||||
<!-- cspell:enable -->
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
<hr class="opacity-50" />
|
||||
<footer class="p-4 flex justify-start items-center space-x-4">
|
||||
<div class="flex-auto flex justify-between items-center">
|
||||
<h6 class="font-bold" data-toc-ignore>By Matt</h6>
|
||||
<small>
|
||||
{#if post.date}
|
||||
<span class="date text-p-small ml-macro">
|
||||
{new Date(Date.parse(post.date)).toLocaleDateString(undefined, {
|
||||
year: 'numeric',
|
||||
month: 'short',
|
||||
day: 'numeric'
|
||||
})}
|
||||
</span>
|
||||
{/if}
|
||||
</small>
|
||||
</div>
|
||||
</footer>
|
||||
</a>
|
||||
</div>
|
||||
</a>
|
|
@ -1,15 +1,16 @@
|
|||
import type { MarkdownMetadata } from '$lib/contents/types';
|
||||
|
||||
export type BlogTag = 'Projects' | 'Ideas' | 'Updates' | '';
|
||||
export type BlogTag = 'Projects' | 'Blog' | 'Updates' | '';
|
||||
|
||||
export interface BlogPost extends MarkdownMetadata {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
tags?: BlogTag[];
|
||||
modified?: string;
|
||||
date?: string;
|
||||
excerpt: string;
|
||||
image: string;
|
||||
slug?: string;
|
||||
href?: string;
|
||||
tags?: BlogTag[];
|
||||
subtitle?: string;
|
||||
title: string;
|
||||
published: boolean;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Credit goes to @Xananax for providing this solution within the gist https://gist.github.com/Xananax/5dca3a1dd7070e4fdebe2927e4aeb55b
|
||||
*/
|
||||
import { join, basename, extname } from 'path';
|
||||
|
||||
export const defaults = {
|
||||
extensions: ['.svelte.md', '.md', '.svx'],
|
||||
dir: `$lib`,
|
||||
list: []
|
||||
};
|
||||
|
||||
/**
|
||||
* Injects global imports in all your mdsvex files
|
||||
* Specify:
|
||||
* - the root dir (defaults to `src/lib`)
|
||||
* - the array list of components (with extension), like `['Component.svelte']`
|
||||
* - the valid extensions list as an array (defaults to `['.svelte.md', '.md', '.svx']`)
|
||||
*
|
||||
* If you want the component name to be different from the file name, you can specify an array
|
||||
* of arrays: `['Component.svelte', ['Another', 'AnotherComp.svelte'], 'ThirdComp.svelte']`
|
||||
*
|
||||
* @param {Object} options options described above
|
||||
* @returns a preprocessor suitable to plug into the `preprocess` key of the svelte config
|
||||
*/
|
||||
export const mdsvexGlobalComponents = (options = {}) => {
|
||||
const { extensions, dir, list } = { ...defaults, ...options };
|
||||
const extensionsRegex = new RegExp(
|
||||
'(' + extensions.join('|').replace(/\./g, '\\.') + ')$',
|
||||
'i'
|
||||
);
|
||||
|
||||
if (!list || !list.length || !Array.isArray(list)) {
|
||||
throw new Error(`"list" option must be an array and contain at least one element`);
|
||||
}
|
||||
|
||||
const imports = list
|
||||
.map((entry) => {
|
||||
let name = '';
|
||||
if (Array.isArray(entry)) {
|
||||
name = entry[0];
|
||||
entry = entry[1];
|
||||
}
|
||||
const ext = extname(entry);
|
||||
const path = join(dir, entry);
|
||||
name = name || basename(entry, ext);
|
||||
return `\nimport ${name} from "${path}";`;
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
const preprocessor = {
|
||||
script(thing) {
|
||||
const { content, filename, attributes, markup } = thing;
|
||||
if (!filename.match(extensionsRegex)) {
|
||||
return { code: content };
|
||||
}
|
||||
const hasModuleContext = /^<script context="module">/.test(markup);
|
||||
|
||||
const isModulePass = attributes?.context === 'module';
|
||||
if (!isModulePass || !hasModuleContext) {
|
||||
return { code: content };
|
||||
}
|
||||
const isValidPass = (hasModuleContext && isModulePass) || !hasModuleContext;
|
||||
if (!isValidPass) {
|
||||
return { code: content };
|
||||
}
|
||||
return { code: `${imports}\n${content}` };
|
||||
}
|
||||
};
|
||||
return preprocessor;
|
||||
};
|
|
@ -3,22 +3,15 @@ import { visit } from 'unist-util-visit';
|
|||
const imagesRelativeUrlPattern = '/images/';
|
||||
|
||||
const visitor = (node) => {
|
||||
if (
|
||||
node.type === 'image' &&
|
||||
node.url.indexOf(imagesRelativeUrlPattern) > 0
|
||||
) {
|
||||
node.url = node.url.substring(
|
||||
node.url.indexOf(imagesRelativeUrlPattern) + ''.length,
|
||||
);
|
||||
if (node.type === 'image' && node.url.indexOf(imagesRelativeUrlPattern) > 0) {
|
||||
node.url = node.url.substring(node.url.indexOf(imagesRelativeUrlPattern) + ''.length);
|
||||
}
|
||||
};
|
||||
|
||||
export default () => async (tree, vFile) => {
|
||||
if (
|
||||
vFile.filename.indexOf('src/routes/docs/') > 0 ||
|
||||
vFile.filename.indexOf('src/routes/blog/') > 0 ||
|
||||
vFile.filename.indexOf('src/routes/guides/') > 0 ||
|
||||
vFile.filename.indexOf('src/routes/customers/') > 0
|
||||
vFile.filename.indexOf('src/routes/projects/') > 0
|
||||
) {
|
||||
visit(tree, visitor);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<!-- This page handles any error encountered by the site. -->
|
||||
<script>
|
||||
import { page } from '$app/stores';
|
||||
</script>
|
||||
|
||||
{#if $page.status === 404}
|
||||
<div class="flex flex-col items-center">
|
||||
<div
|
||||
class="relative mb-[3.33vh] flex h-96 w-96 items-center justify-center rounded-full bg-404"
|
||||
>
|
||||
<h1 class="h1 absolute text-h1 leading-[5rem]">404</h1>
|
||||
</div>
|
||||
<h2 class="h4 mb-x-small">You just hit a route that doesn't exist</h2>
|
||||
</div>
|
||||
{:else}
|
||||
<h2>{$page.status}</h2>
|
||||
|
||||
{#if $page.error}
|
||||
<p class="subhead">{$page.error.message}</p>
|
||||
{/if}
|
||||
|
||||
<p><strong>Sorry!</strong> Maybe try one of these links?</p>
|
||||
<ul>
|
||||
<li><a href="/">Home</a></li>
|
||||
</ul>
|
||||
{/if}
|
|
@ -3,6 +3,7 @@
|
|||
import { AppShell } from '@skeletonlabs/skeleton';
|
||||
import { onMount } from 'svelte';
|
||||
import MainFooter from '$lib/components/MainFooter.svelte';
|
||||
import MainHeader from '$lib/components/MainHeader.svelte';
|
||||
|
||||
// Floating UI for Popups
|
||||
import { computePosition, autoUpdate, flip, shift, offset, arrow } from '@floating-ui/dom';
|
||||
|
@ -65,9 +66,8 @@
|
|||
|
||||
// Highlight JS
|
||||
import hljs from 'highlight.js';
|
||||
import 'highlight.js/styles/github-dark.css';
|
||||
import 'highlight.js/styles/nord.css';
|
||||
import { storeHighlightJs } from '@skeletonlabs/skeleton';
|
||||
import MainHeader from '$lib/components/MainHeader.svelte';
|
||||
storeHighlightJs.set(hljs);
|
||||
</script>
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export const prerender = true;
|
||||
export const trailingSlash = 'never';
|
|
@ -43,7 +43,7 @@
|
|||
</section> -->
|
||||
|
||||
<script lang="ts">
|
||||
import PostPreview from '$lib/components/blog/post-preview.svelte';
|
||||
import PostPreview from '$lib/components/blog/BlogLayout.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import type { BlogTag } from '$lib/types/blog';
|
||||
import { page } from '$app/stores';
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
<script lang="ts">
|
||||
import BlogContentLayout from '$lib/components/blog/BlogLayout.svelte';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
</script>
|
||||
|
||||
<!-- <svelte:head>
|
||||
<title>{data.post.title}</title>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:title" content={data.post.title} />
|
||||
</svelte:head> -->
|
||||
|
||||
<BlogContentLayout post={data.post}>
|
||||
<svelte:component this={data.Component} />
|
||||
</BlogContentLayout>
|
Loading…
Reference in New Issue