Add furhter processing to posts display page
This commit is contained in:
parent
d761f72248
commit
bff88838d3
146
package-lock.json
generated
146
package-lock.json
generated
@ -8,13 +8,17 @@
|
||||
"name": "fredboniface.co.uk-svelte",
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"mongodb": "^5.7.0"
|
||||
"marked": "^7.0.3",
|
||||
"mongodb": "^5.7.0",
|
||||
"sanitize-html": "^2.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.28.1",
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/adapter-node": "^1.3.1",
|
||||
"@sveltejs/kit": "^1.20.4",
|
||||
"@types/node": "^20.5.1",
|
||||
"@types/sanitize-html": "^2.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"eslint": "^8.28.0",
|
||||
@ -916,9 +920,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz",
|
||||
"integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q=="
|
||||
"version": "20.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz",
|
||||
"integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg=="
|
||||
},
|
||||
"node_modules/@types/pug": {
|
||||
"version": "2.0.6",
|
||||
@ -932,6 +936,15 @@
|
||||
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/sanitize-html": {
|
||||
"version": "2.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.9.0.tgz",
|
||||
"integrity": "sha512-4fP/kEcKNj2u39IzrxWYuf/FnCCwwQCpif6wwY6ROUS1EPRIfWJjGkY3HIowY1EX/VbX5e86yq8AAE7UPMgATg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"htmlparser2": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/semver": {
|
||||
"version": "7.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz",
|
||||
@ -1674,7 +1687,6 @@
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
|
||||
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@ -1736,6 +1748,68 @@
|
||||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dom-serializer": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
||||
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.2",
|
||||
"entities": "^4.2.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domelementtype": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
]
|
||||
},
|
||||
"node_modules/domhandler": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domhandler?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/domutils": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
|
||||
"integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
|
||||
"dependencies": {
|
||||
"dom-serializer": "^2.0.0",
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/domutils?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/entities": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
|
||||
"engines": {
|
||||
"node": ">=0.12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/es6-promise": {
|
||||
"version": "3.3.1",
|
||||
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
|
||||
@ -1783,7 +1857,6 @@
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
|
||||
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
@ -2282,6 +2355,24 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/htmlparser2": {
|
||||
"version": "8.0.2",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
|
||||
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
|
||||
"funding": [
|
||||
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fb55"
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"domelementtype": "^2.3.0",
|
||||
"domhandler": "^5.0.3",
|
||||
"domutils": "^3.0.1",
|
||||
"entities": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "5.2.4",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
|
||||
@ -2431,6 +2522,14 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/is-plain-object": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
|
||||
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/is-reference": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.1.tgz",
|
||||
@ -2585,6 +2684,17 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/marked": {
|
||||
"version": "7.0.3",
|
||||
"resolved": "https://registry.npmjs.org/marked/-/marked-7.0.3.tgz",
|
||||
"integrity": "sha512-ev2uM40p0zQ/GbvqotfKcSWEa59fJwluGZj5dcaUOwDRrB1F3dncdXy8NWUApk4fi8atU3kTBOwjyjZ0ud0dxw==",
|
||||
"bin": {
|
||||
"marked": "bin/marked.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.0.30",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||
@ -2777,7 +2887,6 @@
|
||||
"version": "3.3.6",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||
"integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@ -2880,6 +2989,11 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-srcset": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
|
||||
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q=="
|
||||
},
|
||||
"node_modules/path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
@ -2951,8 +3065,7 @@
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.3.1",
|
||||
@ -2993,7 +3106,6 @@
|
||||
"version": "8.4.28",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz",
|
||||
"integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -3344,6 +3456,19 @@
|
||||
"rimraf": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/sanitize-html": {
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.11.0.tgz",
|
||||
"integrity": "sha512-BG68EDHRaGKqlsNjJ2xUB7gpInPA8gVx/mvjO743hZaeMCZ2DwzW7xvsqZ+KNU4QKwj86HJ3uu2liISf2qBBUA==",
|
||||
"dependencies": {
|
||||
"deepmerge": "^4.2.2",
|
||||
"escape-string-regexp": "^4.0.0",
|
||||
"htmlparser2": "^8.0.0",
|
||||
"is-plain-object": "^5.0.0",
|
||||
"parse-srcset": "^1.0.2",
|
||||
"postcss": "^8.3.11"
|
||||
}
|
||||
},
|
||||
"node_modules/saslprep": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
|
||||
@ -3468,7 +3593,6 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
|
||||
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
@ -19,6 +19,8 @@
|
||||
"@sveltejs/adapter-auto": "^2.0.0",
|
||||
"@sveltejs/adapter-node": "^1.3.1",
|
||||
"@sveltejs/kit": "^1.20.4",
|
||||
"@types/node": "^20.5.1",
|
||||
"@types/sanitize-html": "^2.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||
"@typescript-eslint/parser": "^5.45.0",
|
||||
"eslint": "^8.28.0",
|
||||
@ -36,6 +38,8 @@
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"mongodb": "^5.7.0"
|
||||
"marked": "^7.0.3",
|
||||
"mongodb": "^5.7.0",
|
||||
"sanitize-html": "^2.11.0"
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ let dbClient: MongoClient | null = null;
|
||||
|
||||
export async function mongoConnect() {
|
||||
if (!dbClient) {
|
||||
dbClient = await MongoClient.connect(MongoUri)
|
||||
dbClient = await MongoClient.connect(MongoUri);
|
||||
}
|
||||
return dbClient
|
||||
}
|
||||
return dbClient;
|
||||
}
|
||||
|
@ -1,17 +1,17 @@
|
||||
<script lang="ts">
|
||||
import type { ArticleSummary } from "./types";
|
||||
import FullWidthContent from "$lib/content-boxes/FullWidthContent.svelte";
|
||||
import type { ArticleSummary } from './types';
|
||||
import FullWidthContent from '$lib/content-boxes/FullWidthContent.svelte';
|
||||
|
||||
export let article: ArticleSummary
|
||||
export let article: ArticleSummary;
|
||||
</script>
|
||||
|
||||
<FullWidthContent>
|
||||
<a href="/posts/{article.slug}">
|
||||
<article>
|
||||
<h1>{article.title}</h1>
|
||||
<p>{article.summary}</p>
|
||||
</article>
|
||||
</a>
|
||||
<article>
|
||||
<h1>{article.title}</h1>
|
||||
<p>{article.summary}</p>
|
||||
</article>
|
||||
</a>
|
||||
</FullWidthContent>
|
||||
|
||||
<style>
|
||||
|
@ -1,20 +1,20 @@
|
||||
export interface ArticleSummary {
|
||||
title: string;
|
||||
author: string;
|
||||
tags: string[];
|
||||
pusblished: boolean;
|
||||
date: Date;
|
||||
summary: string;
|
||||
slug: string;
|
||||
title: string;
|
||||
author: string;
|
||||
tags: string[];
|
||||
pusblished: boolean;
|
||||
date: Date;
|
||||
summary: string;
|
||||
slug: string;
|
||||
}
|
||||
|
||||
export interface Article {
|
||||
title: string;
|
||||
author: string;
|
||||
tags: string[];
|
||||
pusblished: boolean;
|
||||
date: Date;
|
||||
summary: string;
|
||||
slug: string;
|
||||
content: string;
|
||||
}
|
||||
title: string;
|
||||
author: string;
|
||||
tags: string[];
|
||||
pusblished: boolean;
|
||||
date: Date;
|
||||
summary: string;
|
||||
slug: string;
|
||||
content: string;
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type { Project } from "./types";
|
||||
import Logos from "$lib/language-logos/Logos.svelte";
|
||||
import type { Project } from './types';
|
||||
import Logos from '$lib/language-logos/Logos.svelte';
|
||||
|
||||
export let project: Project
|
||||
export let project: Project;
|
||||
</script>
|
||||
|
||||
<article>
|
||||
<a href="/posts/tag/{project.tag}"><h1>{project.name}</h1></a>
|
||||
<Logos langs={project.lang || []} plats={project.plat || []} />
|
||||
<Logos langs={project.lang || []} plats={project.plat || []} />
|
||||
<p>{project.summary}</p>
|
||||
</article>
|
||||
|
||||
@ -27,4 +27,4 @@
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
@ -35,15 +35,12 @@
|
||||
<section id="meta-links">
|
||||
<div id="projects" class="col">
|
||||
<h1>Projects</h1>
|
||||
|
||||
</div>
|
||||
<div id="posts" class="col">
|
||||
<h1>Posts</h1>
|
||||
|
||||
</div>
|
||||
<div id="tags" class="col">
|
||||
<h1>Tags</h1>
|
||||
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
@ -1,16 +1,57 @@
|
||||
import { mongoConnect } from "$lib/database/mongo";
|
||||
import { mongoConnect } from '$lib/database/mongo';
|
||||
import { marked } from 'marked';
|
||||
import * as path from 'path';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
|
||||
import type { Article } from '$lib/posts/types';
|
||||
import type { _Renderer } from 'Renderer';
|
||||
|
||||
export async function load({ params }) {
|
||||
const slug = params.slug;
|
||||
const db = await mongoConnect()
|
||||
const db = await mongoConnect();
|
||||
const query = {
|
||||
slug: slug
|
||||
}
|
||||
const col = db.db('fredboniface').collection('posts')
|
||||
const res = col.findOne(query)
|
||||
const posts = await res
|
||||
slug: slug
|
||||
};
|
||||
const col = db.db('fredboniface').collection('posts');
|
||||
const res = await col.findOne(query);
|
||||
|
||||
// Create the `Article` object here and return that rather than doing it on the page.
|
||||
if (!res) {
|
||||
throw new Error('Post Not Found');
|
||||
}
|
||||
|
||||
return {data: JSON.stringify(posts)}
|
||||
const renderer = new marked.Renderer();
|
||||
renderer.image = function (href, title, text) {
|
||||
const imgPath = path.join('/images/posts', res.slug, href);
|
||||
return `<figure>
|
||||
<img class="post-inline-image-546543" src="${imgPath}" alt="${text}" title="${title}">
|
||||
<figcaption>${title}</figcaption>
|
||||
</figure>`;
|
||||
};
|
||||
|
||||
const post: Article = {
|
||||
title: res.title,
|
||||
author: res.author,
|
||||
pusblished: res.published,
|
||||
summary: res.summary,
|
||||
content: renderMarkdown(res.content, renderer),
|
||||
slug: res.slug,
|
||||
tags: res.tags,
|
||||
date: res.date
|
||||
};
|
||||
|
||||
return { data: post };
|
||||
}
|
||||
|
||||
function renderMarkdown(md: string, renderer: _Renderer): string {
|
||||
const rawHtml = marked(md, { renderer });
|
||||
console.log(rawHtml)
|
||||
const sanitizedHtml = sanitizeHtml(rawHtml, {
|
||||
allowedTags: ['a', 'br', 'code', 'figcaption', 'figure', 'img', 'p', 'pre'],
|
||||
allowedAttributes: {
|
||||
'a': ['href'],
|
||||
'img': ['alt', 'class', 'src', 'title']
|
||||
}
|
||||
});
|
||||
console.log(sanitizedHtml)
|
||||
return sanitizedHtml
|
||||
}
|
||||
|
@ -1,24 +1,109 @@
|
||||
<script lang="ts">
|
||||
import Header from "$lib/header.svelte";
|
||||
import type { Article } from "$lib/posts/types";
|
||||
import Header from '$lib/header.svelte';
|
||||
import type { Article } from '$lib/posts/types';
|
||||
import { afterUpdate } from 'svelte';
|
||||
|
||||
export let data: any;
|
||||
|
||||
const post: Article = JSON.parse(data.data)
|
||||
const post: Article = data.data;
|
||||
|
||||
afterUpdate(() => {
|
||||
const codeBlocks = document.querySelectorAll('article pre');
|
||||
codeBlocks.forEach((codeBlock) => {
|
||||
const copyButton = document.createElement('button');
|
||||
copyButton.textContent = '📋 Copy code';
|
||||
copyButton.classList.add('article-code-copy-button-32984456');
|
||||
|
||||
copyButton.addEventListener('click', () => {
|
||||
const codeText = codeBlock.textContent || '';
|
||||
const trimmedCodeText = codeText.replace(copyButton.textContent || '', '');
|
||||
|
||||
navigator.clipboard
|
||||
.writeText(trimmedCodeText)
|
||||
.then(() => {
|
||||
console.log('Copied code to clipboard');
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(
|
||||
'Error copying code to clipboard, this may be due to privacy settings in your browser'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
codeBlock.appendChild(copyButton);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<article>
|
||||
<Header title={post.title} />
|
||||
<p>{#each post.tags as tag}
|
||||
<span>{tag}</span>
|
||||
{/each}<br>
|
||||
{post.date}<br>
|
||||
{post.author}<br>
|
||||
{post.content}</p>
|
||||
|
||||
<div class="column-container">
|
||||
<div class="main-column">
|
||||
<article>
|
||||
<p>
|
||||
{#each post.tags as tag}
|
||||
<span>{tag}</span>
|
||||
{/each}<br />
|
||||
{post.date.toLocaleDateString()}<br />
|
||||
Written by: {post.author}
|
||||
</p>
|
||||
<content>
|
||||
{@html post.content}
|
||||
</content>
|
||||
</article>
|
||||
</div>
|
||||
<div class="side-column">
|
||||
<p>HELLO FROM COLUMN 2</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.column-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.column-container {
|
||||
flex-direction: row; /* Switch to row layout for larger screens */
|
||||
}
|
||||
.main-column {
|
||||
flex: 2; /* Take up 2/3 of the available width */
|
||||
}
|
||||
.side-column {
|
||||
flex: 1; /* Take up 1/3 of the available width */
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
:global(article pre) {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
background-color: rgb(46, 46, 46);
|
||||
color: white;
|
||||
padding: 15px;
|
||||
padding-top: 30px;
|
||||
padding-bottom: 30px;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
border-radius: 8px;
|
||||
width: 90%;
|
||||
max-width: 800px;
|
||||
margin: auto;
|
||||
white-space: pre;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:global(.article-code-copy-button-32984456) {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 15px;
|
||||
color: white;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,19 +1,16 @@
|
||||
import { mongoConnect } from "$lib/database/mongo";
|
||||
|
||||
import { mongoConnect } from '$lib/database/mongo';
|
||||
|
||||
export async function load({ params }) {
|
||||
const tag = params.tag;
|
||||
const db = await mongoConnect()
|
||||
const db = await mongoConnect();
|
||||
const query = {
|
||||
tags: {
|
||||
$in: [
|
||||
tag
|
||||
]
|
||||
}
|
||||
tags: {
|
||||
$in: [tag]
|
||||
}
|
||||
const col = db.db('fredboniface').collection('posts')
|
||||
const res = col.find(query)
|
||||
const posts = await res.toArray()
|
||||
};
|
||||
const col = db.db('fredboniface').collection('posts');
|
||||
const res = col.find(query);
|
||||
const posts = await res.toArray();
|
||||
|
||||
return {data: JSON.stringify(posts)}
|
||||
return { data: JSON.stringify(posts) };
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
<script lang="ts">
|
||||
import PostsSummary from "$lib/posts/PostsSummary.svelte";
|
||||
import type { ArticleSummary } from "$lib/posts/types.js";
|
||||
import PostsSummary from '$lib/posts/PostsSummary.svelte';
|
||||
import type { ArticleSummary } from '$lib/posts/types.js';
|
||||
|
||||
export let data;
|
||||
const posts: ArticleSummary[] = JSON.parse(data.data)
|
||||
const posts: ArticleSummary[] = JSON.parse(data.data);
|
||||
|
||||
console.log("Posts:", posts)
|
||||
console.log('Posts:', posts);
|
||||
</script>
|
||||
|
||||
<h1>Testing</h1>
|
||||
|
||||
{#each posts as article}
|
||||
<PostsSummary {article} />
|
||||
<PostsSummary {article} />
|
||||
{/each}
|
||||
|
@ -19,14 +19,14 @@
|
||||
/>
|
||||
<p>
|
||||
Working full time on the 'iron road', left me wanting a faster way to get the information I
|
||||
needed. OwlBoard evolved from <a href="/articles/athena">Athena</a> and grew to provide more
|
||||
information that frontline rail colleagues need.
|
||||
needed. OwlBoard evolved from <a href="/articles/athena">Athena</a> and grew to provide more information
|
||||
that frontline rail colleagues need.
|
||||
</p>
|
||||
</FullWidthContent>
|
||||
<FullWidthContent>
|
||||
<h1><a href="/posts/tag/map-dots">map-dots</a></h1>
|
||||
<br />
|
||||
<GitLink url={"https://git.fjla.uk/fred.boniface/map-dots"} />
|
||||
<GitLink url={'https://git.fjla.uk/fred.boniface/map-dots'} />
|
||||
<Logos langs={['go', 'py']} plats={[]} />
|
||||
<p>
|
||||
I like to collect data, I am just not always sure what to do with that data. map-dots takes in
|
||||
|
BIN
static/images/posts/sveltekit-dev-ribbon/owlboard-devmode.png
Normal file
BIN
static/images/posts/sveltekit-dev-ribbon/owlboard-devmode.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
Loading…
Reference in New Issue
Block a user