Skip to content

Commit

Permalink
Merge pull request nature-of-code#941 from nature-of-code/dev/misc-up…
Browse files Browse the repository at this point in the history
…date

Misc website updates
  • Loading branch information
shiffman authored Apr 24, 2024
2 parents 2f5e192 + e32bb47 commit 8634bd7
Show file tree
Hide file tree
Showing 14 changed files with 169 additions and 62 deletions.
9 changes: 8 additions & 1 deletion gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module.exports = {
siteMetadata: {
title: `Nature of Code`,
siteUrl: `https://natureofcode.com`,
description: ``,
description: `Simulating Natural Systems with JavaScript`,
},
plugins: [
{
Expand All @@ -12,6 +12,13 @@ module.exports = {
path: `${__dirname}/content/`,
},
},
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images/`,
},
},
`gatsby-plugin-image`,
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
Expand Down
47 changes: 45 additions & 2 deletions gatsby/lib/parse-content.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { unified } from 'unified';
import { h } from 'hastscript';
import { visit } from 'unist-util-visit';
import { remove } from 'unist-util-remove';
import rehypeParse from 'rehype-parse';
Expand All @@ -16,12 +17,26 @@ export function parseContent(html) {
if (
node.properties.className &&
Array.isArray(node.properties.className) &&
(node.properties.className.includes('pdf-only') ||
node.properties.className.includes('chapter-opening-figure'))
node.properties.className.includes('pdf-only')
) {
remove(tree, node);
}

if (
node.properties.className &&
Array.isArray(node.properties.className) &&
node.properties.className.includes('chapter-opening-figure')
) {
// Find the h3 element within the children of the node
node.children.forEach((child, index) => {
if (child.tagName === 'h3') {
// Replace the h3 tag with a span tag
node.children[index] = h('span', child.properties, child.children);
}
});
node.children.push(h('hr'));
}

if (
node.properties.dataType === 'embed' &&
node.properties.dataExamplePath
Expand All @@ -42,6 +57,19 @@ export function parseContent(html) {
}
});

/**
* using colon as separator instead of period
*
* e.g.
* 'Chapter 4. Particle Systems' => 'Chapter 4: Particle Systems'
*/
visit(tree, { tagName: 'h1' }, (node) => {
const originalTitle = node.children[0].value;
const modifiedTitle = originalTitle.replace(/(Chapter \d+)\./, '$1:');

node.children[0].value = modifiedTitle;
});

visit(tree, { tagName: 'span' }, (node) => {
if (
node.properties.className &&
Expand Down Expand Up @@ -108,6 +136,20 @@ export function parseContent(html) {
});
});

/**
* Generate a short description
*/
const paragraphs = [];
visit(ast, [{ tagName: 'p' }], (node, _, parent) => {
if (
parent.properties.dataType === 'chapter' ||
parent.properties.dataType === 'page'
) {
paragraphs.push(toString(node).replace(/\s+/g, ' ').trim());
}
});
const description = paragraphs.join(' ').trim().substring(0, 150);

const transformedAst = unified()
.use(replaceMedia)
.use(externalLinkInNewTab)
Expand All @@ -127,6 +169,7 @@ export function parseContent(html) {
return {
ast: transformedAst,
toc,
description,
examples,
};
}
8 changes: 7 additions & 1 deletion gatsby/on-create-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ module.exports = async ({

// load the html source to every HTML file node
const content = await loadNodeContent(node);
const { ast, toc, examples } = parseContent(content);
const { ast, toc, examples, description } = parseContent(content);

createNodeField({
node,
Expand All @@ -29,6 +29,12 @@ module.exports = async ({
value: JSON.stringify(toc),
});

createNodeField({
node,
name: 'description',
value: description,
});

for (let example of examples) {
const exampleNode = {
id: createNodeId(example.relativeDirectory),
Expand Down
24 changes: 13 additions & 11 deletions src/components/Head.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import { Helmet } from 'react-helmet';
import { useStaticQuery, graphql } from 'gatsby';
import { getSrc } from 'gatsby-plugin-image';

const Head = ({ title, description }) => {
const data = useStaticQuery(graphql`
Expand All @@ -12,6 +13,11 @@ const Head = ({ title, description }) => {
description
}
}
previewImage: file(relativePath: { eq: "cover.png" }) {
childImageSharp {
gatsbyImageData(width: 1200)
}
}
}
`);

Expand All @@ -25,6 +31,9 @@ const Head = ({ title, description }) => {
},
} = data;

const metaDescription = description || defaultDescription;
const previewImageSrc = getSrc(data.previewImage);

return (
<Helmet
htmlAttributes={{
Expand All @@ -33,26 +42,19 @@ const Head = ({ title, description }) => {
defaultTitle={defaultTitle}
titleTemplate={`%s / ${defaultTitle}`}
>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>{title}</title>
<meta name="description" content={description ?? defaultDescription} />
<meta name="description" content={metaDescription} />

<meta property="og:type" content="website" />
<meta property="og:url" content={siteUrl} />
<meta property="og:image" content={previewImageSrc} />
<meta property="og:title" content={title ?? defaultTitle} />
<meta
property="og:description"
content={description ?? defaultDescription}
/>
<meta property="og:description" content={metaDescription} />

<meta property="twitter:card" content="summary_large_image" />
<meta property="twitter:url" content={siteUrl} />
<meta property="twitter:title" content={title ?? defaultTitle} />
<meta
property="twitter:description"
content={description ?? defaultDescription}
/>
<meta property="twitter:description" content={metaDescription} />
</Helmet>
);
};
Expand Down
12 changes: 6 additions & 6 deletions src/components/Header.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ const MenuButton = (props) => {
title="Toggle menu"
>
<span
className="block h-0.5 w-full rounded bg-noc-400 transition-transform"
className="bg-noc-200 block h-0.5 w-full rounded transition-transform"
style={{
transform:
props.open && 'rotate(45deg) translateY(6.5px) translateX(6.5px)',
}}
></span>
<span
className="block h-0.5 w-full rounded bg-noc-400 transition-opacity"
className="bg-noc-200 block h-0.5 w-full rounded transition-opacity"
style={{
opacity: props.open ? '0' : '1',
}}
></span>
<span
className="block h-0.5 w-full rounded bg-noc-400 transition-transform"
className="bg-noc-200 block h-0.5 w-full rounded transition-transform"
style={{
transform:
props.open && 'rotate(-45deg) translateY(-6.5px) translateX(6.5px)',
Expand Down Expand Up @@ -61,7 +61,7 @@ const Header = (props) => {
href="https://www.patreon.com/codingtrain"
className="flex items-center gap-1.5 text-sm text-gray-500 hover:underline"
>
<FaRegHeart size="1.2em" className="text-noc-400" />
<FaRegHeart size="1.2em" className="text-noc-200" />
SUPPORT
</a>
</li>
Expand All @@ -70,7 +70,7 @@ const Header = (props) => {
href="https://github.com/nature-of-code/noc-book-2"
className="flex items-center gap-1.5 text-sm text-gray-500 hover:underline"
>
<FaGithub size="1.2em" className="text-noc-400" />
<FaGithub size="1.2em" className="text-noc-200" />
GITHUB
</a>
</li>
Expand All @@ -82,7 +82,7 @@ const Header = (props) => {
<img
src={CodingTrainIcon}
alt="Coding Train's logo"
className="w-8"
className="-ml-2 w-8"
></img>
CODING TRAIN
</a>
Expand Down
58 changes: 41 additions & 17 deletions src/components/SideNav.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,26 +54,50 @@ const SideNav = (props) => {
}
`);

