Refactor, update UI, and add notes

This commit is contained in:
Paul W
2022-10-04 23:41:59 -04:00
parent 3781c2c154
commit d94de055d8
31 changed files with 813 additions and 265 deletions

80
lib/date.ts Normal file
View File

@@ -0,0 +1,80 @@
const months = [
'January',
'February',
'March',
'April',
'May',
'June',
'July',
'August',
'September',
'October',
'November',
'December'
];
const ordSfx = ['','st','nd','rd','th'];
function toHumanReadableDate(date: Date | string, disable?: {year?: boolean, month?: boolean, day?: boolean}) {
const oDate = (typeof date === 'string')? new Date(date): date;
const year = oDate.getFullYear();
const month = months[oDate.getMonth()];
const day = oDate.getDate();
let sfx;
if (day >= 1 && day <= 3)
sfx = ordSfx[day];
else
sfx = ordSfx[4];
let out = !disable?.day ? `${day}${sfx}` : '';
out = !disable?.month ? `${out} ${month}` : out;
out = !disable?.year ? `${out} ${year}` : out;
return out;
}
function toRelativeDate(date: Date | string): string {
const oDate = (typeof date === 'string')? new Date(date): date;
const now = new Date();
const diff = now.getTime() - oDate.getTime();
let tdiff = Math.floor(diff/1000);
if (tdiff < 0) {
return toHumanReadableDate(oDate);
}
if (tdiff < 60) {
return `${tdiff} seconds ago`;
}
tdiff = Math.floor(tdiff/60);
if (tdiff < 60) {
return `${tdiff} minute${tdiff === 1? '' : 's'} ago`;
}
tdiff = Math.floor(tdiff/60);
if (tdiff < 24) {
return `${tdiff} hour${tdiff === 1? '' : 's'} ago`;
}
if (tdiff < 48) {
return `Yesterday`;
}
if (oDate.getFullYear() != now.getFullYear())
return toHumanReadableDate(oDate);
return toHumanReadableDate(oDate, {year: true});
}
function isValid(date: any) {
return (new Date(date)).toString() === 'Invalid Date';
}
const DateTool = {
toRelativeDate,
isValid
};;
export default DateTool;

35
lib/slug.d.ts vendored Normal file
View File

@@ -0,0 +1,35 @@
interface IPost {
slug: string;
rawslug: string;
content: string;
title: string;
}
interface INote {
slug: string;
rawslug: string;
content: string;
title: string;
}
interface INoteMeta {
title: string;
slug: string;
last_updated?: string;
}
interface IPostMeta {
title: string;
slug: string;
created_at: string;
last_updated?: string;
}
export function getAllPosts(filter?: Array<any>): IPost[];
export function getAllNotes(filter?: Array<any>): INote[];
export function getPost(rawslug: string, filter?: Array<any>): IPost;
export function getNote(rawslug: string, filter?: Array<any>): INote;
export function getPostsMeta(): IPostMeta[];
export function getNotesMeta(): INoteMeta[];

139
lib/slug.js Normal file
View File

@@ -0,0 +1,139 @@
const fs = require('fs');
const matter = require('gray-matter');
const { join } = require('path');
const cacheDir = join(process.cwd(), '.cache');
function getDir(name) {
return join(process.cwd(), name);
}
function getCacheFileName(name) {
return join(cacheDir, `${name}.cache.json`)
}
function get(dir, rawslug, filter = []) {
const slug = rawslug.replace(/\.md$/, '');
const path = join(dir, `${slug}.md`);
const file = fs.readFileSync(path, 'utf-8');
const { data, content } = matter(file);
if (data['last_updated'] === undefined)
data['last_updated'] = '';
if (filter.length === 0)
return { ...data, content, slug, rawslug };
let post = {};
for (const [_, entry] of filter.entries()) {
if (entry === 'slug')
post[entry] = slug;
if (entry === 'rawslug')
post[entry] = rawslug;
if (entry === 'content')
post[entry] = content;
if (typeof data[entry] !== 'undefined') {
post[entry] = data[entry]
}
}
return post;
}
function getAllPosts(filter = []) {
const files = fs.readdirSync(getDir('posts'));
return files
.filter(c => (!c.match(/^\.]/) && c.match(/\.md$/)))
.map(file => {
return get(getDir('posts'), file, filter)
})
.filter(c => (c.title && c.slug && c.created_at && (new Date(c.created_at)).toString() !== 'Invalid Date'))
.sort((a, b) => {
const dA = new Date(a['created_at']);
const dB = new Date(b['created_at']);
return dB - dA;
});
}
function getAllNotes(filter = []) {
const files = fs.readdirSync(getDir('notes'));
return files
.filter(c => (!c.match(/^\.]/) && c.match(/\.md$/)))
.map(file => {
return get(getDir('notes'), file, filter)
})
.filter(c => (c.title && c.slug && c.last_updated && (new Date(c.last_updated)).toString() !== 'Invalid Date'))
.sort((a, b) => {
const dA = new Date(a['last_updated']);
const dB = new Date(b['last_updated']);
return dB - dA;
});
}
const cats = {
notes: {
name: 'notes',
getAll: getAllNotes,
filter: ['title', 'slug', 'last_updated'],
},
posts: {
name: 'posts',
getAll: getAllPosts,
filter: ['title', 'slug', 'created_at', 'last_updated'],
}
};
function cacheMeta({name, getAll, filter}) {
const items = getAll(filter);
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir);
}
fs.writeFile(getCacheFileName(name), JSON.stringify(items), (e) => {
if (e)
console.error(e);
});
return items;
}
function getMeta(cat) {
try {
const file = fs.readFileSync(getCacheFileName(cat.name), 'utf-8');
return JSON.parse(file);
} catch (e) {
if (cat.name)
return cacheMeta(cat);
}
}
function getPostsMeta() {
return getMeta(cats.posts);
};
function getNotesMeta() {
return getMeta(cats.notes);
};
function cache() {
Object.entries(cats).map(([_, v]) => {
return cacheMeta(v);
});
}
const getPost = (s, f) => {return get(getDir('posts'), s, f)};
const getNote = (s, f) => {return get(getDir('notes'), s, f)};
module.exports = {
getAllPosts,
getAllNotes,
getPostsMeta,
getNotesMeta,
getPost,
getNote,
cache
};