diff options
author | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-09-07 21:28:37 -0500 |
---|---|---|
committer | flu0r1ne <flu0r1ne@flu0r1ne.net> | 2023-09-07 21:28:37 -0500 |
commit | d67f3514eff4f45ad1ca84cde6465e622acd4dcc (patch) | |
tree | 55f9c8e4f68f1269300b937fb14ae76e3446d621 | |
parent | ef4fb0a5277ee99bd0f1747b77e733ef7f02460d (diff) | |
download | homepage-d67f3514eff4f45ad1ca84cde6465e622acd4dcc.tar.xz homepage-d67f3514eff4f45ad1ca84cde6465e622acd4dcc.zip |
Scoped global styling to all markdown
Make React compatible with markdown-style HTML by added components
with identical styling to markdown. This is done while CSS scoping
is maintained. Additional style is loaded through the markdown loader
by injecting default-styling tags into the components. This allows
default-margin to be added to these elements in addition to the styling
found in the React elements. The homepage reflects the domain, as defined
by an environmental variable.
27 files changed, 815 insertions, 254 deletions
diff --git a/components/Box/index.tsx b/components/Box/index.tsx index 32866b2..f81fa5b 100644 --- a/components/Box/index.tsx +++ b/components/Box/index.tsx @@ -3,15 +3,23 @@ import { getSystemStyle, SystemProps } from '../utils/systemProps'; interface BoxProps extends SystemProps { style?: React.CSSProperties; children?: React.ReactNode; + el?: keyof React.ReactHTML; }; -const Box: React.FC<BoxProps> = ({ style, children, ...props}) => { +const Box: React.FC<BoxProps> = ({ el, style, children, ...props}) => { const systemStyle = getSystemStyle(props, style); + let Tag = el; + + if(!el) { + Tag = 'div' as keyof React.ReactHTML; + } + return ( - <div style={systemStyle}> + // @ts-ignore + <Tag style={systemStyle}> { children } - </div> + </Tag> ); }; diff --git a/components/BreadCrumbs/index.tsx b/components/BreadCrumbs/index.tsx index 693a9d0..98b20b4 100644 --- a/components/BreadCrumbs/index.tsx +++ b/components/BreadCrumbs/index.tsx @@ -1,5 +1,5 @@ import React, { Children, FC } from "react"; -import Link from "next/link"; +import Link from '../Link'; import styles from './breadcrumbs.module.scss'; import clsx from 'clsx'; @@ -9,8 +9,8 @@ export type BreadCrumbsProps = { children: React.ReactNode; }; -const BreadCrumbs : FC<BreadCrumbsProps> = ({children, className, ...props}) => ( - <span className={clsx(styles.breadcrumbs, className)} {...props}> +const BreadCrumbs : FC<BreadCrumbsProps> = ({children, className, style, ...props}) => ( + <span style={{ whiteSpace: 'nowrap', ...style }} className={clsx(styles.breadcrumbs, className)} {...props}> {Children.map(children, (child, index) => { return ( <> diff --git a/components/Code/index.tsx b/components/Code/index.tsx new file mode 100644 index 0000000..23e7a8b --- /dev/null +++ b/components/Code/index.tsx @@ -0,0 +1,10 @@ +import React, { FC, CSSProperties } from 'react'; + +interface CodeProps extends React.HTMLProps<HTMLSpanElement> { + style?: CSSProperties; +} +const Code: FC<CodeProps> = ({ children, style }) => { + return <code className='md-codespan' style={style}>{children}</code>; +}; + +export default Code; diff --git a/components/Link/index.tsx b/components/Link/index.tsx new file mode 100644 index 0000000..e6477c2 --- /dev/null +++ b/components/Link/index.tsx @@ -0,0 +1,23 @@ +import React, { ReactNode } from 'react'; +import NextLink from 'next/link'; +import styles from './link.module.scss'; +import clsx from 'clsx'; + +interface LinkProps { + href: string; + children: ReactNode; + className?: string; +} + +const Link: React.FC<LinkProps> = ({ href, className, children }) => { + return ( + <NextLink + href={href} + className={clsx('md-a', className)} + > + {children} + </NextLink> + ); +}; + +export default Link; diff --git a/components/Link/link.module.scss b/components/Link/link.module.scss new file mode 100644 index 0000000..b6ef943 --- /dev/null +++ b/components/Link/link.module.scss @@ -0,0 +1,11 @@ +.link { + text-decoration: none; +} + +.link:hover { + text-decoration: underline; +} + +.link, .link:visited, .link:active, .link:hover { + color: #0716ea; +} diff --git a/components/List/index.tsx b/components/List/index.tsx new file mode 100644 index 0000000..ae5c190 --- /dev/null +++ b/components/List/index.tsx @@ -0,0 +1,52 @@ +import React, { FC } from 'react'; +import { getSystemStyle, SystemProps } from '../utils/systemProps'; +import clsx from 'clsx'; + +interface ListProps extends SystemProps { + style?: React.CSSProperties; + variant : 'ordered' | 'unordered'; + children?: React.ReactNode; + className?: string; +}; + +const List : FC<ListProps> = ({ style, className, variant, children, ...props }) => { + + const systemStyle = getSystemStyle(props, style); + + const Tag = { + 'ordered': 'ol', + 'unordered': 'ul' + }[variant] as keyof React.ReactHTML; + + const styleClass = 'md-' + Tag; + + return ( + <Tag + className={clsx(styleClass, 'md-list', className)} + children={children} + style={systemStyle} + /> + ); +}; + +interface ListItemProps extends SystemProps { + style?: React.CSSProperties; + children?: React.ReactNode; + className?: string; +}; + +const ListItem : FC<ListItemProps> = ({ style, className, children, ...props }) => { + const systemStyle = getSystemStyle(props, style); + + return ( + <li + className={clsx('md-li', className)} + style={systemStyle} + >{children}</li> + ); +} + +export { + List, + ListItem +}; diff --git a/components/List/list.module.scss b/components/List/list.module.scss new file mode 100644 index 0000000..87ec3a3 --- /dev/null +++ b/components/List/list.module.scss @@ -0,0 +1,41 @@ +.list-li { + font-size: 1rem; + letter-spacing: 0.00938em; + + line-height: 1.4; + margin-left: 1em; + + list-style-image: none; + list-style-position: inside; + list-style-type: none; + + box-sizing: border-box; + + font-size: 1rem; +} + +.list-unordered li:not(:first-child) { + margin-top: 0.15rem; +} + +.list { + .list li:first-child { + margin-top: 0.15rem !important; + } +} + +.list-unordered li { + list-style-type: disc; +} + +.list .list-unordered li { + list-style-type: circle; +} + +.list .list .list-unordered li { + list-style-type: square; +} + +.list-ordered li { + list-style-type: decimal; +} diff --git a/components/Markdown/index.tsx b/components/Markdown/index.tsx index 1a71330..b6def4f 100644 --- a/components/Markdown/index.tsx +++ b/components/Markdown/index.tsx @@ -1,24 +1,24 @@ import React, { FC } from 'react'; -import styles from './markdown.module.scss'; + import clsx from 'clsx'; interface MarkdownProps { md: string; className?: string; - props?: object; } -const Markdown : FC<MarkdownProps> = ({md, className, ...props}) => ( - <div - className={clsx(styles.markdownContainer, className)} +const Markdown : FC<MarkdownProps> = ({md, className}) => { + const prerendered = ( + <div dangerouslySetInnerHTML={{ __html: md }} - - {...props} /> -); + ); + + return prerendered; +}; export type { MarkdownProps diff --git a/components/Markdown/markdown.module.scss b/components/Markdown/markdown.module.scss deleted file mode 100644 index e1debd1..0000000 --- a/components/Markdown/markdown.module.scss +++ /dev/null @@ -1,111 +0,0 @@ -.markdownContainer { - strong { - font-weight: 600; - } - - h1 { - font-size: 2.8rem; - font-weight: 300; - line-height: 1.167; - letter-spacing: -0.01562em; - margin-top: 1.0rem; - margin-bottom: 1rem; - - padding-bottom: 0.4rem; - border-bottom: 0.12rem solid rgb(53, 53, 53); - } - - h2 { - font-size: 2.3rem; - font-weight: 300; - line-height: 1.2; - letter-spacing: -0.00833em; - - margin-top: 1.6rem; - margin-bottom: 0.8rem; - } - - h3 { - font-size: 1.3rem; - font-weight: 400; - line-height: 1.167; - letter-spacing: 0em; - - margin-top: 1.3rem; - margin-bottom: 0.5rem; - } - - h4 { - font-size: 1.25rem; - } - - h5 { - font-size: 1.15rem; - } - - h6 { - font-size: 1.10rem; - } - - h4, h5, h6 { - margin-top: 0.8rem; - margin-bottom: 0.6rem; - } - - p, li { - font-size: 1rem; - letter-spacing: 0.00938em; - font-weight: 300; - } - - p { - font-size: 1rem; - line-height: 1.5; - margin-bottom: 1em; - } - - code { - font-size: 1rem; - line-height: 1.5; - padding: 0.05rem 0.2rem; - } - - pre { - padding: 0.5rem 1.0rem; - margin: 0.5rem 0; - box-sizing: border-box; - } - pre > code { - padding: 0; - } - - code, pre { - background-color: #f2f4f7; - border-radius: 5px; - } - - pre { - overflow: auto; - box-sizing: border-box; - } - - @media screen and (max-width: 700px) { - pre { - padding-bottom: 0.7rem; - } - } - - li { - line-height: 1.15; - margin-left: 1em; - margin-top: 0.3em; - list-style-image: none; - list-style-position: outside; - list-style-type: circle; - } - - img { - max-width: 95%; - margin: 2em 2.5%; - } -} diff --git a/components/Markdown/markdown.scss b/components/Markdown/markdown.scss new file mode 100644 index 0000000..e529e66 --- /dev/null +++ b/components/Markdown/markdown.scss @@ -0,0 +1,418 @@ +/* AUTOMATIC MARGIN APPLIED WHEN md-dl */ + +.md-dl.md-h1, .md-dl.md-h2, .md-dl.md-h3, .md-dl.md-h4, .md-dl.md-h5, .md-dl.md-h6 { + margin-top: 20px; + margin-bottom: 14px; +} + +.md-dl.md-list, .md-dl.md-pre, .md-dl.md-p, .md-dl.md-table, .md-dl.md-blockquote { + margin-bottom: 14px; +} + +.md-dl.md-list .md-list { + margin-bottom: 0; +} + +.md-dl.md-blockquote > :last-child { + margin-bottom: 0; +} + +.md-dl.md-wrapper > :first-child { + margin-top: 0; +} + +/* LINKS */ + +.md-a { + text-decoration: none; +} + +.md-a:hover { + text-decoration: underline; +} + +.md-a, .md-a:visited, .md-a:active, .md-a:hover { + color: #0716ea; +} + +/* TEXT */ + +.md-blockquote, .md-p, .md-li { + font-size: 1rem; + letter-spacing: 0.00938em; + line-height: 1.5; +} + +.md-code { + font-size: 1rem; + line-height: 1.25; +} + +.md-strong { + font-weight: bold; +} + +.md-em { + font-style: italic; +} + +/* LISTS */ + +.md-li { + line-height: 1.25; + margin-left: 1em; + + list-style-image: none; + list-style-position: inside; + list-style-type: none; +} + +// allow wrapping with inside list-style-position elements +.md-li > p { + display: inline; +} + +.md-dl.md-li > p { + margin-bottom: 0; + + &::after { + content: ""; + display: block; + margin-bottom: 14px; + } +} + +.md-li-checkbox { + list-style-type: none !important; +} + +.md-checkbox { + margin: 0; + margin-right: 0.5em; +} + +// UP TO FOUR LEVELS OF DECORATORS + +.md-ol > li { + list-style-type: decimal; +} + +.md-ul > li { + list-style-type: disc; +} + +.md-list .md-ul > li { + list-style-type: circle; +} + +.md-list .md-list .md-ul > li { + list-style-type: square; +} + +.md-list .md-list .md-list .md-ul > li { + list-style-type: disc; +} + +// ADD SLIGHT MARGIN TO SPACE ELEMENTS EXCEPT THE FIRST + +.md-list > li:not(:first-child) { + margin-top: 0.15rem; +} + +.md-list .md-list > li:first-child { + margin-top: 0.15rem; +} + +/* HEADINGS */ + +.md-h1 { + font-size: 3rem; + font-weight: 300; + line-height: 1.167; + letter-spacing: -0.01562em; + + padding-bottom: 0.4rem; + border-bottom: 0.12rem solid rgb(53, 53, 53); +} + +.md-h2 { + font-size: 2.5rem; + font-weight: 300; + line-height: 1.2; + letter-spacing: -0.00833em; +} + +.md-h3 { + font-size: 1.4rem; + font-weight: 400; + line-height: 1.167; + letter-spacing: 0em; +} + +.md-h4 { + font-size: 1.38rem; +} + +.md-h5 { + font-size: 1.26rem; +} + +.md-h6 { + font-size: 1.2rem; +} + + +/* CODE */ + +.md-codespan { + background-color: #f2f4f7; + border-radius: 5px; + padding: 0.05rem 0.2rem; +} + +/* BLOCKQUOTE */ + +.md-blockquote { + box-sizing: border-box; + + position: relative; + padding-left: 1.2rem; + padding-top: 0.05rem; + padding-bottom: 0.05rem; + + &::before { + content: ""; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 3px; + background-color: grey; + } +} + +/* CODE */ + +.md-pre { + background-color: #f2f4f7; + border-radius: 5px; + padding: 12px; + overflow: scroll; +} + +/* MD LINE / SEP */ + +.md-hr { + font-size: 300; +} + +/* TABLES */ + +.md-table { + width: 100%; + border-collapse: collapse; + margin: 1rem 0; +} + +.md-thead { + background-color: #f2f4f7; + font-size: 1.10rem; + + .md-th { + padding: 0.5rem 0.75rem; + text-align: left; + border-bottom: 2px solid #545454; + } +} + + +.md-tbody { + .md-tr { + &:nth-child(even) { + background-color: #f8f8f8; + } + + &:nth-child(odd) { + background-color: #ffffff; + } + } + + .md-td { + padding: 0.5rem 0.75rem; + border-bottom: 1px solid #ddd; + } +} + +/* IMAGE */ + +.md-img { + max-width: 95%; + margin: 2em 2.5%; +} + +/* DEL */ + +.md-del { } + +.markdownContainer { + /* Strong */ + + strong { + font-weight: 600; + } + + /* Headings */ + + h1 { + font-size: 2.8rem; + font-weight: 300; + line-height: 1.167; + letter-spacing: -0.01562em; + margin-top: 1.0rem; + margin-bottom: 1rem; + + padding-bottom: 0.4rem; + border-bottom: 0.12rem solid rgb(53, 53, 53); + } + + h2 { + font-size: 2.3rem; + font-weight: 300; + line-height: 1.2; + letter-spacing: -0.00833em; + + margin-top: 1.6rem; + margin-bottom: 0.8rem; + } + + h3 { + font-size: 1.3rem; + font-weight: 400; + line-height: 1.167; + letter-spacing: 0em; + + margin-top: 1.3rem; + margin-bottom: 0.5rem; + } + + h4 { + font-size: 1.25rem; + } + + h5 { + font-size: 1.15rem; + } + + h6 { + font-size: 1.10rem; + } + + h4, h5, h6 { + margin-top: 0.8rem; + margin-bottom: 0.6rem; + } + + p, li { + font-size: 1rem; + letter-spacing: 0.00938em; + } + + p { + font-size: 1rem; + line-height: 1.5; + margin-bottom: 1em; + } + + code { + font-size: 1rem; + line-height: 1.5; + padding: 0.05rem 0.2rem; + } + + pre { + padding: 0.5rem 1.0rem; + margin: 0.5rem 0; + box-sizing: border-box; + } + pre > code { + padding: 0; + } + + code, pre { + background-color: #f2f4f7; + border-radius: 5px; + } + + pre { + overflow: auto; + box-sizing: border-box; + } + + @media screen and (max-width: 700px) { + pre { + padding-bottom: 0.7rem; + } + } + + /* LISTS */ + + // li { + // font-size: 1rem; + // letter-spacing: 0.00938em; + + // line-height: 1.4; + // margin-left: 1em; + + // list-style-image: none; + // list-style-position: inside; + // list-style-type: none; + + // box-sizing: border-box; + + // font-size: 1rem; + // } + + // ul, ol { + // li:not(:first-child) { + // margin-top: 0.15rem; + // } + // } + + // ul ol li, ol li { + // list-style-type: decimal; + // } + + // ul li { + // list-style-type: disc; + // } + + // ul, ol { + // ul li:first-child, ol li:first-child { + // margin-top: 0.15rem !important; + // } + + // ul li { + // list-style-type: circle; + // } + + // ul, ol { + // ul li { + // list-style-type: square; + // } + // } + // } + + // li { + // line-height: 1.15; + // margin-left: 1em; + // margin-bottom: 0.3em; + // list-style-image: none; + // list-style-position: outside; + // list-style-type: circle; + // } + + img { + max-width: 95%; + margin: 2em 2.5%; + } +} diff --git a/components/PathCrumbs/index.tsx b/components/PathCrumbs/index.tsx index 1c87344..41875ec 100644 --- a/components/PathCrumbs/index.tsx +++ b/components/PathCrumbs/index.tsx @@ -34,12 +34,13 @@ const urlPathComponentsToFullPath = (urlPathComponents : string[]): string[] => }; export type PathCrumbsProps = { - path: string + path: string; + style?: React.CSSProperties; }; import { BreadCrumbs , LinkCrumb } from '../../components/BreadCrumbs'; -const PathCrumbs: FC<PathCrumbsProps> = ({ path }) => { +const PathCrumbs: FC<PathCrumbsProps> = ({ path, style }) => { const pathComponents = urlPathComponents(path); const fullPaths = urlPathComponentsToFullPath(pathComponents); @@ -51,7 +52,7 @@ const PathCrumbs: FC<PathCrumbsProps> = ({ path }) => { )); return ( - <BreadCrumbs> + <BreadCrumbs style={style}> {linksComponents} </BreadCrumbs> ); diff --git a/components/Typography/index.tsx b/components/Typ/index.tsx index b9babc0..43d7673 100644 --- a/components/Typography/index.tsx +++ b/components/Typ/index.tsx @@ -6,7 +6,7 @@ import clsx from 'clsx'; type Variant = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'body'; type Align = 'inherit' | 'left' | 'center' | 'right'; -interface TypographyProps extends React.HTMLAttributes<HTMLElement> { +interface TypProps extends React.HTMLAttributes<HTMLElement> { variant?: Variant; align?: Align; gutter?: boolean; @@ -22,7 +22,7 @@ const variantTagMap: Record<Variant, keyof JSX.IntrinsicElements> = { body: 'p' }; -const Typography: React.FC<TypographyProps> = ({ +const Typ: React.FC<TypProps> = ({ variant = 'body', align = 'inherit', gutter = false, @@ -32,7 +32,7 @@ const Typography: React.FC<TypographyProps> = ({ const Tag = variantTagMap[variant] as keyof React.ReactHTML; const typographyClassName = clsx( - styles[`typo-${variant}`], + `md-${variantTagMap[variant]}`, { [`align-${align}`]: align !== 'inherit', [styles['typo-gutter']]: gutter @@ -43,5 +43,5 @@ const Typography: React.FC<TypographyProps> = ({ return <Tag className={typographyClassName} {...props} />; }; -export default Typography; +export default Typ; diff --git a/components/Typ/typo.module.scss b/components/Typ/typo.module.scss new file mode 100644 index 0000000..48a5b10 --- /dev/null +++ b/components/Typ/typo.module.scss @@ -0,0 +1,3 @@ +.typo-gutter { + margin-bottom: 0.35em; +} diff --git a/components/Typography/typo.module.scss b/components/Typography/typo.module.scss deleted file mode 100644 index 934333d..0000000 --- a/components/Typography/typo.module.scss +++ /dev/null @@ -1,64 +0,0 @@ -.typo-h1 { - font-size: 2.8rem; - font-weight: 300; - line-height: 1.167; - letter-spacing: -0.01562em; - // margin-top: 1.0rem; - // margin-bottom: 1rem; - - padding-bottom: 0.4rem; - border-bottom: 0.12rem solid rgb(53, 53, 53); -} - -.typo-h2 { - font-size: 2.3rem; - font-weight: 300; - line-height: 1.2; - letter-spacing: -0.00833em; - - // margin-top: 1.6rem; - // margin-bottom: 0.8rem; -} - -.typo-h3 { - font-size: 1.3rem; - font-weight: 400; - line-height: 1.167; - letter-spacing: 0em; - - // margin-top: 1.3rem; - // margin-bottom: 0.5rem; -} - -.typo-h4 { - font-size: 1.25rem; -} - -.typo-h5 { - font-size: 1.15rem; -} - -.typo-h6 { - font-size: 1.10rem; -} - -.typo-h4, .typo-h5, .typo-h6 { - // margin-top: 0.8rem; - // margin-bottom: 0.6rem; -} - -.typo-p { - font-size: 1rem; - letter-spacing: 0.00938em; - font-weight: 300; -} - -.typo-p { - font-size: 1rem; - line-height: 1.5; - // margin-bottom: 1em; -} - -.typo-gutter { - margin-bottom: 0.35em; -} diff --git a/components/ViewPort/index.tsx b/components/ViewPort/index.tsx index 29191a1..08b4c7e 100644 --- a/components/ViewPort/index.tsx +++ b/components/ViewPort/index.tsx @@ -1,24 +1,29 @@ import React, { FC } from "react" import styles from './index.module.scss'; +import { getSystemStyle, SystemProps } from '../utils/systemProps'; import clsx from 'clsx'; -export type Props = { - size?: "sm" | "md" | "lg"; - className?: string; - children?: React.ReactNode; +interface Props extends SystemProps { + size?: "sm" | "md" | "lg"; + className?: string; + children?: React.ReactNode; + style?: React.CSSProperties; }; -const Viewport : FC<Props> = ({children, className, size}) => { - const _size : string = size || "md"; - const sizeClass : string = styles['viewport-' + _size]; +const Viewport : FC<Props> = ({children, className, style, size, ...systemProps}) => { + style = getSystemStyle(systemProps, style); - return ( - <div - className={clsx(sizeClass, className)} - > - {children} - </div> - ) + const _size : string = size || "md"; + const sizeClass : string = styles['viewport-' + _size]; + + return ( + <div + className={clsx(sizeClass, className)} + style={style} + > + {children} + </div> + ) }; export default Viewport; diff --git a/loaders/marked-renderer.js b/loaders/marked-renderer.js new file mode 100644 index 0000000..0b55304 --- /dev/null +++ b/loaders/marked-renderer.js @@ -0,0 +1,92 @@ +const prefix = "md-"; +const selectall = `${prefix}dl`; + +const renderer = { + // Block-level methods + code(code, infostring, escaped) { + return `<pre class="${selectall} ${prefix}pre"><code class="${selectall} ${prefix}code">${code}</code></pre>`; + }, + blockquote(quote) { + return `<blockquote class="${selectall} ${prefix}blockquote">${quote}</blockquote>`; + }, + html(html, block) { + return block ? html : `<span class="${selectall} ${prefix}inline-html">${html}</span>`; + }, + heading(text, level, raw, slugger) { + return `<h${level} class="${selectall} ${prefix}h${level}">${text}</h${level}>`; + }, + hr() { + return `<hr class="${selectall} ${prefix}hr" />`; + }, + list(body, ordered, start) { + const tag = ordered ? 'ol' : 'ul'; + return `<${tag} class="${selectall} ${prefix}list ${prefix}${tag}"${ordered && start !== 1 ? ` start="${start}"` : ''}>${body}</${tag}>`; + }, + listitem(text, task, checked) { + let classList = `${prefix}li`; + + if(task) { + classList += ` ${prefix}li-checkbox`; + } else { + classList += ` ${prefix}li-nocheckbox`; + } + + return `<li class="${selectall} ${classList}">${text}</li>`; + }, + checkbox(checked) { + return `<input type="checkbox" class="${selectall} ${prefix}checkbox" ${checked ? 'checked' : ''} disabled />`; + }, + paragraph(text) { + return `<p class="${selectall} ${prefix}p">${text}</p>`; + }, + table(header, body) { + return `<table class="${selectall} ${prefix}table"><thead class="${selectall} ${prefix}thead">${header}</thead><tbody class="${selectall} ${prefix}tbody">${body}</tbody></table>`; + }, + tablerow(content) { + return `<tr class="${selectall} ${prefix}tr">${content}</tr>`; + }, + tablecell(content, flags) { + const type = flags.header ? 'th' : 'td'; + return `<${type} class="${selectall} ${prefix}${type}">${content}</${type}>`; + }, + + // Inline-level methods + strong(text) { + return `<strong class="${selectall} ${prefix}strong">${text}</strong>`; + }, + em(text) { + return `<em class="${selectall} ${prefix}em">${text}</em>`; + }, + codespan(code) { + return `<code class="${selectall} ${prefix}codespan">${code}</code>`; + }, + br() { + return `<br class="${selectall} ${prefix}br" />`; + }, + del(text) { + return `<del class="${selectall} ${prefix}del">${text}</del>`; + }, + link(href, title, text) { + return `<a href="${href}" class="${selectall} ${prefix}a"${title ? ` title="${title}"` : ''}>${text}</a>`; + }, + image(href, title, text) { + return `<img src="${href}" alt="${text}" class="${selectall} ${prefix}img"${title ? ` title="${title}"` : ''} />`; + }, + text(text) { + return text; // text-level elements typically don't have classes + }, +}; + +const hooks = { + postprocess(html) { + return `<div class="${selectall} ${prefix}wrapper" >${html}</div>`; + }, + preprocess(md) { + return md; + } +}; + +module.exports = { + renderer, + hooks +}; diff --git a/loaders/marked.js b/loaders/marked.js index f3c8fcb..a1ed8c3 100644 --- a/loaders/marked.js +++ b/loaders/marked.js @@ -1,15 +1,17 @@ const { Marked } = require('marked'); const { markedHighlight } = require('marked-highlight'); const hljs = require('highlight.js'); +const { renderer, hooks } = require('./marked-renderer.js'); module.exports = function loader(source) { const marker = new Marked( + { renderer, hooks }, markedHighlight({ highlight(code, lang) { const language = hljs.getLanguage(lang) ? lang : 'plaintext'; return hljs.highlight(code, { language }).value; } - }) + }), ); return marker.parse(source); diff --git a/pages/_app.tsx b/pages/_app.tsx index 7b7f22b..cfb045e 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -5,6 +5,7 @@ import '../styles/defaults.scss'; import type { AppProps } from 'next/app'; import Head from 'next/head'; import 'highlight.js/styles/github.css'; +import '../components/Markdown/markdown.scss'; function MyApp({ Component, pageProps }: AppProps) { return ( @@ -21,4 +22,4 @@ function MyApp({ Component, pageProps }: AppProps) { ); } -export default MyApp;
\ No newline at end of file +export default MyApp; diff --git a/pages/greeting.md b/pages/greeting.md index 45514a0..eb7a399 100644 --- a/pages/greeting.md +++ b/pages/greeting.md @@ -1,13 +1,21 @@ ## Hello, -You’ve happened upon my homepage. I’m a student, developer, and engi-nerd pursuing a degree in computer engineering at Texas A&M University. +You've happened upon my homepage. I'm a software developer, engi-nerd, and a recent graduate of computer engineering at Texas A&M University. +I've worked on a wide range of computational projects across a number of subject areas: robotics, bioinformatics, computer security, networking, +deep learning, and computer systems. Engineering projects define my life, and fill much of my waking attention. I've founded and led two robotics teams, +built a SLAM system for autonomous driving, worked as an undergraduate teaching assistant for a datastructures and algorithms course, built genome analysis +toolkits, and have written code in high-performance routers. Much of my code lives in production systems. I'm also passionate about open-source and often flit +around the internet contributing to open-source projects. Recently, I found and reported a buffer overrun in a Linux kernel driver and added zsh autocomplete +support to Python's `argcomplete` module. - [The Logs](/logs) -- [Public Git Projects](https://www.git.flu0r1ne.net) +- [Public Git Projects](https://www.git.al.exander.io) - My PGP keys + [Ascii Armored](/flu0r1ne.asc) + [Binary](/flu0r1ne.pub) +I've a privacy-enthusiast and go by my first name, Alex, or my legacy handle `flu0r1ne`. + Best, -\- Alex < flur01ne [at] flu0r1ne.net > +\- Alex < alex [at] al.exander.io > diff --git a/pages/index.tsx b/pages/index.tsx index 8201dbf..9390157 100644 --- a/pages/index.tsx +++ b/pages/index.tsx @@ -1,13 +1,54 @@ import MarkdownPage from '../templates/MarkdownPage'; + +import Typ from '../components/Typ'; +import ViewPort from '../components/ViewPort'; +import Link from '../components/Link'; +import Code from '../components/Code'; + // @ts-ignore import md from './greeting.md'; +import { List, ListItem } from '../components/List'; +import { DISPLAY_DOMAIN } from '../utils/env'; + + export default function Home() { + + const gitLink = 'https://git.' + DISPLAY_DOMAIN; + + let email : string; + + switch(DISPLAY_DOMAIN) { + case "flu0r1ne.net": + email = "flu0r1ne [at] flu0r1ne.net"; + break; + case "al.exander.io": + email = "alex [at] al.exander.io"; + break; + default: + throw Error("Display domain not recognized"); + } + return ( <> - <MarkdownPage - md={md} - /> + <ViewPort size='md' mt={3} > + <Typ variant="h2" gutter>Hello,</Typ> + <Typ>Welcome to my homepage. I'm a software developer, engi-nerd, and a recent graduate in Computer Engineering at Texas A&M University. I've worked on a wide range of computational projects across a number of subject areas: robotics, bioinformatics, computer security, networking, deep learning, and computer systems. Engineering projects define my life, and fill much of my waking attention. I've founded and led two robotics teams, built a SLAM system for autonomous driving, worked as an undergraduate teaching assistant for a Data Structures and Algorithms course, created genome analysis toolkits, and have contributed code to high-performance routers. I'm also passionate about open-source and often flit around the internet contributing to open-source projects. Recently, I found and reported a buffer overrun in an in-tree Linux kernel driver and added zsh auto complete support to the popular <Code>argcomplete</Code> module for Python.</Typ> + <List mt={1} mb={1} variant="unordered"> + <ListItem><Link href="/logs">The Logs</Link></ListItem> + <ListItem><Link href={gitLink}>Public Git Projects</Link></ListItem> + <ListItem> + My PGP keys + <List variant="unordered"> + <ListItem><Link href="/flur01ne.asc">Ascii Armored</Link></ListItem> + <ListItem><Link href="/flur01ne.pub">Binary</Link></ListItem> + </List> + </ListItem> + </List> + <Typ style={{ marginBottom: '0.5rem' }}>I'm a privacy enthusiast and go by my first name, Alex, or my legacy online handle, <Code>flu0r1ne</Code>.</Typ> + <Typ gutter>Best,</Typ> + <Typ>- Alex {"< " + email + " >"}</Typ> + </ViewPort> </> - ) + ); } diff --git a/pages/logs/index.tsx b/pages/logs/index.tsx index 358dff7..af227e9 100644 --- a/pages/logs/index.tsx +++ b/pages/logs/index.tsx @@ -5,6 +5,10 @@ import styles from './index.module.scss'; import { GetStaticProps, GetStaticPropsContext } from 'next'; import React, { FC } from 'react'; import { getPosts, Post } from '../../utils/Posts'; + +import Link from '../../components/Link'; +import { List, ListItem } from '../../components/List'; + // @ts-ignore import md from './logs.md'; @@ -13,7 +17,6 @@ interface Props { }; const Logs : FC<Props> = ({ posts }) => { - return( <DefaultPage @@ -21,13 +24,13 @@ const Logs : FC<Props> = ({ posts }) => { > <> <Markdown md={md} /> - <ul className={styles.logList}> + <List variant="unordered"> { posts.map(({ directory, meta }) => ( - <li key={directory}><a href={'/logs/' + directory}>{meta.name}</a></li> + <ListItem key={directory}><Link href={'/logs/' + directory}>{meta.name}</Link></ListItem> )) } - </ul> + </List> </> </DefaultPage> ); diff --git a/pages/logs/logs.md b/pages/logs/logs.md index c177646..c8bf543 100644 --- a/pages/logs/logs.md +++ b/pages/logs/logs.md @@ -1,4 +1,3 @@ ## The Logs -Eclectic thoughts, miscellany, and discursive drivel - +Eclectic thoughts and miscellany diff --git a/pages/wg2nd/index.tsx b/pages/wg2nd/index.tsx index 3f38a12..a189f6d 100644 --- a/pages/wg2nd/index.tsx +++ b/pages/wg2nd/index.tsx @@ -7,7 +7,7 @@ import TextArea from '../../components/TextArea'; import Input from '../../components/Input'; import Button from '../../components/Button'; import Markdown from '../../components/Markdown'; -import Typography from '../../components/Typography'; +import Typ from '../../components/Typ'; import PathCrumbs from "../../components/PathCrumbs"; @@ -142,10 +142,10 @@ const Wg2nd = () => { {/* Input Panel */} <Panel> - <Typography variant="h3">WireGuard Configuration</Typography> + <Typ variant="h3">WireGuard Configuration</Typ> <Box my={1}> <label htmlFor="wg_config_intf_name"> - <Typography variant="h4" gutter>Interface Name</Typography> + <Typ variant="h4" gutter>Interface Name</Typ> </label> <Input ref={intfNameRef} @@ -156,7 +156,7 @@ const Wg2nd = () => { </Box> <Box my={1}> <label htmlFor="wg_config_conf"> - <Typography variant="h4" gutter>Interface Configuration</Typography> + <Typ variant="h4" gutter>Interface Configuration</Typ> </label> <TextArea ref={intfConfigRef} @@ -179,7 +179,7 @@ const Wg2nd = () => { {/* Output Panel */} <Panel> <label htmlFor="nd_config_cmds"> - <Typography variant="h3">Networkd Configuration</Typography> + <Typ variant="h3">Networkd Configuration</Typ> </label> <Box my={1}> <div ref={parentDebounceDiv} > diff --git a/templates/Default/default.module.scss b/templates/Default/default.module.scss index 7dd99c5..79760a7 100644 --- a/templates/Default/default.module.scss +++ b/templates/Default/default.module.scss @@ -1,17 +1,21 @@ -.viewportOverrides { - margin-top: 4em; - margin-bottom: 3em; -} +// .date { +// white-space: nowrap; +// } -.date { - margin-top: 0.5em; - padding: 0.1em 0.2em; - display: block; -} +// .viewportOverrides { +// margin-top: 4em; +// margin-bottom: 3em; +// } -@media screen and (min-width: 1000px) { - .date { - float: right; - padding: 0.1em 0.2em; - } -}
\ No newline at end of file +// .date { +// margin-top: 0.5em; +// padding: 0.1em 0.2em; +// display: block; +// } + +// @media screen and (min-width: 1000px) { +// .date { +// float: right; +// padding: 0.1em 0.2em; +// } +// } diff --git a/templates/Default/index.tsx b/templates/Default/index.tsx index ccfde4a..1025703 100644 --- a/templates/Default/index.tsx +++ b/templates/Default/index.tsx @@ -3,6 +3,8 @@ import PathCrumbs from "../../components/PathCrumbs"; import Viewport from "../../components/ViewPort"; import styles from './default.module.scss'; import clsx from 'clsx'; +import Typ from '../../components/Typ'; +import Box from '../../components/Box'; export type DefaultPageProps = { className?: string; @@ -12,17 +14,26 @@ export type DefaultPageProps = { }; const LastUpdatedDate : FC<{ children: React.ReactNode }> = ({children}) => ( - <span className={styles.date}><b>Last Updated: </b>{children}</span> + <span style={{ whiteSpace: 'nowrap', padding: '4px 0px' }} >Last Updated: {children}</span> ) const DefaultPage : FC<DefaultPageProps> = ({className, lastUpdated, children, path, ...props}) => ( - <Viewport - className={clsx(styles.viewportOverrides, className)} + <Viewport + className={clsx(styles.viewportOverrides, className)} + my={3} + > + <Box + style={{ display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap' }} + el='header' + my={1} > - {path !== undefined ? <PathCrumbs path={path!} /> : undefined} - {lastUpdated ? <LastUpdatedDate>{lastUpdated}</LastUpdatedDate> : undefined} - {children} - </Viewport> + {path !== undefined ? <PathCrumbs style={{ padding: '4px 0px' }} path={path!} /> : undefined} + {lastUpdated ? <LastUpdatedDate>{lastUpdated}</LastUpdatedDate> : undefined} + </Box> + <main> + {children} + </main> + </Viewport> ); export default DefaultPage; diff --git a/templates/MarkdownPage/index.tsx b/templates/MarkdownPage/index.tsx index 22b531e..11ae9ce 100644 --- a/templates/MarkdownPage/index.tsx +++ b/templates/MarkdownPage/index.tsx @@ -17,4 +17,4 @@ const MarkdownPage : FC<Props> = ({path, md, ...props}) => ( </DefaultPage> ); -export default MarkdownPage;
\ No newline at end of file +export default MarkdownPage; diff --git a/utils/Posts.tsx b/utils/Posts.tsx index 4b252da..291ea41 100644 --- a/utils/Posts.tsx +++ b/utils/Posts.tsx @@ -5,10 +5,13 @@ import { Marked } from 'marked'; import { markedHighlight } from 'marked-highlight'; import markedOptions from './markedOptions'; +import { renderer, hooks } from '../loaders/marked-renderer.js'; + const hljs = require('highlight.js'); const marker = new Marked( - markedHighlight(markedOptions) + markedHighlight(markedOptions), + { renderer, hooks } ); interface PostMetadata { |