It is now possible to display #1

Merged
Hare merged 24 commits from develop into master 2024-08-26 18:55:10 +09:00
4 changed files with 471 additions and 358 deletions
Showing only changes of commit 64d3e51311 - Show all commits

721
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"dotenv": "^16.4.5", "dotenv": "^16.4.5",
"mdsvex": "^0.12.3",
"pg": "^8.12.0", "pg": "^8.12.0",
"sass": "^1.77.8" "sass": "^1.77.8"
} }

View File

@ -1,7 +1,7 @@
// initialize // initialize
import PG from '$lib/server/database'; import PG from '$lib/server/database';
import fs from 'fs'; import fs from 'fs';
import { compile } from 'mdsvex';
export default async function init() { export default async function init() {
@ -13,9 +13,12 @@ export default async function init() {
{ name: 'seq', type: 'serial', constraint: 'primary key' }, { name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' }, { name: 'id', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' }, { name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'released_at', type: 'timestamp', constraint: 'not null' }, { name: 'released_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' }, { name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' }, { name: 'tags', type: 'text[]', constraint: 'not null' },
{ name: 'image', type: 'text', constraint: '' },
{ name: 'publish', type: 'text', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' }, { name: 'content', type: 'text', constraint: 'not null' },
], ],
}, },
@ -34,6 +37,7 @@ export default async function init() {
{ name: 'seq', type: 'serial', constraint: 'primary key' }, { name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'id', type: 'text', constraint: 'not null' }, { name: 'id', type: 'text', constraint: 'not null' },
{ name: 'title', type: 'text', constraint: 'not null' }, { name: 'title', type: 'text', constraint: 'not null' },
{ name: 'category', type: 'text', constraint: 'not null' },
{ name: 'created_at', type: 'timestamp', constraint: 'not null' }, { name: 'created_at', type: 'timestamp', constraint: 'not null' },
{ name: 'updated_at', type: 'timestamp', constraint: 'not null' }, { name: 'updated_at', type: 'timestamp', constraint: 'not null' },
{ name: 'tags', type: 'text[]', constraint: 'not null' }, { name: 'tags', type: 'text[]', constraint: 'not null' },
@ -58,8 +62,17 @@ export default async function init() {
{ name: 'posted_at', type: 'timestamp', constraint: 'not null' }, { name: 'posted_at', type: 'timestamp', constraint: 'not null' },
{ name: 'content', type: 'text', constraint: 'not null' }, { name: 'content', type: 'text', constraint: 'not null' },
], ],
},
{
name: 'tag',
columns: [
{ name: 'seq', type: 'serial', constraint: 'primary key' },
{ name: 'name', type: 'text', constraint: 'not null' },
{ name: 'ref_count', type: 'integer', constraint: 'not null' },
],
} }
]; ];
const db = await PG(); const db = await PG();
try { try {
await db.begin(); await db.begin();
@ -79,7 +92,6 @@ export default async function init() {
await db.rollback(); await db.rollback();
} }
// Check if the article are already in the database
const articleFiles: ArticleFileItem[] = []; const articleFiles: ArticleFileItem[] = [];
function scanDir(path: string) { function scanDir(path: string) {
const files = fs.readdirSync(path); const files = fs.readdirSync(path);
@ -89,13 +101,51 @@ export default async function init() {
if (stat.isDirectory()) { if (stat.isDirectory()) {
scanDir(dir); scanDir(dir);
} else { } else {
// articleFiles.push({ path: `${path}/${file}`, id: file }); articleFiles.push({ path: `${path}/${file}`, id: file });
console.log(`${path}/${file}`);
} }
} }
} }
scanDir('./articles/dist'); scanDir('./articles/dist');
await db.query('update tag set ref_count = 0');
db.commit();
for (const { path, id } of articleFiles) {
const res = await db.query('select * from article where id = $1', [id]);
const md = await compile(fs.readFileSync(path, 'utf-8'));
const title = md.data.fm.title;
const category = path.split('/')[3];
const tags: string[] = md.data.fm.tags;
const released_at = new Date(md.data.fm.released_at);
const updated_at = new Date(md.data.fm.updated_at);
const image = md.data.fm.image;
const publish = md.data.fm.publish;
const content = md.code;
if (res.rowCount == 0) {
console.log(`New article: ${id}`);
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)',
[id, title, category, released_at, updated_at, tags, image, publish, content]
);
} else if (res.rows[0].updated_at < updated_at) {
console.log(`Update article: ${id}`);
await db.query(
'update article set title = $2, updated_at = $4, tags = $5, content = $6 where id = $1',
[id, title, updated_at, tags, content]
);
} else {
console.log(`Article ${id} is already up-to-date`);
}
for (const tag of tags) {
if ((await db.query('select * from tag where name = $1', [tag])).rowCount == 0) {
db.query('insert into tag (name, ref_count) values ($1, 1)', [tag]);
} else {
db.query('update tag set ref_count = ref_count + 1 where name = $1', [tag]);
}
}
}
await db.commit();
await db.release(); await db.release();
} }

View File

@ -4,29 +4,46 @@ import type { Content } from '$lib/article';
import PG from '$lib/server/database'; import PG from '$lib/server/database';
let data: { let data: {
recent: Content[], recent: {
title: string,
image: string,
date: string,
link: string,
tags: string[]
}[],
tags: string[], tags: string[],
updated: string updated: string,
} = { } = {
recent: [ recent: [],
{ tags: [],
title: "title",
image: "image",
date: "date",
link: "link",
tags: ["tag1", "tag2"],
},
],
tags: ["hoge", "fuga", "piyo"],
updated: "", updated: "",
}; };
export const load: PageServerLoad = async ({ params }) => { export const load: PageServerLoad = async ({ params }) => {
const db = await PG(); const db = await PG();
const now = await db.query('SELECT NOW()'); await db.begin();
await db.release(); try {
const recent_articles = await db.query(
"SELECT * FROM article WHERE publish = 'public' ORDER BY updated_at DESC LIMIT 4"
);
data.recent = recent_articles.rows.map((row) => ({
title: row.title,
image: row.image,
date: row.updated_at.toISOString().slice(0, 10),
link: `/post/${row.category}/${row.id}`,
tags: row.tags,
}));
const tags = await db.query("SELECT * FROM tag ORDER BY ref_count DESC");
data.tags = tags.rows.map((row) => row.name + ":" + row.ref_count);
} catch (e) {
await db.rollback();
throw error(500, e as Error);
} finally {
await db.release();
}
data.updated = data.recent[0].date;
data.updated = now.rows[0].now;
return data; return data;
} }