feat: change article load logic

- change highlighter prism to shiki
- separate logic into several files
This commit is contained in:
Keisuke Hirata 2024-09-07 02:42:50 +09:00
parent 68dde60151
commit 005fd864b2
4 changed files with 59 additions and 30 deletions

22
src/lib/server/article.ts Normal file
View File

@ -0,0 +1,22 @@
import { compile, escapeSvelte } from "mdsvex";
import { createHighlighter } from "shiki";
import { kanagawa_dark as theme } from "$lib/kanagawa"
const highlighter = await createHighlighter({
themes: [theme],
langs: ["javascript", "typescript", "shell"],
});
export default async function compileArticle(code: string) {
return compile(code, {
highlight: {
highlighter: async (code: string, lang = "text") => {
const html = escapeSvelte(
highlighter.codeToHtml(code, { lang, theme }),
);
return html;
},
},
});
}

View File

@ -14,6 +14,6 @@ const pool = new Pool({ connectionString });
export const getConnection = () => pool; export const getConnection = () => pool;
import init from '$lib/server/database/init_db'; import init_db from '$lib/server/database/init';
import PG from '$lib/server/database'; import PG from '$lib/server/database';
await init(await PG(pool)); await init_db(await PG(pool));

View File

@ -1,8 +1,8 @@
// initialize // initialize
import type { Postgres } from '$lib/server/database'; import type { Postgres } from '$lib/server/database';
import fs from 'fs'; import fs from 'fs';
import { compile } from 'mdsvex';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
import compile from '$lib/server/article';
export default async function init(db: Postgres) { export default async function init(db: Postgres) {
if (fs.existsSync('./articles/')) { if (fs.existsSync('./articles/')) {
@ -95,29 +95,35 @@ export default async function init(db: Postgres) {
console.log(`Table ${schema.name} already exists`); console.log(`Table ${schema.name} already exists`);
} }
} }
} catch (err) {
console.error(err);
await db.rollback();
} finally {
await db.commit(); await db.commit();
}
const articleFiles: ArticleFileItem[] = []; const articleFiles: ArticleFileItem[] = [];
function scanDir(path: string) { function scanDir(path: string) {
const files = fs.readdirSync(path); const files = fs.readdirSync(path);
for (const file of files) { for (const file of files) {
const dir = `${path}/${file}`; const dir = `${path}/${file}`;
const stat = fs.statSync(dir); const stat = fs.statSync(dir);
if (stat.isDirectory()) { if (stat.isDirectory()) {
scanDir(dir); scanDir(dir);
} else { } else {
articleFiles.push({ path: `${path}/${file}`, id: file.replace('.md', '') }); articleFiles.push({ path: `${path}/${file}`, id: file.replace('.md', '') });
}
} }
} }
scanDir('./articles/article'); }
scanDir('./articles/article');
await db.query('update tag set ref_count = 0'); await db.query('update tag set ref_count = 0');
db.commit();
for (const { path, id } of articleFiles) { for (const { path, id } of articleFiles) {
await db.begin();
try {
const res = await db.query('select * from article where id = $1', [id]); const res = await db.query('select * from article where id = $1', [id]);
const compiled = await compile(fs.readFileSync(path, 'utf-8'), {}); const compiled = await compile(fs.readFileSync(path, 'utf-8'));
const title = compiled.data.fm.title; const title = compiled.data.fm.title;
const category = path.split('/')[3]; const category = path.split('/')[3];
@ -128,14 +134,15 @@ export default async function init(db: Postgres) {
const publish = compiled.data.fm.publish; const publish = compiled.data.fm.publish;
const content = compiled.code const content = compiled.code
.replace(/>{@html `<code class="language-/g, '><code class="language-') .replace(/>{@html `<code class="language-/g, '><code class="language-')
.replace(/<\/code>`}<\/pre>/g, '</code></pre>'); .replace(/<\/code>`}<\/pre>/g, '</code></pre>')
if (res.rowCount == 0) { if (res.rowCount == 0) {
console.log(`New article: ${id}`); console.log(`New article: ${id}`);
await db.query( await db.query(
'insert into article (id, title, category, released_at, updated_at, tags, image, publish, content) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)', 'insert into article (id, title, category, released_at, updated_at, tags, image, publish, content) values ($1, $2, $3, $4, $5, $6, $7, $8, $9)',
[id, title, category, released_at, updated_at, tags, image, publish, content] [id, title, category, released_at, updated_at, tags, image, publish, content]
); );
} else if (res.rows[0].updated_at < updated_at) { // } else if (res.rows[0].updated_at < updated_at) {
} else if (true) {
console.log(`Update article: ${id}`); console.log(`Update article: ${id}`);
await db.query( await db.query(
'update article set title = $2, category = $3, released_at = $4, updated_at = $5, tags = $6, image = $7, publish = $8, content = $9 where id = $1', 'update article set title = $2, category = $3, released_at = $4, updated_at = $5, tags = $6, image = $7, publish = $8, content = $9 where id = $1',
@ -151,15 +158,15 @@ export default async function init(db: Postgres) {
db.query('update tag set ref_count = ref_count + 1 where name = $1', [tag]); db.query('update tag set ref_count = ref_count + 1 where name = $1', [tag]);
} }
} }
} catch (err) {
console.log(err);
await db.rollback();
} finally {
await db.commit();
} }
await db.commit();
} catch (err) {
console.error(err);
await db.rollback();
} finally {
await db.release();
} }
await db.release();
} }
type ArticleFileItem = { type ArticleFileItem = {

View File

@ -8,7 +8,7 @@ import {
import PG from '$lib/server/database'; import PG from '$lib/server/database';
// import { building } from '$app/environment'; // import { building } from '$app/environment';
import init from '$lib/server/database/init_db'; import init_db from '$lib/server/database/init';
export const POST: RequestHandler = async ({ url, locals }) => { export const POST: RequestHandler = async ({ url, locals }) => {
const token = url.searchParams.get('token'); const token = url.searchParams.get('token');
@ -17,6 +17,6 @@ export const POST: RequestHandler = async ({ url, locals }) => {
return error(401, 'Unauthorized'); return error(401, 'Unauthorized');
} }
await init(await PG(locals.db)); await init_db(await PG(locals.db));
return new Response(String(token)); return new Response(String(token));
}; };