const pages = data.allBookSection.edges
.filter(({ node }) => node.type === 'page')
.map(({ node }) => node);

const introductionPageIndex = pages.findIndex(
(node) => node.title === 'Introduction',
);

const chapters = data.allBookSection.edges
.filter(({ node }) => node.type === 'chapter')
.map(({ node }) => node);

return (
<nav className="rounded-3xl border border-noc-400">
<ul className="divide-y divide-noc-400">
{data.allBookSection.edges.map(({ node }) => {
<nav className="border-noc-200 rounded-3xl border">
<ul className="divide-noc-200 divide-y">
{pages.slice(0, introductionPageIndex + 1).map((node) => {
return (
<PageItem
key={node.slug}
slug={node.slug}
title={node.title}
type={node.type}
/>
);
})}

{chapters.map((node) => {
const [chapterNumber] = node.title.split('. ');

if (node.type === 'chapter' && chapterNumber === activeChapter) {
return (
<PageItem
key={node.slug}
slug={node.slug}
title={node.title}
type={node.type}
>
{node.type === 'chapter' && chapterNumber === activeChapter && (
<TableOfContents toc={JSON.parse(toc)} />
)}
</PageItem>
);
}
return (
<PageItem
key={node.slug}
slug={node.slug}
title={node.title}
type={node.type}
>
{node.type === 'chapter' && chapterNumber === activeChapter && (
<TableOfContents toc={JSON.parse(toc)} />
)}
</PageItem>
);
})}

{pages.slice(introductionPageIndex + 1).map((node) => {
return (
<PageItem
key={node.slug}
Expand Down
4 changes: 2 additions & 2 deletions src/layouts/BaseLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Header from '../components/Header';
import OverlayNav from '../components/OverlayNav';

export default function BaseLayout(props) {
const { title, children } = props;
const { title, description, children } = props;

const [menuOpen, setMenuOpen] = React.useState(false);

Expand All @@ -26,7 +26,7 @@ export default function BaseLayout(props) {

return (
<>
<Head title={title} />
<Head title={title} description={description} />

<Header menuOpen={menuOpen} onToggleMenu={() => setMenuOpen(!menuOpen)} />

Expand Down
5 changes: 3 additions & 2 deletions src/layouts/ChapterLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ const renderAst = ({ ast, images }) => {
export default function ChapterLayout({ data }) {
const { chapter, previous, next } = data;

const { htmlAst, toc } = chapter.src.fields;
const { htmlAst, toc, description } = chapter.src.fields;

return (
<SideNavLayout title={chapter.title} toc={toc}>
<SideNavLayout title={chapter.title} toc={toc} description={description}>
{renderAst({
ast: JSON.parse(htmlAst),
images: chapter.images,
Expand All @@ -63,6 +63,7 @@ export const query = graphql`
fields {
htmlAst
toc
description
}
}
images {
Expand Down
8 changes: 4 additions & 4 deletions src/layouts/SideNavLayout.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import BaseLayout from './BaseLayout';
import SideNav from '../components/SideNav';

export default function SideNavLayout(props) {
const { title, children, toc } = props;
const { title, toc, description, children } = props;

return (
<BaseLayout title={title}>
<div className="mx-auto max-w-6xl lg:flex lg:gap-10 xl:gap-14 lg:justify-between">
<BaseLayout title={title} description={description}>
<div className="mx-auto max-w-6xl lg:flex lg:justify-between lg:gap-10 xl:gap-14">
<aside className="sticky top-[6em] z-10 hidden max-h-[calc(100vh-6em)] min-w-[14em] overflow-y-auto pb-8 lg:block lg:flex-grow">
<SideNav activeChapter={title.split('. ')[0]} toc={toc} />
<SideNav activeChapter={title && title.split('. ')[0]} toc={toc} />
</aside>

<main className="prose mx-auto max-w-[50em] pb-8">{children}</main>
Expand Down
Loading

0 comments on commit 8634bd7

Please sign in to comment.