More changes to structure and UI
This commit is contained in:
parent
2d4a2809b4
commit
6ba7d561fb
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,4 +2,4 @@ node_modules/
|
||||
dist/
|
||||
.next/
|
||||
.DS_Store
|
||||
public/posts.json
|
||||
.cache/
|
@ -1,22 +1,24 @@
|
||||
import FuzzyBar from './fuzzy-bar';
|
||||
import Meta from './meta';
|
||||
import Title from './title';
|
||||
// import FuzzyBar from './fuzzy-bar';
|
||||
|
||||
type layoutProps = {
|
||||
type ChildrenType = JSX.Element | Array<ChildrenType>;
|
||||
|
||||
type LayoutProps = {
|
||||
name: string,
|
||||
title?: string,
|
||||
children?: JSX.Element | JSX.Element[],
|
||||
ancestors?: Array<{ name: string, path: string }>
|
||||
children?: ChildrenType,
|
||||
};
|
||||
|
||||
function Layout(props: layoutProps) {
|
||||
function Layout({ name, title, children, ancestors }: LayoutProps) {
|
||||
return (
|
||||
<>
|
||||
<Meta name={props.name} ancestors={props.ancestors} />
|
||||
<Title title={props.title} name={props.name} ancestors={props.ancestors} />
|
||||
<FuzzyBar />
|
||||
<Meta name={name} ancestors={ancestors} />
|
||||
<Title title={title} name={name} ancestors={ancestors} />
|
||||
{/* <FuzzyBar /> */}
|
||||
<div className='container'>
|
||||
{props.children}
|
||||
{children}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -80,7 +80,7 @@ export function mapChild(obj: listItem | string, level: number) {
|
||||
title = React.createElement('strong', {}, obj.title);
|
||||
|
||||
return (
|
||||
<section className={level < 4 ? 'block' : ''}>
|
||||
<section className={level < 4 && `block ${style.block}` || ''}>
|
||||
{title}
|
||||
{obj.description ? <p className={style.desc}>{obj.description}</p> : <></>}
|
||||
<div>
|
@ -1,16 +1,17 @@
|
||||
import Head from 'next/head';
|
||||
|
||||
export default function Meta(props: { name: string, ancestors?: Array<{ name: string, path: string }> }) {
|
||||
function Meta({name, ancestors}
|
||||
: {name: string, ancestors?: Array<{ name: string, path: string }> }) {
|
||||
const path = () => {
|
||||
if (!props.ancestors)
|
||||
return props.name;
|
||||
if (!ancestors)
|
||||
return name;
|
||||
|
||||
let path = '';
|
||||
props.ancestors.map((obj) => {
|
||||
ancestors.map((obj) => {
|
||||
path = `${path}${obj.name} /`;
|
||||
});
|
||||
|
||||
return `${path} ${props.name}`;
|
||||
return `${path} ${name}`;
|
||||
};
|
||||
|
||||
return (
|
||||
@ -18,4 +19,6 @@ export default function Meta(props: { name: string, ancestors?: Array<{ name: st
|
||||
<title>PaulW.XYZ / {path()}</title>
|
||||
</Head>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default Meta;
|
21
components/quick-links.tsx
Normal file
21
components/quick-links.tsx
Normal file
@ -0,0 +1,21 @@
|
||||
import Link from 'next/link';
|
||||
import Pages from '../public/pages.json';
|
||||
import style from '../styles/quick-links.module.css'
|
||||
|
||||
function QuickLinks() {
|
||||
return (<>
|
||||
<div className='h2'>Quick Links</div>
|
||||
{
|
||||
Pages.map((obj, i) => {
|
||||
const extern = obj.link.match(/^http/) && `blue ${style.blueButton}` || '';
|
||||
return (
|
||||
<Link key={i} href={obj.link}>
|
||||
<a className={`${extern} ${style.button} button`}>{obj.title}</a>
|
||||
</Link>
|
||||
);
|
||||
})
|
||||
}
|
||||
</>);
|
||||
}
|
||||
|
||||
export default QuickLinks;
|
34
components/recent-posts.tsx
Normal file
34
components/recent-posts.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import Link from "next/link";
|
||||
import date from "../util/date";
|
||||
import { PostMeta } from "../util/slug";
|
||||
import style from '../styles/recent-posts.module.css';
|
||||
|
||||
function RecentPosts({ postsMeta }: { postsMeta: PostMeta[] }) {
|
||||
return (<>
|
||||
<div className='h2'>Recent Posts</div>
|
||||
<div className={style.container}>
|
||||
{postsMeta?.slice(0, 10)
|
||||
.map((post: any) => {
|
||||
return <div className={style.block} key={post.slug}>
|
||||
<Link href={`/posts/${post.slug}`}>
|
||||
<a className={`${style.postTitle} h5`}>{post.title}</a>
|
||||
</Link>
|
||||
<span className={style.postDate}>
|
||||
{date.prettyPrint(new Date(post.created_at))}
|
||||
</span>
|
||||
</div>
|
||||
})}
|
||||
</div>
|
||||
{
|
||||
postsMeta.length > 10 &&
|
||||
<div className={style.more}>
|
||||
<Link href='/posts'>
|
||||
<a className='h5'>More...</a>
|
||||
</Link>
|
||||
</div>
|
||||
}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default RecentPosts;
|
@ -7,42 +7,33 @@ type propsObj = {
|
||||
ancestors?: Array<{ name: string, path: string }>
|
||||
};
|
||||
|
||||
function Title(props: propsObj) {
|
||||
|
||||
const path = () => {
|
||||
if (!props.ancestors)
|
||||
return (<></>);
|
||||
|
||||
let currentPath = '';
|
||||
return (<>
|
||||
{
|
||||
props.ancestors.map(ancestor => {
|
||||
currentPath += `/${ancestor.path}`
|
||||
return (
|
||||
<>
|
||||
<Link href={currentPath} key=''>
|
||||
<a>{ancestor.name}</a>
|
||||
</Link>
|
||||
<> / </>
|
||||
</>
|
||||
);
|
||||
})
|
||||
}
|
||||
</>
|
||||
function createPathElements(ancestors: Array<{ name: string, path: string }>) {
|
||||
let currentPath = '';
|
||||
return ancestors.map((ancestor) => {
|
||||
currentPath += `/${ancestor.path}`
|
||||
return (
|
||||
<>
|
||||
<Link href={currentPath}>
|
||||
<a>{ancestor.name}</a>
|
||||
</Link>
|
||||
<> / </>
|
||||
</>
|
||||
);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
function Title({ name, title, ancestors }: propsObj) {
|
||||
const pathElements = ancestors && createPathElements(ancestors) || <></>;
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1 className={style.container}>
|
||||
{props.title || props.name}
|
||||
{title || name}
|
||||
</h1>
|
||||
<div className={style.nav + ' h1'}>
|
||||
{
|
||||
props.name === ''
|
||||
? <>PaulW.XYZ / {props.name}</>
|
||||
: <><Link href='/'><a>PaulW.XYZ</a></Link> / {path()}{props.name}</>
|
||||
}
|
||||
<div className={`${style.nav} h1`}>
|
||||
{name
|
||||
? <><Link href='/'><a>PaulW.XYZ</a></Link> / {pathElements}{name}</>
|
||||
: <>PaulW.XYZ /</>}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
@ -6,13 +6,13 @@ module.exports = {
|
||||
webpack: (config, options) => {
|
||||
config.experiments = { asset: true };
|
||||
|
||||
const { cachePostsMeta } = require('./util/slug');
|
||||
const { cache } = require('./util/slug');
|
||||
|
||||
config.plugins.push(
|
||||
{
|
||||
apply: (compiler) => {
|
||||
compiler.hooks.initialize.tap('cachePostDataBC', _ => {
|
||||
cachePostsMeta();
|
||||
compiler.hooks.beforeCompile.tap('cachePostDataBC', _ => {
|
||||
cache();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1,46 +1,17 @@
|
||||
import Link from 'next/link';
|
||||
import React from 'react';
|
||||
import Layout from '../components/layout';
|
||||
import Pages from '../public/pages.json';
|
||||
import style from '../styles/home.module.css';
|
||||
import prettyDatePrint from '../util/pretty-date';
|
||||
import QuickLinks from '../components/quick-links';
|
||||
import RecentPosts from '../components/recent-posts';
|
||||
import { getPostsMeta, PostMeta } from '../util/slug';
|
||||
|
||||
function HomePage(props: { postsMeta: PostMeta[] }) {
|
||||
props.postsMeta.sort((x, y) => { return (x.title).localeCompare(y.title) });
|
||||
function HomePage({ postsMeta }: { postsMeta: PostMeta[] }) {
|
||||
return (
|
||||
<Layout name='' title='PaulW.XYZ'>
|
||||
<section className='block'>
|
||||
<div className='h2'>Welcome!</div>
|
||||
{
|
||||
Pages.map(obj => {
|
||||
return <span key={obj.link}>
|
||||
<Link href={obj.link}>
|
||||
{
|
||||
obj.link.match(/^http/)
|
||||
? <a className={`button blue ${style.button} ${style.blueButton}`}>{obj.title}</a>
|
||||
: <a className={`${style.button} button`}>{obj.title}</a>
|
||||
}
|
||||
</Link>
|
||||
</span>
|
||||
})
|
||||
}
|
||||
<QuickLinks />
|
||||
</section>
|
||||
<section className='block'>
|
||||
<table style={{ width: '100%' }}>
|
||||
<th className='h2'>Posts</th> <th>Posted</th>
|
||||
{props.postsMeta?.map((post: any) => {
|
||||
return <tr key={post.slug}>
|
||||
<td className='h5'>
|
||||
<Link href={`posts/${post.slug}`}>
|
||||
{post.title}
|
||||
</Link>
|
||||
</td>
|
||||
<td>{prettyDatePrint(new Date(post.created_at))}</td>
|
||||
|
||||
</tr>
|
||||
})}
|
||||
</table>
|
||||
<RecentPosts postsMeta={postsMeta} />
|
||||
</section>
|
||||
</Layout>
|
||||
)
|
||||
|
@ -1,70 +1,19 @@
|
||||
import React, { ReactElement } from 'react';
|
||||
import Layout from '../components/layout';
|
||||
import { mapChild, toListItem } from '../components/lists';
|
||||
import pl from '../public/playlists.yaml';
|
||||
|
||||
type listItem = {
|
||||
children?: listItem[];
|
||||
url?: string;
|
||||
title: string;
|
||||
};
|
||||
|
||||
function toListItem(record: Record<string, any>): listItem | null {
|
||||
if (!record.title)
|
||||
return null;
|
||||
|
||||
let children: listItem[] = [];
|
||||
if (record.children)
|
||||
for (const child of record.children) {
|
||||
const lChild = toListItem(child);
|
||||
if (lChild)
|
||||
children.push(lChild);
|
||||
}
|
||||
|
||||
return {
|
||||
title: record.title,
|
||||
url: record.url,
|
||||
children: children.length ? children : undefined,
|
||||
};
|
||||
}
|
||||
|
||||
const list: listItem[] = [];
|
||||
|
||||
function mapChild(obj: listItem, level: number) {
|
||||
if (obj.url)
|
||||
return <li key=''><a href={obj.url}>{obj.title}</a></li>
|
||||
|
||||
if (!obj.children)
|
||||
return <></> // ignore playlists without links
|
||||
|
||||
let title: ReactElement;
|
||||
if (level >= 0 && level <= 3)
|
||||
title = React.createElement(`h${level + 3}`, {}, obj.title);
|
||||
else
|
||||
title = React.createElement('strong', {}, obj.title);
|
||||
|
||||
return (
|
||||
<>
|
||||
{title}
|
||||
<ul>
|
||||
{obj.children.map(l => mapChild(l, level + 1))}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function Playlists() {
|
||||
return (
|
||||
<Layout name='Playlists'>
|
||||
<section className='block'>
|
||||
<h2>Music</h2>
|
||||
{
|
||||
pl.map((item: Record<string, any>) => {
|
||||
const lItem = toListItem(item)
|
||||
if (lItem)
|
||||
return mapChild(lItem, 0)
|
||||
})
|
||||
}
|
||||
</section>
|
||||
<h2>Music</h2>
|
||||
{
|
||||
pl.map((item: Record<string, any>) => {
|
||||
const lItem = toListItem(item)
|
||||
if (lItem)
|
||||
return mapChild(lItem, 0)
|
||||
})
|
||||
}
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
@ -1,28 +1,30 @@
|
||||
import Link from 'next/link';
|
||||
import React from 'react';
|
||||
import Layout from '../../components/layout';
|
||||
import prettyDatePrint from '../../util/pretty-date';
|
||||
import date from '../../util/date';
|
||||
import { getPostsMeta, PostMeta } from '../../util/slug';
|
||||
|
||||
function HomePage(props: {postsMeta: PostMeta[]}) {
|
||||
props.postsMeta.sort((x: any, y: any) => { return (x as any).title.localeCompare((y as any).title) });
|
||||
function HomePage({ postsMeta }: { postsMeta: PostMeta[] }) {
|
||||
// todo: create a table-like user interface
|
||||
return (
|
||||
return ( // wow this is horrible
|
||||
<Layout name='Posts'>
|
||||
<>
|
||||
<section className='h4 block'>
|
||||
Post Name <span style={{float: 'right', margin: 'auto 1rem'}}> Created on </span> <span style={{float: 'right', margin: 'auto 1rem'}}>Last Updated </span>
|
||||
Post Name
|
||||
<span style={{ float: 'right', margin: 'auto 1rem' }}> Created on </span>
|
||||
<span style={{ float: 'right', margin: 'auto 1rem' }}>Last Updated </span>
|
||||
</section>
|
||||
{props.postsMeta.map((post: any) => {
|
||||
return <section key='' className='h5 block'>
|
||||
<Link href={`posts/${post.slug}`}>
|
||||
{postsMeta.map((post: PostMeta, i) => {
|
||||
return <section key={i} className='h5 block'>
|
||||
<Link href={`/posts/${post.slug}`}>
|
||||
{post.title}
|
||||
</Link>
|
||||
<span className='h6' style={{float: 'right', margin: 'auto 1rem'}}>{prettyDatePrint(new Date(post.created_at))}</span>
|
||||
{post.last_updated ? <span className='h6' style={{float: 'right', margin: 'auto 1rem'}}>{prettyDatePrint(new Date(post.last_updated))}</span> : ''}
|
||||
<span className='h6' style={{ float: 'right', margin: 'auto 1rem' }}>
|
||||
{date.prettyPrint(new Date(post.created_at))}
|
||||
</span>
|
||||
{post.last_updated && <span className='h6' style={{ float: 'right', margin: 'auto 1rem' }}>
|
||||
{date.prettyPrint(new Date(post.last_updated))}
|
||||
</span>}
|
||||
</section>
|
||||
})}
|
||||
</>
|
||||
</Layout>
|
||||
)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Layout from '../components/layout';
|
||||
import rec from '../public/recommended.yaml';
|
||||
import { toListItem, mapChild } from '../util/resrec';
|
||||
import { toListItem, mapChild } from '../components/lists';
|
||||
|
||||
function Recommended() {
|
||||
return (
|
||||
|
@ -1,6 +1,6 @@
|
||||
import Layout from '../components/layout';
|
||||
import res from '../public/resources.yaml';
|
||||
import { toListItem, mapChild } from '../util/resrec';
|
||||
import { toListItem, mapChild } from '../components/lists';
|
||||
|
||||
function Resources() {
|
||||
return (
|
||||
|
@ -8,4 +8,21 @@
|
||||
url: https://youtube.com/playlist?list=PLSU6wJEYct5Etx0WAXUQ7YXe84Fp5E142
|
||||
- title: "[Youtube] Wolfgang Amadeus Mozart"
|
||||
url: https://youtube.com/playlist?list=PLSU6wJEYct5EJsE-9Zh-jWckBuZAmIt8Q
|
||||
- Große Fuge Op. 133
|
||||
- KV 387
|
||||
- KV 448
|
||||
- KV 626
|
||||
- Piano Sonata No. 2 Mvmt. 3 (Chopin)
|
||||
- BWV 1048
|
||||
- Prelude in G Minor (Op. 23 No. 5)
|
||||
- String Quartet, Op. 20 No. 2 (Haydn)
|
||||
- Arabesque No. 1 (Debussy)
|
||||
- title: Other
|
||||
children:
|
||||
- title: Rock
|
||||
children:
|
||||
- American Pie by Don McLean
|
||||
- title: Multimedia OST
|
||||
children:
|
||||
- L'Ultima Diligenza by Ennio Morricone
|
||||
|
@ -71,26 +71,6 @@
|
||||
- Dune (2021)
|
||||
- Hot Fuzz
|
||||
- Snatch
|
||||
- title: Music
|
||||
description: This is probably the most incomplete list. I have a playlists page so maybe I should move these there.
|
||||
children:
|
||||
- title: Rock
|
||||
children:
|
||||
- American Pie by Don McLean
|
||||
- title: Multimedia OST
|
||||
children:
|
||||
- L'Ultima Diligenza by Ennio Morricone
|
||||
- title: Classical
|
||||
children:
|
||||
- Große Fuge Op. 133
|
||||
- KV 387
|
||||
- KV 448
|
||||
- KV 626
|
||||
- Piano Sonata No. 2 Mvmt. 3 (Chopin)
|
||||
- BWV 1048
|
||||
- Prelude in G Minor (Op. 23 No. 5)
|
||||
- String Quartet, Op. 20 No. 2 (Haydn)
|
||||
- Arabesque No. 1 (Debussy)
|
||||
- title: Video Games
|
||||
children:
|
||||
- "The Legend of Zelda: Breath of the Wild"
|
||||
|
@ -180,24 +180,6 @@ section {
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.block .block {
|
||||
margin: 0 ;
|
||||
border-radius: 0;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
border-top: 1px dashed var(--main-border-color);
|
||||
border-left: 1px dashed var(--main-border-color);
|
||||
}
|
||||
|
||||
.block .block:first-of-type {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.block .block:last-of-type {
|
||||
border-bottom-left-radius: 1rem;
|
||||
border-bottom: 1px dashed var(--main-border-color);
|
||||
}
|
||||
|
||||
code {
|
||||
overflow-x: scroll;
|
||||
max-width: 100%;
|
||||
|
@ -19,3 +19,20 @@
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.block .block {
|
||||
margin: 0 ;
|
||||
border-radius: 0;
|
||||
border-right: none;
|
||||
border-bottom: none;
|
||||
border-top: 1px dashed var(--main-border-color);
|
||||
border-left: 1px dashed var(--main-border-color);
|
||||
}
|
||||
|
||||
.block .block:first-of-type {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.block .block:last-of-type {
|
||||
border-bottom-left-radius: 1rem;
|
||||
border-bottom: 1px dashed var(--main-border-color);
|
||||
}
|
||||
|
@ -1,14 +1,19 @@
|
||||
.button::after {
|
||||
content: ' \2192';
|
||||
margin-left: 0.5rem;
|
||||
display: inline-block;
|
||||
transition: 100ms ease-in-out all;
|
||||
margin-left: 0.3rem;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
display: inline-block;
|
||||
transition: 100ms ease-in-out all;
|
||||
}
|
||||
|
||||
.button:hover::after {
|
||||
transform: translateX(0.2rem) scale(1.1);
|
||||
transform: translateX(0.2rem) scale(1.3);
|
||||
}
|
||||
|
||||
.blueButton:hover::after {
|
||||
transform: rotateZ(-45deg) scale(1.5);
|
||||
}
|
||||
}
|
34
styles/recent-posts.module.css
Normal file
34
styles/recent-posts.module.css
Normal file
@ -0,0 +1,34 @@
|
||||
.container {
|
||||
border-bottom-left-radius: 1rem;
|
||||
border-bottom: 1px dashed var(--main-border-color);
|
||||
border-left: 1px dashed var(--main-border-color);
|
||||
padding-top: 1.5rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.block {
|
||||
padding: 0.25rem 0.5rem;
|
||||
margin: 0 0.5rem 0.25rem 0;
|
||||
border-top: 1px dashed var(--main-border-color);
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.postTitle {
|
||||
flex-grow: 8;
|
||||
padding: 0.1rem 0.2rem;
|
||||
}
|
||||
|
||||
.postDate {
|
||||
font-style: italic;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
.more {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.more a {
|
||||
text-decoration: none;
|
||||
}
|
@ -15,6 +15,6 @@
|
||||
"jsx": "preserve",
|
||||
"importHelpers": true
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "util/post-cache.js", "util/slug.js"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "util/slug.js"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
@ -13,11 +13,13 @@ const months = [
|
||||
'December'
|
||||
];
|
||||
|
||||
const suffixes = ['','st','nd','rd','th'];
|
||||
const ordSfx = ['','st','nd','rd','th'];
|
||||
|
||||
function prettyPrint(date: Date | string): string {
|
||||
const oDate = (typeof date === 'string')? new Date(date): date;
|
||||
|
||||
export default function prettyDatePrint(date: Date) {
|
||||
const now = new Date();
|
||||
const diff = now.getTime() - date.getTime();
|
||||
const diff = now.getTime() - oDate.getTime();
|
||||
|
||||
let tdiff = Math.floor(diff/1000);
|
||||
|
||||
@ -38,13 +40,27 @@ export default function prettyDatePrint(date: Date) {
|
||||
return `Yesterday`;
|
||||
}
|
||||
|
||||
const year = date.getFullYear();
|
||||
const month = months[date.getMonth()];
|
||||
const day = date.getDate();
|
||||
const year = oDate.getFullYear();
|
||||
const month = months[oDate.getMonth()];
|
||||
const day = oDate.getDate();
|
||||
|
||||
let sfx;
|
||||
if (day >= 1 && day <= 3)
|
||||
sfx = suffixes[day];
|
||||
sfx = ordSfx[day];
|
||||
else
|
||||
sfx = suffixes[4];
|
||||
return `${day}${sfx} ${month} ${year}`;
|
||||
}
|
||||
sfx = ordSfx[4];
|
||||
if (year != now.getFullYear())
|
||||
return `${day}${sfx} ${month} ${year}`;
|
||||
return `${day}${sfx} ${month}`;
|
||||
}
|
||||
|
||||
function isValid(date: any) {
|
||||
return (new Date(date)).toString() === 'Invalid Date';
|
||||
}
|
||||
|
||||
const d = {
|
||||
prettyPrint,
|
||||
isValid
|
||||
};
|
||||
|
||||
export default d;
|
31
util/slug.js
31
util/slug.js
@ -3,6 +3,7 @@ const matter = require('gray-matter');
|
||||
const { join } = require('path');
|
||||
|
||||
const postsDir = join(process.cwd(), 'posts');
|
||||
const cacheDir = join(process.cwd(), '.cache');
|
||||
|
||||
function getPost(rawslug, filter = []) {
|
||||
const slug = rawslug.replace(/\.md$/, '');
|
||||
@ -11,7 +12,7 @@ function getPost(rawslug, filter = []) {
|
||||
const { data, content } = matter(file);
|
||||
|
||||
if (data['last_updated'] === undefined)
|
||||
data['last_updated'] = data['created_at'];
|
||||
data['last_updated'] = '';
|
||||
|
||||
if (filter.length === 0)
|
||||
return { ...data, content, slug, rawslug };
|
||||
@ -41,13 +42,24 @@ function getAllPosts(filter = []) {
|
||||
.filter(c => (!c.match(/^\.]/) && c.match(/\.md$/)))
|
||||
.map(file => {
|
||||
return getPost(file, filter)
|
||||
})
|
||||
.sort((a, b) => {
|
||||
const dA = new Date(a['created_at']);
|
||||
const dB = new Date(b['created_at']);
|
||||
return dB - dA;
|
||||
});
|
||||
}
|
||||
|
||||
const postMetaCacheFile = join(cacheDir, 'posts.meta.json');
|
||||
|
||||
function cachePostsMeta() { // public access cache
|
||||
const posts = getAllPosts(['title', 'slug', 'created_at', 'last_updated']);
|
||||
fs.writeFile(join(postsDir, 'meta.json'), JSON.stringify(posts), (e) => {
|
||||
|
||||
if (!fs.existsSync(cacheDir)) {
|
||||
fs.mkdirSync(cacheDir);
|
||||
}
|
||||
|
||||
fs.writeFile(postMetaCacheFile, JSON.stringify(posts), (e) => {
|
||||
if (e)
|
||||
console.error(e);
|
||||
});
|
||||
@ -55,13 +67,16 @@ function cachePostsMeta() { // public access cache
|
||||
}
|
||||
|
||||
function getPostsMeta() {
|
||||
const file = fs.readFileSync(join(postsDir, 'meta.json'), 'utf-8');
|
||||
|
||||
if (!file) {
|
||||
try {
|
||||
const file = fs.readFileSync(postMetaCacheFile, 'utf-8');
|
||||
return JSON.parse(file);
|
||||
} catch (e) {
|
||||
return cachePostsMeta();
|
||||
}
|
||||
|
||||
return JSON.parse(file);
|
||||
}
|
||||
|
||||
module.exports = { getAllPosts, getPost, getPostsMeta, cachePostsMeta };
|
||||
function cache() {
|
||||
cachePostsMeta();
|
||||
}
|
||||
|
||||
module.exports = { getAllPosts, getPost, getPostsMeta, cache };
|
Loading…
Reference in New Issue
Block a user