aboutsummaryrefslogtreecommitdiff
path: root/pages
diff options
context:
space:
mode:
Diffstat (limited to 'pages')
-rw-r--r--pages/_app.tsx13
-rw-r--r--pages/index.tsx72
-rw-r--r--pages/post/[id].tsx123
-rw-r--r--pages/search.tsx165
4 files changed, 190 insertions, 183 deletions
diff --git a/pages/_app.tsx b/pages/_app.tsx
index 62c1c9b..662f841 100644
--- a/pages/_app.tsx
+++ b/pages/_app.tsx
@@ -1,20 +1,19 @@
import Head from 'next/head';
+import '../styles/button.css';
import '../styles/colors.css';
-import '../styles/layout.css';
import '../styles/globals.css';
-import '../styles/navbar.css';
-import '../styles/button.css';
import '../styles/image.css';
-import '../styles/tags.css';
+import '../styles/layout.css';
+import '../styles/navbar.css';
import '../styles/search.css';
+import '../styles/tags.css';
export default function Blog({ Component, pageProps }) {
return <div>
<Head>
- <link rel="stylesheet" href="/font/font.css"/>
+ <link rel='stylesheet' href='/font/font.css' />
</Head>
<Component {...pageProps} />
- </div>
+ </div>;
}
-
diff --git a/pages/index.tsx b/pages/index.tsx
index 96b8684..65b53cb 100644
--- a/pages/index.tsx
+++ b/pages/index.tsx
@@ -1,52 +1,52 @@
-import Navbar, { NavbarItem } from '../components/navbar';
import Chapters, { chapter } from '../components/chapters';
+import Navbar, { NavbarItem } from '../components/navbar';
import Seperator from '../components/seperator';
-import { getStaticProps as getBlogPage, ArticleMeta, RenderedArticle } from './post/[id]';
+import { ArticleMeta, getStaticProps as getBlogPage, RenderedArticle } from './post/[id]';
-var posts = ["index", "index", "index"];
+var posts = ['index', 'index', 'index'];
export default function Home(props: {
posts: Array<{
props: {
- content: string,
- meta: ArticleMeta
- }
- }>
+ content: string;
+ meta: ArticleMeta;
+ };
+ }>;
}) {
return <div>
- <div className="centeredPage">
- <div className="titleWrapper">
+ <div className='centeredPage'>
+ <div className='titleWrapper'>
<h1>{props.posts[0].props.meta.title}</h1>
</div>
- <div className="navAreaWrapper">
- <div className="sticky">
- <Navbar page="home"/>
- <NavbarItem title="Pinned posts:" classList={["pinned"]}/>
- <Chapters chapters={[
- ...props.posts.slice(1).map(post => {
- return {
- children: post.props.meta.chapters,
- name: post.props.meta.title,
- sectionLink: "/post/" + post.props.meta.id
- } as chapter
- })
- ]}/>
+ <div className='navAreaWrapper'>
+ <div className='sticky'>
+ <Navbar page='home' />
+ <NavbarItem title='Pinned posts:' classList={['pinned']} />
+ <Chapters
+ chapters={[
+ ...props.posts.slice(1).map(post => {
+ return {
+ children: post.props.meta.chapters,
+ name: post.props.meta.title,
+ sectionLink: '/post/' + post.props.meta.id,
+ } as chapter;
+ }),
+ ]}
+ />
</div>
</div>
- <div className="contentWrapper">
- {
- props.posts.map((post, index) => {
- return <>
- { index != 0 && <h1>{post.props.meta.title}</h1> }
- <RenderedArticle content={post.props.content}/>
- { index + 1 != props.posts.length && <Seperator/> }
- </>
- })
- }
+ <div className='contentWrapper'>
+ {props.posts.map((post, index) => {
+ return <>
+ {index != 0 && <h1>{post.props.meta.title}</h1>}
+ <RenderedArticle content={post.props.content} />
+ {index + 1 != props.posts.length && <Seperator />}
+ </>;
+ })}
</div>
</div>
- </div>
+ </div>;
}
export function getStaticProps() {
@@ -54,9 +54,9 @@ export function getStaticProps() {
posts.forEach(id => {
postsContent.push(getBlogPage({ params: { id } }));
- })
+ });
var staticProps = { props: { posts: postsContent } };
-
- return staticProps
+
+ return staticProps;
}
diff --git a/pages/post/[id].tsx b/pages/post/[id].tsx
index b68b790..c0d4e9d 100644
--- a/pages/post/[id].tsx
+++ b/pages/post/[id].tsx
@@ -1,14 +1,14 @@
-import { ReactNode } from 'react';
import ReactMarkdownWithHTML from 'react-markdown/with-html';
import { readdirSync, readFileSync } from 'fs';
import { join } from 'path';
+import { ReactNode } from 'react';
import gfm from 'remark-gfm';
-import Seperator from '../../components/seperator';
import Navbar from '../../components/navbar';
+import Seperator from '../../components/seperator';
// import Button from '../../components/button';
-import Image from '../../components/image';
import Chapters, { chapter } from '../../components/chapters';
+import Image from '../../components/image';
import Tags from '../../components/tag';
export interface ArticleMeta {
@@ -21,70 +21,72 @@ export interface ArticleMeta {
id?: string;
}
-export function RenderedArticle(props: { content: string }) {
+export function RenderedArticle(props: { content: string; }) {
return <ReactMarkdownWithHTML
- plugins={[gfm]}
- allowDangerousHtml
- children={props.content}
- renderers={{
- image: Image,
- thematicBreak: Seperator,
- heading: Heading,
- }}/>;
+ plugins={[gfm]}
+ allowDangerousHtml
+ children={props.content}
+ renderers={{
+ image: Image,
+ thematicBreak: Seperator,
+ heading: Heading,
+ }}
+ />;
}
var headingLevel = (input: string) => input?.match(/^[#]+/)[0]?.length || 0;
-var sectionID = (input: string) => input
- .replace(/[()\[\]{}!@#$%^&*<>?,./\;':"\\|=+]/g, "")
- .replace(/\s/g, "-")
- .toLowerCase();
+var sectionID = (input: string) =>
+ input
+ .replace(/[()\[\]{}!@#$%^&*<>?,./\;':"\\|=+]/g, '')
+ .replace(/\s/g, '-')
+ .toLowerCase();
function Heading(props: {
children?: ReactNode;
level?: number;
}) {
- var HeadingTag = "h" + props.level as keyof JSX.IntrinsicElements;
- return <HeadingTag id={sectionID(props.children[0].props.children)} children={props.children}/>
+ var HeadingTag = 'h' + props.level as keyof JSX.IntrinsicElements;
+ return <HeadingTag id={sectionID(props.children[0].props.children)} children={props.children} />;
}
export default function Post(props: {
- content: string,
- meta: ArticleMeta
+ content: string;
+ meta: ArticleMeta;
}) {
return <div>
- <div className="centeredPage">
- <div className="titleWrapper">
+ <div className='centeredPage'>
+ <div className='titleWrapper'>
<h1>{props.meta.title}</h1>
- <p className="subtile">{props.meta.subtitle}</p>
- { props.meta.tags && <Tags tags={props.meta.tags}/> }
+ <p className='subtile'>{props.meta.subtitle}</p>
+ {props.meta.tags && <Tags tags={props.meta.tags} />}
</div>
- <div className="navAreaWrapper">
- <div className="sticky">
- <Navbar/>
- <Chapters chapters={props.meta.chapters}/>
+ <div className='navAreaWrapper'>
+ <div className='sticky'>
+ <Navbar />
+ <Chapters chapters={props.meta.chapters} />
</div>
</div>
- <div className="contentWrapper">
- <RenderedArticle content={props.content}/>
+ <div className='contentWrapper'>
+ <RenderedArticle content={props.content} />
</div>
</div>
- </div>
+ </div>;
}
var parseTag = {
- "title": (val: string) => val,
- "subtitle": (val: string) => val,
- "author": (val: string) => val,
- "tags": (val: string) => val.split(",").map(i => i.trim()),
- "date": (val: string) => new Date(val).toDateString(),
-}
+ 'title': (val: string) => val,
+ 'subtitle': (val: string) => val,
+ 'author': (val: string) => val,
+ 'tags': (val: string) => val.split(',').map(i => i.trim()),
+ 'date': (val: string) => new Date(val).toDateString(),
+};
function parseMeta(file: Array<string>): ArticleMeta {
var meta: ArticleMeta = {};
file.forEach(line => {
- if (!line.startsWith("[meta]: ")) return;
+ if (!line.startsWith('[meta]: ')) return;
var tags = line.match(/\[meta\]:\s+\<(.+?)\>\s+\((.+?)\)/);
if (!tags || !tags[1] || !tags[2]) return;
if (!parseTag.hasOwnProperty(tags[1])) return;
@@ -98,7 +100,7 @@ function parseToCRecursive(headings: Array<string>): Array<chapter> {
interface WIPchapter extends chapter {
unparsedChildren?: Array<string>;
}
- var children: Array<WIPchapter> = []
+ var children: Array<WIPchapter> = [];
var lowestLevel = headingLevel(headings[0]);
var currentChildIndex = -1;
@@ -108,44 +110,44 @@ function parseToCRecursive(headings: Array<string>): Array<chapter> {
var chapterName = headings[i].match(/^[#]+\s+(.+)/)[1];
children.push({
name: chapterName,
- sectionLink: "#" + sectionID(chapterName),
+ sectionLink: '#' + sectionID(chapterName),
unparsedChildren: [],
});
currentChildIndex += 1;
} else {
- children[currentChildIndex].unparsedChildren.push(headings[i])
+ children[currentChildIndex].unparsedChildren.push(headings[i]);
}
}
children.map(child => {
- child.children = parseToCRecursive(child.unparsedChildren)
+ child.children = parseToCRecursive(child.unparsedChildren);
delete child.unparsedChildren;
- return child
- })
+ return child;
+ });
return children as Array<chapter>;
}
function parseToC(file: Array<string>): Array<chapter> {
- var fileAsStr = file.join("\n");
- fileAsStr = fileAsStr.replace(/```.*?```/gs, ""); // filter out code blocks from table of contents
- var fileAsArr = fileAsStr.split("\n");
- var chapterStrings = fileAsArr.filter(line => line.startsWith("#"));
+ var fileAsStr = file.join('\n');
+ fileAsStr = fileAsStr.replace(/```.*?```/gs, ''); // filter out code blocks from table of contents
+ var fileAsArr = fileAsStr.split('\n');
+ var chapterStrings = fileAsArr.filter(line => line.startsWith('#'));
return parseToCRecursive(chapterStrings);
}
function preprocessor(fileContent: string) {
- var fileAsArr = fileContent.split("\n");
+ var fileAsArr = fileContent.split('\n');
var meta = parseMeta(fileAsArr);
meta.chapters = parseToC(fileAsArr);
- var result = fileAsArr.join("\n").trim()
- return { meta, result }
+ var result = fileAsArr.join('\n').trim();
+ return { meta, result };
}
-export function getStaticProps(props: {params: { id: string }}) {
- var filename = join("posts/", props.params.id + ".md")
- var filecontent = readFileSync(filename).toString().trim()
+export function getStaticProps(props: { params: { id: string; }; }) {
+ var filename = join('posts/', props.params.id + '.md');
+ var filecontent = readFileSync(filename).toString().trim();
var parsed = preprocessor(filecontent);
parsed.meta.id = props.params.id;
@@ -155,21 +157,20 @@ export function getStaticProps(props: {params: { id: string }}) {
content: parsed.result,
meta: parsed.meta,
},
- }
+ };
}
export function getStaticPaths() {
- var files = readdirSync("posts").filter(f => f.endsWith(".md"));
+ var files = readdirSync('posts').filter(f => f.endsWith('.md'));
return {
paths: files.map((f) => {
return {
params: {
- id: f.substr(0, f.length - 3)
- }
- }
+ id: f.substr(0, f.length - 3),
+ },
+ };
}),
fallback: false,
- }
+ };
}
-
diff --git a/pages/search.tsx b/pages/search.tsx
index c9b27a5..8eff8d8 100644
--- a/pages/search.tsx
+++ b/pages/search.tsx
@@ -1,65 +1,69 @@
-import { useState, useEffect } from 'react';
import Fuse from 'fuse.js';
+import { useEffect, useState } from 'react';
import Navbar from '../components/navbar';
-import Tags from '../components/tag'
+import Tags from '../components/tag';
import SearchOutlinedIcon from '@material-ui/icons/SearchOutlined';
-function SearchBar(props: { searchFunction: () => void }) {
- return <div className="searchBar">
+function SearchBar(props: { searchFunction: () => void; }) {
+ return <div className='searchBar'>
<input
- className="input"
- id="searchInput"
- placeholder="Search for posts..."
- onChange={() => props.searchFunction()}
- spellCheck="false"
- autoComplete="off"/>
- <button className="button" onClick={() => props.searchFunction()}><SearchOutlinedIcon/></button>
- </div>
+ className='input'
+ id='searchInput'
+ placeholder='Search for posts...'
+ onChange={() => props.searchFunction()}
+ spellCheck='false'
+ autoComplete='off'
+ />
+ <button className='button' onClick={() => props.searchFunction()}>
+ <SearchOutlinedIcon />
+ </button>
+ </div>;
}
interface Post {
- title: string
- subtitle: string
- author: string
- date: string
- urlname: string
- tags: Array<string>
+ title: string;
+ subtitle: string;
+ author: string;
+ date: string;
+ urlname: string;
+ tags: Array<string>;
}
interface PostsInfo {
- valid_tags: Array<string>
- posts: Array<Post>
+ valid_tags: Array<string>;
+ posts: Array<Post>;
}
-function Post(props: { post: Post }) {
- return <a className="post" href={"/post/" + props.post.urlname}>
- <b className="title">{props.post.title}</b>
- {props.post.subtitle && <p className="subtitle">{props.post.subtitle}</p>}
- <p className="authordate">Written by {props.post.author} on {new Date(props.post.date).toLocaleString("en-us", {
- month: "long", day: "numeric"
- })}</p>
- <Tags tags={props.post.tags}/>
+function Post(props: { post: Post; }) {
+ return <a className='post' href={'/post/' + props.post.urlname}>
+ <b className='title'>{props.post.title}</b>
+ {props.post.subtitle && <p className='subtitle'>{props.post.subtitle}</p>}
+ <p className='authordate'>
+ Written by {props.post.author} on {new Date(props.post.date).toLocaleString('en-us', {
+ month: 'long',
+ day: 'numeric',
+ })}
+ </p>
+ <Tags tags={props.post.tags} />
</a>;
}
-function Posts(props: { posts: Array<Post> }) {
- return <div className="searchResults">
- {
- props.posts.map(post => <Post post={post} key={Math.random().toString()}/>)
- }
+function Posts(props: { posts: Array<Post>; }) {
+ return <div className='searchResults'>
+ {props.posts.map(post => <Post post={post} key={Math.random().toString()} />)}
</div>;
}
function searchFilter(query: string, tags: Array<string>) {
var output = {
- query: "",
- tags: []
- }
+ query: '',
+ tags: [],
+ };
// remove string literals from tag matching
- var queryWithoutLiterals = query.replace(/\".+?\"/g, "");
+ var queryWithoutLiterals = query.replace(/\".+?\"/g, '');
// find tags and remove them from the query
tags.forEach(tag => {
@@ -67,55 +71,56 @@ function searchFilter(query: string, tags: Array<string>) {
if (index == -1) return;
// remove tag from query
- queryWithoutLiterals =
- queryWithoutLiterals.substr(0, index) +
- queryWithoutLiterals.substr(index + tag.length);
+ queryWithoutLiterals = queryWithoutLiterals.substr(0, index)
+ + queryWithoutLiterals.substr(index + tag.length);
output.tags.push(tag);
});
// add back in the string literals (janky just gets pasted on end)
- output.query =
- queryWithoutLiterals + " " +
- (query.match(/\".+?\"/g)
+ output.query = queryWithoutLiterals + ' '
+ + (query.match(/\".+?\"/g)
?.map(r => r.substr(1, r.length - 2))
- .join(" ") || "");
+ .join(' ') || '');
return output;
}
export default function SearchPage() {
var [posts, setPosts] = useState<PostsInfo>({ posts: [], valid_tags: [] });
- var [query, setQuery] = useState("-");
+ var [query, setQuery] = useState('-');
var [visiblePosts, setVisiblePosts] = useState<Array<Post>>([]);
var fuse = new Fuse(posts.posts, {
keys: [
- "title",
- "subtitle",
- "author",
- "date",
- "urlname",
- "tags"
+ 'title',
+ 'subtitle',
+ 'author',
+ 'date',
+ 'urlname',
+ 'tags',
],
- isCaseSensitive: false
- })
+ isCaseSensitive: false,
+ });
- useEffect(() => {(async () => {
- var query = new URLSearchParams(window.location.search).get("q") || "";
- if(query)
- (document.getElementById("searchInput") as HTMLInputElement).value = query;
+ useEffect(() => {
+ (async () => {
+ var query = new URLSearchParams(window.location.search).get('q') || '';
+ if (query) {
+ (document.getElementById('searchInput') as HTMLInputElement).value = query;
+ }
- var posts = await fetch("/posts.json");
- var postsJson: PostsInfo = await posts.json();
- postsJson.posts = postsJson.posts.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime())
- setPosts(postsJson);
- setQuery(query);
- })()}, []);
+ var posts = await fetch('/posts.json');
+ var postsJson: PostsInfo = await posts.json();
+ postsJson.posts = postsJson.posts.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
+ setPosts(postsJson);
+ setQuery(query);
+ })();
+ }, []);
useEffect(() => {
var search = searchFilter(query, posts.valid_tags);
- if(search.query.length == 0) {
+ if (search.query.length == 0) {
var results = posts.posts;
} else {
var fuseSearch = fuse.search(search.query);
@@ -123,32 +128,34 @@ export default function SearchPage() {
}
results = results.filter(result => {
- for(var i in search.tags) {
- if (!result.tags.includes(search.tags[i]))
+ for (var i in search.tags) {
+ if (!result.tags.includes(search.tags[i])) {
return false;
+ }
}
return true;
});
- setVisiblePosts(results)
+ setVisiblePosts(results);
}, [query]);
return <div>
- <div className="centeredPage">
- <div className="titleWrapper">
+ <div className='centeredPage'>
+ <div className='titleWrapper'>
<h1>Search for posts</h1>
</div>
- <div className="navAreaWrapper">
- <div className="sticky">
- <Navbar page="search"/>
+ <div className='navAreaWrapper'>
+ <div className='sticky'>
+ <Navbar page='search' />
</div>
</div>
- <div className="contentWrapper">
- <SearchBar searchFunction={() => {
- setTimeout(() => setQuery((document.getElementById("searchInput") as HTMLInputElement).value));
- }}/>
- <Posts posts={visiblePosts}/>
+ <div className='contentWrapper'>
+ <SearchBar
+ searchFunction={() => {
+ setTimeout(() => setQuery((document.getElementById('searchInput') as HTMLInputElement).value));
+ }}
+ />
+ <Posts posts={visiblePosts} />
</div>
</div>
- </div>
+ </div>;
}
-