add prettier

This commit is contained in:
Nathan Wang 2020-06-20 01:08:44 -07:00
parent d25046542a
commit 952776c608
24 changed files with 1879 additions and 1333 deletions

View file

@ -2,3 +2,4 @@
package.json package.json
package-lock.json package-lock.json
public public
content

View file

@ -1,4 +1,9 @@
{ {
"arrowParens": "avoid", "endOfLine": "lf",
"semi": false "semi": true,
"singleQuote": true,
"tabWidth": 2,
"useTabs": true,
"trailingComma": "es5",
"arrowParens": "avoid"
} }

View file

@ -13,13 +13,13 @@ Located at `content/ordering.js`, this file stores the ordering of the modules.
### Frontmatter ### Frontmatter
[Frontmatter](https://jekyllrb.com/docs/front-matter/) is the stuff in the beginning of each module that's surrounded [Frontmatter](https://jekyllrb.com/docs/front-matter/) is the stuff in the beginning of each module that's surrounded
by three dashes. Frontmatter is written in [YAML](https://yaml.org/). It stores the "metadata" for each module. by three dashes. Frontmatter is written in [YAML](https://yaml.org/). It stores the "metadata" for each module.
YAML formatting is _extremely strict_. Be careful about spaces. YAML formatting is _extremely strict_. Be careful about spaces.
- **ID**: _Required_. The ID of the module. Ex: `getting-started`, or `containers`. This ID is used to identify - **ID**: _Required_. The ID of the module. Ex: `getting-started`, or `containers`. This ID is used to identify
the module, so make sure it is **unique** and **all lowercase with dashes only**. The URL will be generated based off this. the module, so make sure it is **unique** and **all lowercase with dashes only**. The URL will be generated based off this.
- **Title**: _Required_. The title of the module. Ex: `Getting Started` - **Title**: _Required_. The title of the module. Ex: `Getting Started`
- **Author**: _Required_. The author of the module. Ex: `Unknown` - **Author**: _Required_. The author of the module. Ex: `Unknown`
- **Prerequisites**: _Optional_. Any prerequisites for this module. - **Prerequisites**: _Optional_. Any prerequisites for this module.
@ -28,6 +28,7 @@ The prerequisite formatting is rather unintuitive. It expects an array of arrays
the name of the prerequisite, and the optional second item is a link. **Note the number of spaces!** the name of the prerequisite, and the optional second item is a link. **Note the number of spaces!**
Example: Example:
``` ```
prerequisites: prerequisites:
- -
@ -37,8 +38,8 @@ prerequisites:
- Another Prerequisite Without a Link - Another Prerequisite Without a Link
``` ```
- **Problems**: _Optional_. A list of problems in the article. As we haven't figured out what we're going to do with - **Problems**: _Optional_. A list of problems in the article. As we haven't figured out what we're going to do with
**it's best to not include this yet.** For USACO problems, enter each problem as `division_filename`. Ex: `bronze_promote`. **it's best to not include this yet.** For USACO problems, enter each problem as `division_filename`. Ex: `bronze_promote`.
### Module Description ### Module Description
@ -52,6 +53,7 @@ If you want a description that appears only on the homepage but not the article,
an HTML element with the class `syllabus-only`. Note that you can't use markdown in HTML elements. an HTML element with the class `syllabus-only`. Note that you can't use markdown in HTML elements.
Example: Example:
``` ```
<module-excerpt> <module-excerpt>
@ -149,4 +151,4 @@ problems:
</details> </details>
# Hello World! # Hello World!
``` ```

View file

@ -4,8 +4,8 @@
A collection of curated, high-quality resources to take you from Bronze to Platinum. A collection of curated, high-quality resources to take you from Bronze to Platinum.
All markdown files belong in `content/`. Other files are for the front-end dashboard interface. All markdown files belong in `content/`. Other files are for the front-end dashboard interface.
The content should not care about how the front-end interface is implemented. That way, we can easily The content should not care about how the front-end interface is implemented. That way, we can easily
change the front-end interface without having to rewrite the content. change the front-end interface without having to rewrite the content.
Refer to "Content Documentation.md" and "Syllabus.md" for more info. Refer to "Content Documentation.md" and "Syllabus.md" for more info.

View file

@ -1,58 +1,86 @@
import "./src/styles/main.css"; import './src/styles/main.css';
import React from "react"; import React from 'react';
import { MDXProvider } from "@mdx-js/react"; import { MDXProvider } from '@mdx-js/react';
const SpoilerComponent = ({ children, title }) => { const SpoilerComponent = ({ children, title }) => {
const [show, setShow] = React.useState(false); const [show, setShow] = React.useState(false);
return ( return (
<div className={`border border-gray-200 rounded-md`}> <div className={`border border-gray-200 rounded-md`}>
<p className="p-4 flex items-start" <p
onClick={e => setShow(!show)} style={{ marginBottom: 0 }}> className="p-4 flex items-start"
{show && <svg className="h-6 w-6 text-gray-500 mr-4" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>} onClick={e => setShow(!show)}
{!show && <svg className="h-6 w-6 text-gray-500 mr-4" fill="currentColor" viewBox="0 0 20 20"><path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg>} style={{ marginBottom: 0 }}
{title} >
</p> {show && (
<svg
className="h-6 w-6 text-gray-500 mr-4"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
clip-rule="evenodd"
></path>
</svg>
)}
{!show && (
<svg
className="h-6 w-6 text-gray-500 mr-4"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fill-rule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clip-rule="evenodd"
></path>
</svg>
)}
{title}
</p>
{show && <div className="p-4 pt-0 spoiler-body">{children}</div>} {show && <div className="p-4 pt-0 spoiler-body">{children}</div>}
</div> </div>
); );
}; };
const components = { const components = {
wrapper: ({ excerptOnly = false, children }) => { wrapper: ({ excerptOnly = false, children }) => {
if (excerptOnly) { if (excerptOnly) {
for (let child of children) { for (let child of children) {
if (child.props.originalType === "module-excerpt") return child; if (child.props.originalType === 'module-excerpt') return child;
} }
return null; return null;
} }
return children; return children;
}, },
"module-excerpt": (props) => <div {...props} />, 'module-excerpt': props => <div {...props} />,
spoiler: SpoilerComponent, spoiler: SpoilerComponent,
"info-block": ({ children }) => ( 'info-block': ({ children }) => (
<div className="rounded-md bg-blue-50 p-4 info-block mb-4"> <div className="rounded-md bg-blue-50 p-4 info-block mb-4">
<div className="flex"> <div className="flex">
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<svg className="h-5 w-5 text-blue-400" viewBox="0 0 20 20" fill="currentColor"> <svg
<path fillRule="evenodd" className="h-5 w-5 text-blue-400"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" viewBox="0 0 20 20"
clipRule="evenodd" /> fill="currentColor"
</svg> >
</div> <path
<div className="ml-3"> fillRule="evenodd"
{children} d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
</div> clipRule="evenodd"
</div> />
</div> </svg>
), </div>
<div className="ml-3">{children}</div>
</div>
</div>
),
}; };
export const wrapRootElement = ({ element }) => ( export const wrapRootElement = ({ element }) => (
<MDXProvider <MDXProvider components={components}>{element}</MDXProvider>
components={components}> );
{element}
</MDXProvider>
);

View file

@ -4,84 +4,82 @@ const tailwindConfig = require('./tailwind.config.js');
const fullConfig = resolveConfig(tailwindConfig); const fullConfig = resolveConfig(tailwindConfig);
module.exports = { module.exports = {
siteMetadata: { siteMetadata: {
title: `USACO Guide`, title: `USACO Guide`,
description: `A collection of curated, high-quality resources to take you from Bronze to Platinum.`, description: `A collection of curated, high-quality resources to take you from Bronze to Platinum.`,
author: `@usacoteam`, author: `@usacoteam`,
}, },
plugins: [ plugins: [
{ {
resolve: `gatsby-source-filesystem`, resolve: `gatsby-source-filesystem`,
options: { options: {
path: `${__dirname}/content`, path: `${__dirname}/content`,
name: `content`, name: `content`,
}, },
}, },
{ {
resolve: `gatsby-plugin-mdx`, resolve: `gatsby-plugin-mdx`,
options: { options: {
extensions: [`.mdx`, `.md`], extensions: [`.mdx`, `.md`],
gatsbyRemarkPlugins: [ gatsbyRemarkPlugins: [
`gatsby-remark-autolink-headers`, `gatsby-remark-autolink-headers`,
{ {
resolve: "gatsby-remark-custom-blocks", resolve: 'gatsby-remark-custom-blocks',
options: { options: {
blocks: { blocks: {
info: { info: {
containerElement: "info-block", containerElement: 'info-block',
title: "optional", title: 'optional',
}, },
}, },
}, },
}, },
{ {
resolve: `gatsby-remark-katex`, resolve: `gatsby-remark-katex`,
options: { options: {
// Add any KaTeX options from https://github.com/KaTeX/KaTeX/blob/master/docs/options.md here // Add any KaTeX options from https://github.com/KaTeX/KaTeX/blob/master/docs/options.md here
strict: `ignore` strict: `ignore`,
} },
}, },
{ {
resolve: `gatsby-remark-prismjs`, resolve: `gatsby-remark-prismjs`,
options: { options: {
noInlineHighlight: true, noInlineHighlight: true,
}, },
}, },
], ],
plugins: [ plugins: [`gatsby-remark-autolink-headers`],
`gatsby-remark-autolink-headers`, },
] },
}, {
}, resolve: `gatsby-plugin-postcss`,
{ options: {
resolve: `gatsby-plugin-postcss`, postCssPlugins: [
options: { require(`tailwindcss`)(tailwindConfig),
postCssPlugins: [ require(`autoprefixer`),
require(`tailwindcss`)(tailwindConfig), ...(process.env.NODE_ENV === `production`
require(`autoprefixer`), ? [require(`cssnano`)]
...(process.env.NODE_ENV === `production` : []),
? [require(`cssnano`)] ],
: []), },
], },
}, `gatsby-plugin-react-helmet`,
}, `gatsby-transformer-sharp`,
`gatsby-plugin-react-helmet`, `gatsby-plugin-sharp`,
`gatsby-transformer-sharp`, // {
`gatsby-plugin-sharp`, // resolve: `gatsby-plugin-manifest`,
// { // options: {
// resolve: `gatsby-plugin-manifest`, // name: `gatsby-starter-default`,
// options: { // short_name: `starter`,
// name: `gatsby-starter-default`, // start_url: `/`,
// short_name: `starter`, // background_color: `#663399`,
// start_url: `/`, // theme_color: `#663399`,
// background_color: `#663399`, // display: `minimal-ui`,
// theme_color: `#663399`, // // icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site.
// display: `minimal-ui`, // },
// // icon: `src/images/gatsby-icon.png`, // This path is relative to the root of the site. // },
// }, // this (optional) plugin enables Progressive Web App + Offline functionality
// }, // To learn more, visit: https://gatsby.dev/offline
// this (optional) plugin enables Progressive Web App + Offline functionality // `gatsby-plugin-offline`,
// To learn more, visit: https://gatsby.dev/offline ],
// `gatsby-plugin-offline`, };
],
}

View file

@ -1,51 +1,53 @@
import ModuleOrdering, { divisions } from "./content/ordering"; import ModuleOrdering, { divisions } from './content/ordering';
exports.createPages = async ({ actions, graphql, reporter }) => { exports.createPages = async ({ actions, graphql, reporter }) => {
const { createPage } = actions; const { createPage } = actions;
// Generate Module Pages // // Generate Module Pages //
const moduleTemplate = require.resolve(`./src/templates/moduleTemplate.tsx`); const moduleTemplate = require.resolve(`./src/templates/moduleTemplate.tsx`);
Object.keys(ModuleOrdering).forEach(division => { Object.keys(ModuleOrdering).forEach(division => {
const processItem = item => { const processItem = item => {
if (typeof item === "object") { if (typeof item === 'object') {
// this is a nested module // this is a nested module
item.items.forEach(x => processItem(x)); item.items.forEach(x => processItem(x));
} else { } else {
createPage({ createPage({
path: `/${division}/${item}`, path: `/${division}/${item}`,
component: moduleTemplate, component: moduleTemplate,
context: { context: {
// additional data can be passed via context // additional data can be passed via context
id: item, id: item,
division: division, division: division,
}, },
}); });
} }
}; };
ModuleOrdering[division].forEach(item => processItem(item)); ModuleOrdering[division].forEach(item => processItem(item));
}); });
// End Generate Module Pages // // End Generate Module Pages //
// Generate Syllabus Pages // // Generate Syllabus Pages //
const syllabusTemplate = require.resolve(`./src/templates/syllabusTemplate.js`); const syllabusTemplate = require.resolve(
divisions.forEach(division => { `./src/templates/syllabusTemplate.js`
createPage({ );
path: `/${division}`, divisions.forEach(division => {
component: syllabusTemplate, createPage({
context: { path: `/${division}`,
division: division component: syllabusTemplate,
}, context: {
}); division: division,
}); },
// End Generate Syllabus Pages // });
});
// End Generate Syllabus Pages //
}; };
exports.createSchemaCustomization = ({ actions }) => { exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions; const { createTypes } = actions;
const typeDefs = ` const typeDefs = `
type MarkdownRemarkFrontmatter implements Node { type MarkdownRemarkFrontmatter implements Node {
prerequisites: [[String]] prerequisites: [[String]]
} }
`; `;
createTypes(typeDefs) createTypes(typeDefs);
}; };

View file

@ -1,2 +1,2 @@
require = require('esm')(module); require = require('esm')(module);
module.exports = require('./gatsby-node.esm.js'); module.exports = require('./gatsby-node.esm.js');

View file

@ -36,7 +36,9 @@
"tailwindcss": "^1.4.6" "tailwindcss": "^1.4.6"
}, },
"devDependencies": { "devDependencies": {
"prettier": "2.0.5" "husky": "^4.2.5",
"lint-staged": "^10.2.11",
"prettier": "^2.0.5"
}, },
"keywords": [ "keywords": [
"gatsby" "gatsby"
@ -57,5 +59,13 @@
}, },
"bugs": { "bugs": {
"url": "https://github.com/gatsbyjs/gatsby/issues" "url": "https://github.com/gatsbyjs/gatsby/issues"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,jsx,json,md}": "prettier --write"
} }
} }

View file

@ -1,16 +1,16 @@
import React from "react"; import React from 'react';
import "../styles/markdown.css"; import '../styles/markdown.css';
import "katex/dist/katex.min.css"; import 'katex/dist/katex.min.css';
import "../styles/prism-theme.css"; import '../styles/prism-theme.css';
import { MDXRenderer } from "gatsby-plugin-mdx"; import { MDXRenderer } from 'gatsby-plugin-mdx';
const Markdown = ({ body, className, excerptOnly = false }) => { const Markdown = ({ body, className, excerptOnly = false }) => {
return ( return (
<div className={`markdown ${className}`}> <div className={`markdown ${className}`}>
<MDXRenderer excerptOnly={excerptOnly}>{body}</MDXRenderer> <MDXRenderer excerptOnly={excerptOnly}>{body}</MDXRenderer>
</div> </div>
); );
}; };
export default Markdown; export default Markdown;

View file

@ -1,71 +1,119 @@
import React from "react"; import React from 'react';
import { Link } from "gatsby"; import { Link } from 'gatsby';
const CompletedCheck = () => (<svg className="h-6 w-6 mr-2 text-green-500" fill="currentColor" viewBox="0 0 20 20"> const CompletedCheck = () => (
<path fillRule="evenodd" <svg
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" className="h-6 w-6 mr-2 text-green-500"
clipRule="evenodd" /> fill="currentColor"
</svg>); viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
);
const IncompleteCheck = () => (<svg className="h-6 w-6 mr-2 text-gray-200" fill="currentColor" viewBox="0 0 20 20"> const IncompleteCheck = () => (
<path fillRule="evenodd" <svg
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" className="h-6 w-6 mr-2 text-gray-200"
clipRule="evenodd" /> fill="currentColor"
</svg>); viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
);
const renderProblem = (problem, idx) => { const renderProblem = (problem, idx) => {
return ( return (
<li className="flex items-center" key={problem}> <li className="flex items-center" key={problem}>
{idx>0?<IncompleteCheck/>:<CompletedCheck/>} {idx > 0 ? <IncompleteCheck /> : <CompletedCheck />}
{/* todo make url legit */} {/* todo make url legit */}
<a className="text-blue-600" href="https://google.com/">{problem}</a> <a className="text-blue-600" href="https://google.com/">
</li> {problem}
); </a>
</li>
);
}; };
const renderPrerequisite = (prerequisite) => { const renderPrerequisite = prerequisite => {
const link = prerequisite.length > 1 ? prerequisite[1] : null; const link = prerequisite.length > 1 ? prerequisite[1] : null;
return ( return (
<li key={prerequisite[0]}> <li key={prerequisite[0]}>
{link && <a href={link} className="text-blue-600">{prerequisite[0]}</a>} {link && (
{!link && prerequisite[0]} <a href={link} className="text-blue-600">
</li> {prerequisite[0]}
); </a>
)}
{!link && prerequisite[0]}
</li>
);
}; };
const SyllabusModule = ({ title, children, author, problems, prerequisites, url }) => { const SyllabusModule = ({
// in the future, fetch this data either from localStorage or from server. title,
const isComplete = title === "Prerequisites" || title === "Getting Started"; children,
author,
problems,
prerequisites,
url,
}) => {
// in the future, fetch this data either from localStorage or from server.
const isComplete = title === 'Prerequisites' || title === 'Getting Started';
return ( return (
<div className="bg-white overflow-hidden shadow rounded-lg mb-8" id={url}> <div className="bg-white overflow-hidden shadow rounded-lg mb-8" id={url}>
<div className="border-b border-gray-200 px-4 py-4 sm:px-6 flex items-center"> <div className="border-b border-gray-200 px-4 py-4 sm:px-6 flex items-center">
<h2 className="font-bold text-xl mr-2"> <h2 className="font-bold text-xl mr-2">{title}</h2>
{title} {isComplete && (
</h2> <svg
{isComplete && className="h-8 w-8 text-green-500"
<svg className="h-8 w-8 text-green-500" fill="none" strokeLinecap="round" strokeLinejoin="round" fill="none"
strokeWidth={2} viewBox="0 0 24 24" stroke="currentColor"> strokeLinecap="round"
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" /> strokeLinejoin="round"
</svg>} strokeWidth={2}
</div> viewBox="0 0 24 24"
{prerequisites&& stroke="currentColor"
<div className="p-4 sm:p-6 border-b border-gray-200"> >
Prerequisites: <ul className="ml-8 list-disc">{prerequisites.map(renderPrerequisite)}</ul> <path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</div>} </svg>
<div className="px-4 py-4 sm:p-6"> )}
{children} </div>
{prerequisites && (
<div className="p-4 sm:p-6 border-b border-gray-200">
Prerequisites:{' '}
<ul className="ml-8 list-disc">
{prerequisites.map(renderPrerequisite)}
</ul>
</div>
)}
<div className="px-4 py-4 sm:p-6">
{children}
{problems&&(<>Problems:<ul className="ml-3 space-y-1 py-2">{problems.map(renderProblem)}</ul></>)} {problems && (
<>
Problems:
<ul className="ml-3 space-y-1 py-2">
{problems.map(renderProblem)}
</ul>
</>
)}
{author&&<p className="mt-2">Author: {author}</p>} {author && <p className="mt-2">Author: {author}</p>}
</div> </div>
<Link to={url || "/"} <Link
className="block border-t border-gray-200 px-4 py-4 sm:px-6 text-blue-600 font-bold uppercase text-sm hover:bg-gray-50 transition duration-150"> to={url || '/'}
View Module className="block border-t border-gray-200 px-4 py-4 sm:px-6 text-blue-600 font-bold uppercase text-sm hover:bg-gray-50 transition duration-150"
</Link> >
</div> View Module
); </Link>
</div>
);
}; };
export default SyllabusModule; export default SyllabusModule;

View file

@ -1,110 +1,110 @@
import { CSSTransition as ReactCSSTransition } from 'react-transition-group' import { CSSTransition as ReactCSSTransition } from 'react-transition-group';
import * as React from "react"; import * as React from 'react';
import { useRef, useEffect, useContext } from 'react' import { useRef, useEffect, useContext } from 'react';
const TransitionContext = React.createContext({ const TransitionContext = React.createContext({
parent: {}, parent: {},
}) });
function useIsInitialRender() { function useIsInitialRender() {
const isInitialRender = useRef(true) const isInitialRender = useRef(true);
useEffect(() => { useEffect(() => {
isInitialRender.current = false isInitialRender.current = false;
}, []) }, []);
return isInitialRender.current return isInitialRender.current;
} }
function CSSTransition({ function CSSTransition({
show, show,
enter = '', enter = '',
enterFrom = '', enterFrom = '',
enterTo = '', enterTo = '',
leave = '', leave = '',
leaveFrom = '', leaveFrom = '',
leaveTo = '', leaveTo = '',
appear, appear,
children, children,
}) { }) {
const enterClasses = enter.split(' ').filter((s) => s.length) const enterClasses = enter.split(' ').filter(s => s.length);
const enterFromClasses = enterFrom.split(' ').filter((s) => s.length) const enterFromClasses = enterFrom.split(' ').filter(s => s.length);
const enterToClasses = enterTo.split(' ').filter((s) => s.length) const enterToClasses = enterTo.split(' ').filter(s => s.length);
const leaveClasses = leave.split(' ').filter((s) => s.length) const leaveClasses = leave.split(' ').filter(s => s.length);
const leaveFromClasses = leaveFrom.split(' ').filter((s) => s.length) const leaveFromClasses = leaveFrom.split(' ').filter(s => s.length);
const leaveToClasses = leaveTo.split(' ').filter((s) => s.length) const leaveToClasses = leaveTo.split(' ').filter(s => s.length);
function addClasses(node, classes) { function addClasses(node, classes) {
classes.length && node.classList.add(...classes) classes.length && node.classList.add(...classes);
} }
function removeClasses(node, classes) { function removeClasses(node, classes) {
classes.length && node.classList.remove(...classes) classes.length && node.classList.remove(...classes);
} }
return ( return (
<ReactCSSTransition <ReactCSSTransition
appear={appear} appear={appear}
unmountOnExit unmountOnExit
in={show} in={show}
addEndListener={(node, done) => { addEndListener={(node, done) => {
node.addEventListener('transitionend', done, false) node.addEventListener('transitionend', done, false);
}} }}
onEnter={(node) => { onEnter={node => {
addClasses(node, [...enterClasses, ...enterFromClasses]) addClasses(node, [...enterClasses, ...enterFromClasses]);
}} }}
onEntering={(node) => { onEntering={node => {
removeClasses(node, enterFromClasses) removeClasses(node, enterFromClasses);
addClasses(node, enterToClasses) addClasses(node, enterToClasses);
}} }}
onEntered={(node) => { onEntered={node => {
removeClasses(node, [...enterToClasses, ...enterClasses]) removeClasses(node, [...enterToClasses, ...enterClasses]);
}} }}
onExit={(node) => { onExit={node => {
addClasses(node, [...leaveClasses, ...leaveFromClasses]) addClasses(node, [...leaveClasses, ...leaveFromClasses]);
}} }}
onExiting={(node) => { onExiting={node => {
removeClasses(node, leaveFromClasses) removeClasses(node, leaveFromClasses);
addClasses(node, leaveToClasses) addClasses(node, leaveToClasses);
}} }}
onExited={(node) => { onExited={node => {
removeClasses(node, [...leaveToClasses, ...leaveClasses]) removeClasses(node, [...leaveToClasses, ...leaveClasses]);
}} }}
> >
{children} {children}
</ReactCSSTransition> </ReactCSSTransition>
) );
} }
function Transition({ show, appear, ...rest }: any) { function Transition({ show, appear, ...rest }: any) {
const { parent }: { parent: any } = useContext(TransitionContext); const { parent }: { parent: any } = useContext(TransitionContext);
const isInitialRender = useIsInitialRender(); const isInitialRender = useIsInitialRender();
const isChild = show === undefined; const isChild = show === undefined;
if (isChild) { if (isChild) {
return ( return (
// @ts-ignore // @ts-ignore
<CSSTransition <CSSTransition
appear={parent.appear || !parent.isInitialRender} appear={parent.appear || !parent.isInitialRender}
show={parent.show} show={parent.show}
{...rest} {...rest}
/> />
) );
} }
return ( return (
<TransitionContext.Provider <TransitionContext.Provider
value={{ value={{
parent: { parent: {
show, show,
isInitialRender, isInitialRender,
appear, appear,
}, },
}} }}
> >
{/* {/*
// @ts-ignore*/} // @ts-ignore*/}
<CSSTransition appear={appear} show={show} {...rest} /> <CSSTransition appear={appear} show={show} {...rest} />
</TransitionContext.Provider> </TransitionContext.Provider>
) );
} }
export default Transition; export default Transition;

View file

@ -1,11 +1,7 @@
import * as React from "react" import * as React from 'react';
const Layout = ({ children }) => { const Layout = ({ children }) => {
return ( return <>{children}</>;
<>
{children}
</>
)
}; };
export default Layout; export default Layout;

View file

@ -5,84 +5,84 @@
* See: https://www.gatsbyjs.org/docs/use-static-query/ * See: https://www.gatsbyjs.org/docs/use-static-query/
*/ */
import React from "react" import React from 'react';
import PropTypes from "prop-types" import PropTypes from 'prop-types';
import { Helmet } from "react-helmet" import { Helmet } from 'react-helmet';
import { useStaticQuery, graphql } from "gatsby" import { useStaticQuery, graphql } from 'gatsby';
function SEO({ description, lang, meta, title }) { function SEO({ description, lang, meta, title }) {
const { site } = useStaticQuery( const { site } = useStaticQuery(
graphql` graphql`
query { query {
site { site {
siteMetadata { siteMetadata {
title title
description description
author author
} }
} }
} }
` `
) );
const metaDescription = description || site.siteMetadata.description const metaDescription = description || site.siteMetadata.description;
return ( return (
<Helmet <Helmet
htmlAttributes={{ htmlAttributes={{
lang, lang,
}} }}
title={title} title={title}
titleTemplate={`%s | ${site.siteMetadata.title}`} titleTemplate={`%s | ${site.siteMetadata.title}`}
meta={[ meta={[
{ {
name: `description`, name: `description`,
content: metaDescription, content: metaDescription,
}, },
{ {
property: `og:title`, property: `og:title`,
content: title, content: title,
}, },
{ {
property: `og:description`, property: `og:description`,
content: metaDescription, content: metaDescription,
}, },
{ {
property: `og:type`, property: `og:type`,
content: `website`, content: `website`,
}, },
{ {
name: `twitter:card`, name: `twitter:card`,
content: `summary`, content: `summary`,
}, },
{ {
name: `twitter:creator`, name: `twitter:creator`,
content: site.siteMetadata.author, content: site.siteMetadata.author,
}, },
{ {
name: `twitter:title`, name: `twitter:title`,
content: title, content: title,
}, },
{ {
name: `twitter:description`, name: `twitter:description`,
content: metaDescription, content: metaDescription,
}, },
].concat(meta)} ].concat(meta)}
/> />
) );
} }
SEO.defaultProps = { SEO.defaultProps = {
lang: `en`, lang: `en`,
meta: [], meta: [],
description: ``, description: ``,
} };
SEO.propTypes = { SEO.propTypes = {
description: PropTypes.string, description: PropTypes.string,
lang: PropTypes.string, lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object), meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired, title: PropTypes.string.isRequired,
} };
export default SEO export default SEO;

View file

@ -1,36 +1,36 @@
import React from "react" import React from 'react';
import PropTypes from "prop-types" import PropTypes from 'prop-types';
export default function HTML(props) { export default function HTML(props) {
return ( return (
<html {...props.htmlAttributes}> <html {...props.htmlAttributes}>
<head> <head>
<meta charSet="utf-8" /> <meta charSet="utf-8" />
<meta httpEquiv="x-ua-compatible" content="ie=edge" /> <meta httpEquiv="x-ua-compatible" content="ie=edge" />
<meta <meta
name="viewport" name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no" content="width=device-width, initial-scale=1, shrink-to-fit=no"
/> />
{props.headComponents} {props.headComponents}
</head> </head>
<body {...props.bodyAttributes}> <body {...props.bodyAttributes}>
{props.preBodyComponents} {props.preBodyComponents}
<div <div
key={`body`} key={`body`}
id="___gatsby" id="___gatsby"
dangerouslySetInnerHTML={{ __html: props.body }} dangerouslySetInnerHTML={{ __html: props.body }}
/> />
{props.postBodyComponents} {props.postBodyComponents}
</body> </body>
</html> </html>
) );
} }
HTML.propTypes = { HTML.propTypes = {
htmlAttributes: PropTypes.object, htmlAttributes: PropTypes.object,
headComponents: PropTypes.array, headComponents: PropTypes.array,
bodyAttributes: PropTypes.object, bodyAttributes: PropTypes.object,
preBodyComponents: PropTypes.array, preBodyComponents: PropTypes.array,
body: PropTypes.string, body: PropTypes.string,
postBodyComponents: PropTypes.array, postBodyComponents: PropTypes.array,
} };

View file

@ -1,286 +1,451 @@
import * as React from "react"; import * as React from 'react';
import {Link, PageProps} from "gatsby"; import { Link, PageProps } from 'gatsby';
import Layout from "../components/layout"; import Layout from '../components/layout';
import SEO from "../components/seo"; import SEO from '../components/seo';
export default function IndexPage(props: PageProps) { export default function IndexPage(props: PageProps) {
return ( return (
<Layout> <Layout>
<SEO title="" /> <SEO title="" />
{/* Begin Hero */} {/* Begin Hero */}
<div className="relative bg-white overflow-hidden"> <div className="relative bg-white overflow-hidden">
<div className="hidden lg:block lg:absolute lg:inset-0"> <div className="hidden lg:block lg:absolute lg:inset-0">
<svg className="absolute top-0 left-1/2 transform translate-x-64 -translate-y-8" width="640" height="784" <svg
fill="none" viewBox="0 0 640 784"> className="absolute top-0 left-1/2 transform translate-x-64 -translate-y-8"
<defs> width="640"
<pattern id="9ebea6f4-a1f5-4d96-8c4e-4c2abf658047" x="118" y="0" width="20" height="20" height="784"
patternUnits="userSpaceOnUse"> fill="none"
<rect x="0" y="0" width="4" height="4" className="text-gray-200" fill="currentColor" /> viewBox="0 0 640 784"
</pattern> >
</defs> <defs>
<rect y="72" width="640" height="640" className="text-gray-50" fill="currentColor" /> <pattern
<rect x="118" width="404" height="784" fill="url(#9ebea6f4-a1f5-4d96-8c4e-4c2abf658047)" /> id="9ebea6f4-a1f5-4d96-8c4e-4c2abf658047"
</svg> x="118"
</div> y="0"
width="20"
height="20"
patternUnits="userSpaceOnUse"
>
<rect
x="0"
y="0"
width="4"
height="4"
className="text-gray-200"
fill="currentColor"
/>
</pattern>
</defs>
<rect
y="72"
width="640"
height="640"
className="text-gray-50"
fill="currentColor"
/>
<rect
x="118"
width="404"
height="784"
fill="url(#9ebea6f4-a1f5-4d96-8c4e-4c2abf658047)"
/>
</svg>
</div>
<div className="relative pt-6 pb-16 md:pb-20 lg:pb-24 xl:pb-32 border-blue-600" style={{ borderTopWidth: "12px" }}> <div
<main className="mt-8 mx-auto max-w-6xl px-4 sm:mt-12 sm:px-6 md:mt-20 xl:mt-24"> className="relative pt-6 pb-16 md:pb-20 lg:pb-24 xl:pb-32 border-blue-600"
<div className="lg:grid lg:grid-cols-12 lg:gap-8"> style={{ borderTopWidth: '12px' }}
<div className="sm:text-center md:max-w-2xl md:mx-auto lg:col-span-6 lg:text-left lg:flex lg:flex-col lg:justify-center"> >
<div <main className="mt-8 mx-auto max-w-6xl px-4 sm:mt-12 sm:px-6 md:mt-20 xl:mt-24">
className="text-sm font-semibold uppercase tracking-wide text-gray-500 sm:text-base lg:text-sm xl:text-base"> <div className="lg:grid lg:grid-cols-12 lg:gap-8">
Pre-Release <div className="sm:text-center md:max-w-2xl md:mx-auto lg:col-span-6 lg:text-left lg:flex lg:flex-col lg:justify-center">
</div> <div className="text-sm font-semibold uppercase tracking-wide text-gray-500 sm:text-base lg:text-sm xl:text-base">
<h2 Pre-Release
className="mt-1 text-4xl tracking-tight leading-10 font-extrabold text-gray-900 sm:leading-none sm:text-6xl lg:text-5xl xl:text-6xl"> </div>
USACO <span className="text-blue-600">Guide</span> <h2 className="mt-1 text-4xl tracking-tight leading-10 font-extrabold text-gray-900 sm:leading-none sm:text-6xl lg:text-5xl xl:text-6xl">
</h2> USACO <span className="text-blue-600">Guide</span>
<p className="mt-3 text-base text-gray-500 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl"> </h2>
A free collection of <b>curated, high-quality resources</b> to take you from Bronze to Platinum and beyond. <p className="mt-3 text-base text-gray-500 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
</p> A free collection of <b>curated, high-quality resources</b> to
<div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start"> take you from Bronze to Platinum and beyond.
<div className="rounded-md shadow"> </p>
<Link to="/intro" <div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start">
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"> <div className="rounded-md shadow">
View Guide <Link
</Link> to="/intro"
</div> className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
<div className="mt-3 sm:mt-0 sm:ml-3"> >
<a href="#learn-more" View Guide
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-blue-700 bg-blue-100 hover:text-blue-600 hover:bg-blue-50 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"> </Link>
Learn More </div>
</a> <div className="mt-3 sm:mt-0 sm:ml-3">
</div> <a
</div> href="#learn-more"
</div> className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-blue-700 bg-blue-100 hover:text-blue-600 hover:bg-blue-50 focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
<div >
className="mt-12 relative sm:max-w-lg sm:mx-auto lg:mt-0 lg:max-w-none lg:mx-0 lg:col-span-6 lg:flex lg:items-center"> Learn More
<svg </a>
className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-8 scale-75 origin-top sm:scale-100 lg:hidden" </div>
width="640" height="784" fill="none" viewBox="0 0 640 784"> </div>
<defs> </div>
<pattern id="4f4f415c-a0e9-44c2-9601-6ded5a34a13e" x="118" y="0" width="20" height="20" <div className="mt-12 relative sm:max-w-lg sm:mx-auto lg:mt-0 lg:max-w-none lg:mx-0 lg:col-span-6 lg:flex lg:items-center">
patternUnits="userSpaceOnUse"> <svg
<rect x="0" y="0" width="4" height="4" className="text-gray-200" fill="currentColor" /> className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-8 scale-75 origin-top sm:scale-100 lg:hidden"
</pattern> width="640"
</defs> height="784"
<rect y="72" width="640" height="640" className="text-gray-50" fill="currentColor" /> fill="none"
<rect x="118" width="404" height="784" fill="url(#4f4f415c-a0e9-44c2-9601-6ded5a34a13e)" /> viewBox="0 0 640 784"
</svg> >
<div className="relative mx-auto xl:mr-0 w-full rounded-lg shadow-lg lg:max-w-md"> <defs>
<a href="https://www.youtube.com/watch?v=ueNT-w7Oluw" <pattern
target="_blank" id="4f4f415c-a0e9-44c2-9601-6ded5a34a13e"
className="relative block w-full rounded-lg overflow-hidden focus:outline-none focus:shadow-outline"> x="118"
<img className="w-full" y="0"
src="https://img.youtube.com/vi/ueNT-w7Oluw/maxresdefault.jpg" width="20"
alt="Woman making a sale" /> height="20"
<div className="absolute inset-0 w-full h-full flex items-center justify-center"> patternUnits="userSpaceOnUse"
<svg className="h-20 w-20 text-blue-500" fill="currentColor" viewBox="0 0 84 84"> >
<circle opacity="0.9" cx="42" cy="42" r="42" fill="white" /> <rect
<path x="0"
d="M55.5039 40.3359L37.1094 28.0729C35.7803 27.1869 34 28.1396 34 29.737V54.263C34 55.8604 35.7803 56.8131 37.1094 55.9271L55.5038 43.6641C56.6913 42.8725 56.6913 41.1275 55.5039 40.3359Z" /> y="0"
</svg> width="4"
</div> height="4"
</a> className="text-gray-200"
</div> fill="currentColor"
</div> />
</div> </pattern>
</main> </defs>
</div> <rect
</div> y="72"
{/* End Hero */} width="640"
height="640"
className="text-gray-50"
fill="currentColor"
/>
<rect
x="118"
width="404"
height="784"
fill="url(#4f4f415c-a0e9-44c2-9601-6ded5a34a13e)"
/>
</svg>
<div className="relative mx-auto xl:mr-0 w-full rounded-lg shadow-lg lg:max-w-md">
<a
href="https://www.youtube.com/watch?v=ueNT-w7Oluw"
target="_blank"
className="relative block w-full rounded-lg overflow-hidden focus:outline-none focus:shadow-outline"
>
<img
className="w-full"
src="https://img.youtube.com/vi/ueNT-w7Oluw/maxresdefault.jpg"
alt="Woman making a sale"
/>
<div className="absolute inset-0 w-full h-full flex items-center justify-center">
<svg
className="h-20 w-20 text-blue-500"
fill="currentColor"
viewBox="0 0 84 84"
>
<circle
opacity="0.9"
cx="42"
cy="42"
r="42"
fill="white"
/>
<path d="M55.5039 40.3359L37.1094 28.0729C35.7803 27.1869 34 28.1396 34 29.737V54.263C34 55.8604 35.7803 56.8131 37.1094 55.9271L55.5038 43.6641C56.6913 42.8725 56.6913 41.1275 55.5039 40.3359Z" />
</svg>
</div>
</a>
</div>
</div>
</div>
</main>
</div>
</div>
{/* End Hero */}
<div className="py-12 bg-white" id="learn-more"> <div className="py-12 bg-white" id="learn-more">
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8"> <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="lg:text-center"> <div className="lg:text-center">
<p className="text-base leading-6 text-blue-600 font-semibold tracking-wide uppercase">About This Guide</p> <p className="text-base leading-6 text-blue-600 font-semibold tracking-wide uppercase">
<h3 About This Guide
className="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10"> </p>
Not Just Another Resource. <h3 className="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10">
</h3> Not Just Another Resource.
<p className="mt-4 max-w-4xl text-xl leading-7 text-gray-500 lg:mx-auto"> </h3>
This is more than "just another resource." This is the first-ever comprehensive, organized roadmap carefully designed and crafted for USACO contestants available to everyone, for free. <p className="mt-4 max-w-4xl text-xl leading-7 text-gray-500 lg:mx-auto">
</p> This is more than "just another resource." This is the first-ever
comprehensive, organized roadmap carefully designed and crafted
for USACO contestants available to everyone, for free.
</p>
<div className="max-w-3xl mx-auto bg-yellow-50 rounded-md border-yellow-400 border p-4 mt-8"> <div className="max-w-3xl mx-auto bg-yellow-50 rounded-md border-yellow-400 border p-4 mt-8">
<div className="flex"> <div className="flex">
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<svg className="h-5 w-5 text-yellow-400" viewBox="0 0 20 20" fill="currentColor"> <svg
<path fillRule="evenodd" d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z" clipRule="evenodd"/> className="h-5 w-5 text-yellow-400"
</svg> viewBox="0 0 20 20"
</div> fill="currentColor"
<div className="ml-3 flex-1 md:flex md:justify-between"> >
<p className="text-sm leading-5 text-yellow-700 text-left"> <path
This guide is not a syllabus. Topics on this guide reflect <i>past</i> problems, not future problems. fillRule="evenodd"
</p> d="M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z"
<p className="mt-3 text-sm leading-5 md:mt-0 md:ml-6"> clipRule="evenodd"
<a href="#" />
className="whitespace-no-wrap font-medium text-yellow-700 hover:text-yellow-600 transition ease-in-out duration-150"> </svg>
Learn More &rarr; </div>
</a> <div className="ml-3 flex-1 md:flex md:justify-between">
</p> <p className="text-sm leading-5 text-yellow-700 text-left">
</div> This guide is not a syllabus. Topics on this guide reflect{' '}
</div> <i>past</i> problems, not future problems.
</div> </p>
</div> <p className="mt-3 text-sm leading-5 md:mt-0 md:ml-6">
<a
href="#"
className="whitespace-no-wrap font-medium text-yellow-700 hover:text-yellow-600 transition ease-in-out duration-150"
>
Learn More &rarr;
</a>
</p>
</div>
</div>
</div>
</div>
<div className="mt-16"> <div className="mt-16">
<ul className="md:grid md:grid-cols-2 md:col-gap-8 md:row-gap-10"> <ul className="md:grid md:grid-cols-2 md:col-gap-8 md:row-gap-10">
<li> <li>
<div className="flex"> <div className="flex">
<div className="flex-shrink-0"> <div className="flex-shrink-0">
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white"> <div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white">
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <svg
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" className="h-6 w-6"
d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9" /> fill="none"
</svg> viewBox="0 0 24 24"
</div> stroke="currentColor"
</div> >
<div className="ml-4"> <path
<h4 className="text-lg leading-6 font-medium text-gray-900">Experienced Authors</h4> strokeLinecap="round"
<p className="mt-2 text-base leading-6 text-gray-500"> strokeLinejoin="round"
This guide is written by top USACO contestants, including two-time IOI winner and USACO Problemsetter <a href="https://github.com/bqi343" className="underline text-blue-500">Benjamin Qi</a>. strokeWidth="2"
</p> d="M21 12a9 9 0 01-9 9m9-9a9 9 0 00-9-9m9 9H3m9 9a9 9 0 01-9-9m9 9c1.657 0 3-4.03 3-9s-1.343-9-3-9m0 18c-1.657 0-3-4.03-3-9s1.343-9 3-9m-9 9a9 9 0 019-9"
</div> />
</div> </svg>
</li> </div>
<li className="mt-10 md:mt-0"> </div>
<div className="flex"> <div className="ml-4">
<div className="flex-shrink-0"> <h4 className="text-lg leading-6 font-medium text-gray-900">
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white"> Experienced Authors
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> </h4>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" <p className="mt-2 text-base leading-6 text-gray-500">
d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3" /> This guide is written by top USACO contestants, including
</svg> two-time IOI winner and USACO Problemsetter{' '}
</div> <a
</div> href="https://github.com/bqi343"
<div className="ml-4"> className="underline text-blue-500"
<h4 className="text-lg leading-6 font-medium text-gray-900">Calibrated Difficulty</h4> >
<p className="mt-2 text-base leading-6 text-gray-500"> Benjamin Qi
This guide is targeted towards all contestants, regardless of their division. You'll find problems suitable for you. </a>
</p> .
</div> </p>
</div> </div>
</li> </div>
<li className="mt-10 md:mt-0"> </li>
<div className="flex"> <li className="mt-10 md:mt-0">
<div className="flex-shrink-0"> <div className="flex">
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white"> <div className="flex-shrink-0">
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" <svg
d="M13 10V3L4 14h7v7l9-11h-7z" /> className="h-6 w-6"
</svg> fill="none"
</div> viewBox="0 0 24 24"
</div> stroke="currentColor"
<div className="ml-4"> >
<h4 className="text-lg leading-6 font-medium text-gray-900">Improve Faster</h4> <path
<p className="mt-2 text-base leading-6 text-gray-500"> strokeLinecap="round"
Stop wasting time learning topics you already know. Skip over easy topics or delve deeper into difficult ones; the choice is yours. strokeLinejoin="round"
</p> strokeWidth="2"
</div> d="M3 6l3 1m0 0l-3 9a5.002 5.002 0 006.001 0M6 7l3 9M6 7l6-2m6 2l3-1m-3 1l-3 9a5.002 5.002 0 006.001 0M18 7l3 9m-3-9l-6-2m0-2v2m0 16V5m0 16H9m3 0h3"
</div> />
</li> </svg>
<li className="mt-10 md:mt-0"> </div>
<div className="flex"> </div>
<div className="flex-shrink-0"> <div className="ml-4">
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white"> <h4 className="text-lg leading-6 font-medium text-gray-900">
<svg className="h-6 w-6" fill="none" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" viewBox="0 0 24 24" stroke="currentColor"> Calibrated Difficulty
<path d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z"/> </h4>
</svg> <p className="mt-2 text-base leading-6 text-gray-500">
</div> This guide is targeted towards all contestants, regardless
</div> of their division. You'll find problems suitable for you.
<div className="ml-4"> </p>
<h4 className="text-lg leading-6 font-medium text-gray-900">Officially Recognized</h4> </div>
<p className="mt-2 text-base leading-6 text-gray-500"> </div>
This guide is developed in collaboration with USACO Staff and USACO Director Dr. Brian Dean. </li>
</p> <li className="mt-10 md:mt-0">
</div> <div className="flex">
</div> <div className="flex-shrink-0">
</li> <div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white">
</ul> <svg
</div> className="h-6 w-6"
</div> fill="none"
</div> viewBox="0 0 24 24"
stroke="currentColor"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
d="M13 10V3L4 14h7v7l9-11h-7z"
/>
</svg>
</div>
</div>
<div className="ml-4">
<h4 className="text-lg leading-6 font-medium text-gray-900">
Improve Faster
</h4>
<p className="mt-2 text-base leading-6 text-gray-500">
Stop wasting time learning topics you already know. Skip
over easy topics or delve deeper into difficult ones; the
choice is yours.
</p>
</div>
</div>
</li>
<li className="mt-10 md:mt-0">
<div className="flex">
<div className="flex-shrink-0">
<div className="flex items-center justify-center h-12 w-12 rounded-md bg-blue-500 text-white">
<svg
className="h-6 w-6"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" />
</svg>
</div>
</div>
<div className="ml-4">
<h4 className="text-lg leading-6 font-medium text-gray-900">
Officially Recognized
</h4>
<p className="mt-2 text-base leading-6 text-gray-500">
This guide is developed in collaboration with USACO Staff
and USACO Director Dr. Brian Dean.
</p>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
<div className="bg-blue-900"> <div className="bg-blue-900">
<div className="max-w-6xl mx-auto px-4 sm:px-6 py-20 text-center"> <div className="max-w-6xl mx-auto px-4 sm:px-6 py-20 text-center">
<p className="text-xl md:text-2xl font-bold text-blue-200"> <p className="text-xl md:text-2xl font-bold text-blue-200">
Unsure how to get started?<br/> Unsure how to get started?
Overwhelmed by too many resources?<br/> <br />
Looking to take your CP skills to the next level?<br/> Overwhelmed by too many resources?
</p> <br />
Looking to take your CP skills to the next level?
<br />
</p>
<p className="text-3xl sm:text-4xl md:text-6xl font-extrabold text-white mt-8">This is the guide for you.</p> <p className="text-3xl sm:text-4xl md:text-6xl font-extrabold text-white mt-8">
This is the guide for you.
</p>
<div className="mt-8 flex justify-center"> <div className="mt-8 flex justify-center">
<div className="rounded-md shadow"> <div className="rounded-md shadow">
<Link to="/intro" <Link
className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"> to="/intro"
View Guide className="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-blue-600 hover:bg-blue-500 focus:outline-none focus:border-blue-700 focus:shadow-outline-blue transition duration-150 ease-in-out md:py-4 md:text-lg md:px-10"
</Link> >
</div> View Guide
</div> </Link>
</div> </div>
</div> </div>
</div>
</div>
{/* Begin FAQ */} {/* Begin FAQ */}
<div className="bg-white"> <div className="bg-white">
<div className="max-w-screen-xl mx-auto pt-12 pb-16 sm:pt-16 sm:pb-20 px-4 sm:px-6 lg:pt-20 lg:pb-28 lg:px-8"> <div className="max-w-screen-xl mx-auto pt-12 pb-16 sm:pt-16 sm:pb-20 px-4 sm:px-6 lg:pt-20 lg:pb-28 lg:px-8">
<h2 className="text-3xl leading-9 font-extrabold text-gray-900"> <h2 className="text-3xl leading-9 font-extrabold text-gray-900">
Frequently asked questions Frequently asked questions
</h2> </h2>
<div className="mt-6 border-t-2 border-gray-100 pt-10"> <div className="mt-6 border-t-2 border-gray-100 pt-10">
<dl className="md:grid md:grid-cols-2 md:gap-8"> <dl className="md:grid md:grid-cols-2 md:gap-8">
<div> <div>
<div> <div>
<dt className="text-lg leading-6 font-medium text-gray-900"> <dt className="text-lg leading-6 font-medium text-gray-900">
Is this a Syllabus? Is this a Syllabus?
</dt> </dt>
<dd className="mt-2"> <dd className="mt-2">
<p className="text-base leading-6 text-gray-500"> <p className="text-base leading-6 text-gray-500">
<b>No. This guide is NOT a syllabus.</b> USACO does not have an official syllabus. This guide merely lists topics that have <i>historically</i> appeared in USACO contests; it makes no guarantees about the topics in future USACO contests. <b>No. This guide is NOT a syllabus.</b> USACO does not
</p> have an official syllabus. This guide merely lists topics
</dd> that have <i>historically</i> appeared in USACO contests;
</div> it makes no guarantees about the topics in future USACO
<div className="mt-12"> contests.
<dt className="text-lg leading-6 font-medium text-gray-900"> </p>
How can I contribute/report a problem? </dd>
</dt> </div>
<dd className="mt-2"> <div className="mt-12">
<p className="text-base leading-6 text-gray-500"> <dt className="text-lg leading-6 font-medium text-gray-900">
If you would like to contribute towards this guide or report an issue, please contact Nathan Wang at <a className="text-blue-600 underline" href="mailto:nathan.r.wang@gmail.com">nathan.r.wang@gmail.com</a>. How can I contribute/report a problem?
</p> </dt>
</dd> <dd className="mt-2">
</div> <p className="text-base leading-6 text-gray-500">
</div> If you would like to contribute towards this guide or
<div className="mt-12 md:mt-0"> report an issue, please contact Nathan Wang at{' '}
<div> <a
<dt className="text-lg leading-6 font-medium text-gray-900"> className="text-blue-600 underline"
Is this guide for Platinum contestants? href="mailto:nathan.r.wang@gmail.com"
</dt> >
<dd className="mt-2"> nathan.r.wang@gmail.com
<p className="text-base leading-6 text-gray-500"> </a>
While we offer some resources that platinum contestants may find useful, the platinum division has too many topics for us to effectively cover. For platinum contestants, we recommend you treat this as more of a <i>resource</i> than a <i>guide</i>. .
</p> </p>
</dd> </dd>
</div> </div>
<div className="mt-12"> </div>
<dt className="text-lg leading-6 font-medium text-gray-900"> <div className="mt-12 md:mt-0">
How can I get help? <div>
</dt> <dt className="text-lg leading-6 font-medium text-gray-900">
<dd className="mt-2"> Is this guide for Platinum contestants?
<p className="text-base leading-6 text-gray-500"> </dt>
uh..... <dd className="mt-2">
</p> <p className="text-base leading-6 text-gray-500">
</dd> While we offer some resources that platinum contestants
</div> may find useful, the platinum division has too many topics
</div> for us to effectively cover. For platinum contestants, we
</dl> recommend you treat this as more of a <i>resource</i> than
</div> a <i>guide</i>.
</div> </p>
</div> </dd>
{/*End FAQ*/} </div>
</Layout> <div className="mt-12">
) <dt className="text-lg leading-6 font-medium text-gray-900">
} How can I get help?
</dt>
<dd className="mt-2">
<p className="text-base leading-6 text-gray-500">uh.....</p>
</dd>
</div>
</div>
</dl>
</div>
</div>
</div>
{/*End FAQ*/}
</Layout>
);
}

View file

@ -2,4 +2,4 @@
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
/*! purgecss end ignore */ /*! purgecss end ignore */
@tailwind utilities; @tailwind utilities;

View file

@ -1,155 +1,155 @@
/*! purgecss start ignore */ /*! purgecss start ignore */
/* Additional vertical padding used by kbd tag. */ /* Additional vertical padding used by kbd tag. */
.py-05 { .py-05 {
padding-top: 0.125rem; padding-top: 0.125rem;
padding-bottom: 0.125rem; padding-bottom: 0.125rem;
} }
.markdown { .markdown {
@apply text-gray-900 leading-normal break-words; @apply text-gray-900 leading-normal break-words;
} }
.markdown > * + * { .markdown > * + * {
@apply mt-0 mb-4; @apply mt-0 mb-4;
} }
.markdown li + li { .markdown li + li {
@apply mt-1; @apply mt-1;
} }
.markdown li > p + p { .markdown li > p + p {
@apply mt-6; @apply mt-6;
} }
.markdown strong { .markdown strong {
@apply font-semibold; @apply font-semibold;
} }
.markdown a { .markdown a {
@apply text-blue-600 font-semibold; @apply text-blue-600 font-semibold;
} }
.markdown strong a { .markdown strong a {
@apply font-bold; @apply font-bold;
} }
.markdown h1 { .markdown h1 {
@apply leading-tight border-b text-4xl font-semibold mb-4 mt-6 pb-2; @apply leading-tight border-b text-4xl font-semibold mb-4 mt-6 pb-2;
} }
.markdown h2 { .markdown h2 {
@apply leading-tight border-b text-2xl font-semibold mb-4 mt-6 pb-2; @apply leading-tight border-b text-2xl font-semibold mb-4 mt-6 pb-2;
} }
.markdown h3 { .markdown h3 {
@apply leading-snug text-lg font-semibold mb-4 mt-6; @apply leading-snug text-lg font-semibold mb-4 mt-6;
} }
.markdown h4 { .markdown h4 {
@apply leading-none text-base font-semibold mb-4 mt-6; @apply leading-none text-base font-semibold mb-4 mt-6;
} }
.markdown h5 { .markdown h5 {
@apply leading-tight text-sm font-semibold mb-4 mt-6; @apply leading-tight text-sm font-semibold mb-4 mt-6;
} }
.markdown h6 { .markdown h6 {
@apply leading-tight text-sm font-semibold text-gray-600 mb-4 mt-6; @apply leading-tight text-sm font-semibold text-gray-600 mb-4 mt-6;
} }
.markdown blockquote { .markdown blockquote {
@apply text-base border-l-4 border-gray-300 pl-4 pr-4 text-gray-600; @apply text-base border-l-4 border-gray-300 pl-4 pr-4 text-gray-600;
} }
.markdown code:not([class*="language-"]) { .markdown code:not([class*='language-']) {
@apply font-mono text-sm inline bg-gray-200 rounded px-1 py-05; @apply font-mono text-sm inline bg-gray-200 rounded px-1 py-05;
} }
.markdown pre { .markdown pre {
@apply rounded; @apply rounded;
} }
.markdown pre:not([class*="language-"]) { .markdown pre:not([class*='language-']) {
@apply bg-gray-100 p-4; @apply bg-gray-100 p-4;
} }
.markdown pre:not([class*="language-"]) code { .markdown pre:not([class*='language-']) code {
@apply block bg-transparent p-0 overflow-visible rounded-none; @apply block bg-transparent p-0 overflow-visible rounded-none;
} }
.markdown ul { .markdown ul {
@apply text-base list-disc mb-4; @apply text-base list-disc mb-4;
} }
.markdown ul ul { .markdown ul ul {
list-style-type: circle; list-style-type: circle;
} }
.markdown ul ul ul { .markdown ul ul ul {
list-style-type: square; list-style-type: square;
} }
.markdown--module ul { .markdown--module ul {
@apply pl-8; @apply pl-8;
} }
.markdown--syllabus ul { .markdown--syllabus ul {
@apply pl-5; @apply pl-5;
} }
.markdown p { .markdown p {
@apply mb-4; @apply mb-4;
} }
.markdown ul ul { .markdown ul ul {
@apply mb-0; @apply mb-0;
} }
.markdown ul p { .markdown ul p {
@apply mb-0; @apply mb-0;
} }
.markdown ol { .markdown ol {
@apply text-base pl-8 list-decimal mb-4; @apply text-base pl-8 list-decimal mb-4;
} }
.markdown kbd { .markdown kbd {
@apply text-xs inline-block rounded border px-1 py-05 align-middle font-normal font-mono shadow; @apply text-xs inline-block rounded border px-1 py-05 align-middle font-normal font-mono shadow;
} }
.markdown table { .markdown table {
@apply text-base border-gray-600; @apply text-base border-gray-600;
} }
.markdown th { .markdown th {
@apply border py-1 px-3; @apply border py-1 px-3;
} }
.markdown td { .markdown td {
@apply border py-1 px-3; @apply border py-1 px-3;
} }
/* Override pygments style background color. */ /* Override pygments style background color. */
.markdown .highlight pre { .markdown .highlight pre {
@apply bg-gray-100 !important; @apply bg-gray-100 !important;
} }
.markdown--module .syllabus-only { .markdown--module .syllabus-only {
display: none; display: none;
} }
.spoiler-body pre { .spoiler-body pre {
margin-left: -1rem !important; margin-left: -1rem !important;
margin-right: -1rem !important; margin-right: -1rem !important;
margin-bottom: -1rem !important; margin-bottom: -1rem !important;
} }
.info-block .custom-block-heading { .info-block .custom-block-heading {
@apply text-sm leading-5 font-medium text-blue-800; @apply text-sm leading-5 font-medium text-blue-800;
} }
.info-block .custom-block-body { .info-block .custom-block-body {
@apply text-sm leading-5 text-blue-700 mt-2; @apply text-sm leading-5 text-blue-700 mt-2;
} }
.info-block .custom-block-body p:last-child { .info-block .custom-block-body p:last-child {
@apply mb-0; @apply mb-0;
} }
/*! purgecss end ignore */ /*! purgecss end ignore */

View file

@ -1,212 +1,212 @@
/*! purgecss start ignore */ /*! purgecss start ignore */
code[class*="language-"], code[class*='language-'],
pre[class*="language-"] { pre[class*='language-'] {
text-align: left; text-align: left;
white-space: pre; white-space: pre;
word-spacing: normal; word-spacing: normal;
word-break: normal; word-break: normal;
word-wrap: normal; word-wrap: normal;
color: #c3cee3; color: #c3cee3;
background: #263238; background: #263238;
font-family: Roboto Mono, monospace; font-family: Roboto Mono, monospace;
font-size: 1em; font-size: 1em;
line-height: 1.5em; line-height: 1.5em;
-moz-tab-size: 4; -moz-tab-size: 4;
-o-tab-size: 4; -o-tab-size: 4;
tab-size: 4; tab-size: 4;
-webkit-hyphens: none; -webkit-hyphens: none;
-moz-hyphens: none; -moz-hyphens: none;
-ms-hyphens: none; -ms-hyphens: none;
hyphens: none; hyphens: none;
} }
code[class*="language-"]::-moz-selection, code[class*='language-']::-moz-selection,
pre[class*="language-"]::-moz-selection, pre[class*='language-']::-moz-selection,
code[class*="language-"] ::-moz-selection, code[class*='language-'] ::-moz-selection,
pre[class*="language-"] ::-moz-selection { pre[class*='language-'] ::-moz-selection {
background: #363636; background: #363636;
} }
code[class*="language-"]::selection, code[class*='language-']::selection,
pre[class*="language-"]::selection, pre[class*='language-']::selection,
code[class*="language-"] ::selection, code[class*='language-'] ::selection,
pre[class*="language-"] ::selection { pre[class*='language-'] ::selection {
background: #363636; background: #363636;
} }
:not(pre) > code[class*="language-"] { :not(pre) > code[class*='language-'] {
white-space: normal; white-space: normal;
border-radius: 0.2em; border-radius: 0.2em;
padding: 0.1em; padding: 0.1em;
} }
pre[class*="language-"] { pre[class*='language-'] {
overflow: auto; overflow: auto;
position: relative; position: relative;
margin: 0.5em 0; margin: 0.5em 0;
padding: 1.25em 1em; padding: 1.25em 1em;
} }
.language-css > code, .language-css > code,
.language-sass > code, .language-sass > code,
.language-scss > code { .language-scss > code {
color: #fd9170; color: #fd9170;
} }
[class*="language-"] .namespace { [class*='language-'] .namespace {
opacity: 0.7; opacity: 0.7;
} }
.token.atrule { .token.atrule {
color: #c792ea; color: #c792ea;
} }
.token.attr-name { .token.attr-name {
color: #ffcb6b; color: #ffcb6b;
} }
.token.attr-value { .token.attr-value {
color: #c3e88d; color: #c3e88d;
} }
.token.attribute { .token.attribute {
color: #c3e88d; color: #c3e88d;
} }
.token.boolean { .token.boolean {
color: #c792ea; color: #c792ea;
} }
.token.builtin { .token.builtin {
color: #ffcb6b; color: #ffcb6b;
} }
.token.cdata { .token.cdata {
color: #80cbc4; color: #80cbc4;
} }
.token.char { .token.char {
color: #80cbc4; color: #80cbc4;
} }
.token.class { .token.class {
color: #ffcb6b; color: #ffcb6b;
} }
.token.class-name { .token.class-name {
color: #f2ff00; color: #f2ff00;
} }
.token.color { .token.color {
color: #f2ff00; color: #f2ff00;
} }
.token.comment { .token.comment {
color: #546e7a; color: #546e7a;
} }
.token.constant { .token.constant {
color: #c792ea; color: #c792ea;
} }
.token.deleted { .token.deleted {
color: #f07178; color: #f07178;
} }
.token.doctype { .token.doctype {
color: #546e7a; color: #546e7a;
} }
.token.entity { .token.entity {
color: #f07178; color: #f07178;
} }
.token.function { .token.function {
color: #c792ea; color: #c792ea;
} }
.token.hexcode { .token.hexcode {
color: #f2ff00; color: #f2ff00;
} }
.token.id { .token.id {
color: #c792ea; color: #c792ea;
font-weight: bold; font-weight: bold;
} }
.token.important { .token.important {
color: #c792ea; color: #c792ea;
font-weight: bold; font-weight: bold;
} }
.token.inserted { .token.inserted {
color: #80cbc4; color: #80cbc4;
} }
.token.keyword { .token.keyword {
color: #c792ea; color: #c792ea;
font-style: italic; font-style: italic;
} }
.token.number { .token.number {
color: #fd9170; color: #fd9170;
} }
.token.operator { .token.operator {
color: #89ddff; color: #89ddff;
} }
.token.prolog { .token.prolog {
color: #546e7a; color: #546e7a;
} }
.token.property { .token.property {
color: #80cbc4; color: #80cbc4;
} }
.token.pseudo-class { .token.pseudo-class {
color: #c3e88d; color: #c3e88d;
} }
.token.pseudo-element { .token.pseudo-element {
color: #c3e88d; color: #c3e88d;
} }
.token.punctuation { .token.punctuation {
color: #89ddff; color: #89ddff;
} }
.token.regex { .token.regex {
color: #f2ff00; color: #f2ff00;
} }
.token.selector { .token.selector {
color: #f07178; color: #f07178;
} }
.token.string { .token.string {
color: #c3e88d; color: #c3e88d;
} }
.token.symbol { .token.symbol {
color: #c792ea; color: #c792ea;
} }
.token.tag { .token.tag {
color: #f07178; color: #f07178;
} }
.token.unit { .token.unit {
color: #f07178; color: #f07178;
} }
.token.url { .token.url {
color: #fd9170; color: #fd9170;
} }
.token.variable { .token.variable {
color: #f07178; color: #f07178;
} }
/*! purgecss end ignore */ /*! purgecss end ignore */

View file

@ -1,286 +1,371 @@
import * as React from "react"; import * as React from 'react';
import {useState} from "react"; import { useState } from 'react';
import { graphql, Link } from "gatsby" import { graphql, Link } from 'gatsby';
import Layout from "../components/layout"; import Layout from '../components/layout';
import Markdown from "../components/Markdown"; import Markdown from '../components/Markdown';
import ModuleOrdering, { divisionLabels } from "../../content/ordering"; import ModuleOrdering, { divisionLabels } from '../../content/ordering';
import Transition from "../components/Transition"; import Transition from '../components/Transition';
import {graphqlToModulesObject} from "../utils"; import { graphqlToModulesObject } from '../utils';
const renderPrerequisite = (prerequisite) => { const renderPrerequisite = prerequisite => {
const link = prerequisite.length > 1 ? prerequisite[1] : null; const link = prerequisite.length > 1 ? prerequisite[1] : null;
return ( return (
<li key={prerequisite[0]}> <li key={prerequisite[0]}>
{link && <a href={link} className="text-blue-600 underline">{prerequisite[0]}</a>} {link && (
{!link && prerequisite[0]} <a href={link} className="text-blue-600 underline">
</li> {prerequisite[0]}
); </a>
)}
{!link && prerequisite[0]}
</li>
);
}; };
const Breadcrumbs = ({division}) => ( const Breadcrumbs = ({ division }) => (
<nav className="flex items-center text-sm leading-5 font-medium"> <nav className="flex items-center text-sm leading-5 font-medium">
<Link to="/" className="text-gray-500 hover:text-gray-700 transition duration-150 ease-in-out"> <Link
Home to="/"
</Link> className="text-gray-500 hover:text-gray-700 transition duration-150 ease-in-out"
<svg className="flex-shrink-0 mx-2 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor"> >
<path fillRule="evenodd" Home
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" </Link>
clipRule="evenodd" /> <svg
</svg> className="flex-shrink-0 mx-2 h-5 w-5 text-gray-400"
<Link to={`/${division}`} className="text-gray-500 hover:text-gray-700 transition duration-150 ease-in-out"> viewBox="0 0 20 20"
{divisionLabels[division]} fill="currentColor"
</Link> >
<svg className="flex-shrink-0 mx-2 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor"> <path
<path fillRule="evenodd" fillRule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clipRule="evenodd" /> clipRule="evenodd"
</svg> />
<span className="text-gray-500"> </svg>
Getting Started <Link
</span> to={`/${division}`}
</nav> className="text-gray-500 hover:text-gray-700 transition duration-150 ease-in-out"
>
{divisionLabels[division]}
</Link>
<svg
className="flex-shrink-0 mx-2 h-5 w-5 text-gray-400"
viewBox="0 0 20 20"
fill="currentColor"
>
<path
fillRule="evenodd"
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
clipRule="evenodd"
/>
</svg>
<span className="text-gray-500">Getting Started</span>
</nav>
); );
const SidebarBottomButtons = () => ( const SidebarBottomButtons = () => (
<> <>
<div className="flex-shrink-0 border-t border-gray-200 flex"> <div className="flex-shrink-0 border-t border-gray-200 flex">
<button className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"> <button className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150">
<svg className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"> <svg
<path d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"/> className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
</svg> fill="none"
Report an Issue viewBox="0 0 24 24"
</button> stroke="currentColor"
</div> strokeLinecap="round"
<div className="flex-shrink-0 border-t border-gray-200 flex"> strokeLinejoin="round"
<button className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150"> strokeWidth="2"
<svg className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150" fill="none" viewBox="0 0 24 24" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"> >
<path d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z"/> <path d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg> </svg>
Get Help Report an Issue
</button> </button>
</div> </div>
</> <div className="flex-shrink-0 border-t border-gray-200 flex">
<button className="group flex-1 flex items-center p-4 text-sm leading-5 font-medium text-gray-600 hover:text-gray-900 hover:bg-gray-50 focus:outline-none focus:bg-gray-100 transition ease-in-out duration-150">
<svg
className="mr-4 h-6 w-6 text-gray-400 group-hover:text-gray-500 group-focus:text-gray-500 transition ease-in-out duration-150"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
>
<path d="M8 10h.01M12 10h.01M16 10h.01M9 16H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-5l-5 5v-5z" />
</svg>
Get Help
</button>
</div>
</>
); );
interface NavLink { interface NavLink {
kind: "link" kind: 'link';
label: string label: string;
href: string href: string;
} }
interface NavLinkGroup { interface NavLinkGroup {
kind: "group" kind: 'group';
label: string label: string;
children: NavLink[] children: NavLink[];
} }
type NavLinkItem = NavLink | NavLinkGroup; type NavLinkItem = NavLink | NavLinkGroup;
const SidebarNavLinks = ({ links }) => { const SidebarNavLinks = ({ links }) => {
const renderLink = link => { const renderLink = link => {
if (link.kind === "link") { if (link.kind === 'link') {
return ( return (
<Link to={link.href} className={`flex items-center px-6 py-3 text-sm leading-5 text-gray-600 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:bg-gray-200 transition ease-in-out duration-150`}> <Link
{link.label} to={link.href}
</Link> className={`flex items-center px-6 py-3 text-sm leading-5 text-gray-600 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:bg-gray-200 transition ease-in-out duration-150`}
); >
} {link.label}
return ( </Link>
<div className="bg-gray-100 mb-4"> );
<div className={`flex items-center px-6 py-3 text-sm leading-5 font-medium text-gray-600 border-b border-gray-200`}> }
{link.label} return (
</div> <div className="bg-gray-100 mb-4">
{link.children.map(renderLink)} <div
</div> className={`flex items-center px-6 py-3 text-sm leading-5 font-medium text-gray-600 border-b border-gray-200`}
) >
}; {link.label}
return ( </div>
<> {link.children.map(renderLink)}
{links.map(renderLink)} </div>
</> );
); };
return <>{links.map(renderLink)}</>;
}; };
export default function Template(props) { export default function Template(props) {
const { mdx, allMdx } = props.data; // data.markdownRemark holds your post data const { mdx, allMdx } = props.data; // data.markdownRemark holds your post data
const { body } = mdx; const { body } = mdx;
const prereqs = mdx.frontmatter.prerequisites; const prereqs = mdx.frontmatter.prerequisites;
const division = props.pageContext.division; const division = props.pageContext.division;
const [isMobileNavOpen, setIsMobileNavOpen] = useState(false); const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
const navLinks: (NavLinkItem)[] = React.useMemo(() => { const navLinks: NavLinkItem[] = React.useMemo(() => {
const modules = graphqlToModulesObject(allMdx); const modules = graphqlToModulesObject(allMdx);
const getLinks = module => { const getLinks = module => {
if (module.hasOwnProperty("name")) { if (module.hasOwnProperty('name')) {
return { return {
kind: "group", kind: 'group',
label: module.name, label: module.name,
children: module.items.map(getLinks) children: module.items.map(getLinks),
}; };
} }
if (!modules.hasOwnProperty(module)) { if (!modules.hasOwnProperty(module)) {
throw `${module} not found!`; throw `${module} not found!`;
} }
return { return {
kind: "link", kind: 'link',
label: modules[module].frontmatter.title, label: modules[module].frontmatter.title,
href: `/${division}/${module}` href: `/${division}/${module}`,
}; };
}; };
return ModuleOrdering[division].map(getLinks); return ModuleOrdering[division].map(getLinks);
}, []); }, []);
return ( return (
<Layout> <Layout>
<div className="h-screen flex overflow-hidden bg-white"> <div className="h-screen flex overflow-hidden bg-white">
{/* Off-canvas menu for mobile */} {/* Off-canvas menu for mobile */}
<Transition show={isMobileNavOpen}> <Transition show={isMobileNavOpen}>
<div className="lg:hidden"> <div className="lg:hidden">
<div className="fixed inset-0 flex z-40"> <div className="fixed inset-0 flex z-40">
<Transition <Transition
enter="transition-opacity ease-linear duration-300" enter="transition-opacity ease-linear duration-300"
enterFrom="opacity-0" enterFrom="opacity-0"
enterTo="opacity-100" enterTo="opacity-100"
leave="transition-opacity ease-linear duration-300" leave="transition-opacity ease-linear duration-300"
leaveFrom="opacity-100" leaveFrom="opacity-100"
leaveTo="opacity-0" leaveTo="opacity-0"
> >
<div className="fixed inset-0" onClick={() => setIsMobileNavOpen(false)}> <div
<div className="absolute inset-0 bg-gray-600 opacity-75" /> className="fixed inset-0"
</div> onClick={() => setIsMobileNavOpen(false)}
</Transition> >
<div className="absolute inset-0 bg-gray-600 opacity-75" />
</div>
</Transition>
<Transition <Transition
enter="transition ease-in-out duration-300 transform" enter="transition ease-in-out duration-300 transform"
enterFrom="-translate-x-full" enterFrom="-translate-x-full"
enterTo="translate-x-0" enterTo="translate-x-0"
leave="transition ease-in-out duration-300 transform" leave="transition ease-in-out duration-300 transform"
leaveFrom="translate-x-0" leaveFrom="translate-x-0"
leaveTo="-translate-x-full" leaveTo="-translate-x-full"
> >
<div className="relative flex-1 flex flex-col max-w-xs w-full bg-white"> <div className="relative flex-1 flex flex-col max-w-xs w-full bg-white">
<div className="absolute top-0 right-0 -mr-14 p-1"> <div className="absolute top-0 right-0 -mr-14 p-1">
<button className="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600" aria-label="Close sidebar" onClick={() => setIsMobileNavOpen(false)}> <button
<svg className="h-6 w-6 text-white" stroke="currentColor" fill="none" viewBox="0 0 24 24"> className="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600"
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /> aria-label="Close sidebar"
</svg> onClick={() => setIsMobileNavOpen(false)}
</button> >
</div> <svg
<div className="flex-1 h-0 pt-5 pb-4 overflow-y-auto"> className="h-6 w-6 text-white"
<div className="flex-shrink-0 flex items-center px-4"> stroke="currentColor"
<img className="h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg" alt="Workflow" /> fill="none"
</div> viewBox="0 0 24 24"
<div className="mt-8 px-6"> >
<Breadcrumbs division={division} /> <path
</div> strokeLinecap="round"
<nav className="mt-2"> strokeLinejoin="round"
<SidebarNavLinks links={navLinks} /> strokeWidth={2}
</nav> d="M6 18L18 6M6 6l12 12"
</div> />
<SidebarBottomButtons /> </svg>
</div> </button>
</Transition> </div>
<div className="flex-shrink-0 w-14"> <div className="flex-1 h-0 pt-5 pb-4 overflow-y-auto">
{/* Force sidebar to shrink to fit close icon */} <div className="flex-shrink-0 flex items-center px-4">
</div> <img
</div> className="h-8 w-auto"
</div> src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg"
</Transition> alt="Workflow"
{/* Static sidebar for desktop */} />
<div className="hidden lg:flex lg:flex-shrink-0"> </div>
<div className="flex flex-col w-64 border-r border-gray-200 bg-white"> <div className="mt-8 px-6">
<div className="h-0 flex-1 flex flex-col pt-5 pb-4 overflow-y-auto"> <Breadcrumbs division={division} />
<div className="flex items-center flex-shrink-0 px-4"> </div>
<img className="h-8 w-auto" src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg" alt="Workflow" /> <nav className="mt-2">
</div> <SidebarNavLinks links={navLinks} />
{/* Sidebar component, swap this element with another sidebar if you like */} </nav>
<nav className="mt-5 flex-1 bg-white"> </div>
<SidebarNavLinks links={navLinks} /> <SidebarBottomButtons />
</nav> </div>
</div> </Transition>
<SidebarBottomButtons /> <div className="flex-shrink-0 w-14">
</div> {/* Force sidebar to shrink to fit close icon */}
</div> </div>
<div className="flex flex-col w-0 flex-1 overflow-hidden"> </div>
<div className="lg:hidden pl-1 pt-1 sm:pl-3 sm:pt-3"> </div>
<button className="-ml-0.5 -mt-0.5 h-12 w-12 inline-flex items-center justify-center rounded-md text-gray-500 hover:text-gray-900 focus:outline-none focus:bg-gray-200 transition ease-in-out duration-150" aria-label="Open sidebar" </Transition>
onClick={() => setIsMobileNavOpen(true)} {/* Static sidebar for desktop */}
> <div className="hidden lg:flex lg:flex-shrink-0">
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor"> <div className="flex flex-col w-64 border-r border-gray-200 bg-white">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" /> <div className="h-0 flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
</svg> <div className="flex items-center flex-shrink-0 px-4">
</button> <img
</div> className="h-8 w-auto"
<main className="flex-1 relative z-0 overflow-y-auto sm:pt-2 pb-6 focus:outline-none lg:py-6" tabIndex={0}> src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg"
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8"> alt="Workflow"
<div> />
<div className="hidden lg:block"> </div>
<Breadcrumbs division={division} /> {/* Sidebar component, swap this element with another sidebar if you like */}
</div> <nav className="mt-5 flex-1 bg-white">
<div className="lg:mt-12 mb-4"> <SidebarNavLinks links={navLinks} />
<div className="flex-1 min-w-0"> </nav>
<h1 className="text-2xl font-bold text-gray-900 sm:text-3xl"> </div>
{mdx.frontmatter.title} <SidebarBottomButtons />
</h1> </div>
<p className={`text-gray-500`}>Author: {mdx.frontmatter.author}</p> </div>
</div> <div className="flex flex-col w-0 flex-1 overflow-hidden">
</div> <div className="lg:hidden pl-1 pt-1 sm:pl-3 sm:pt-3">
</div> <button
<div className="py-4"> className="-ml-0.5 -mt-0.5 h-12 w-12 inline-flex items-center justify-center rounded-md text-gray-500 hover:text-gray-900 focus:outline-none focus:bg-gray-200 transition ease-in-out duration-150"
{prereqs && aria-label="Open sidebar"
<div className="rounded-md bg-blue-50 p-4 mb-12"> onClick={() => setIsMobileNavOpen(true)}
<div className="flex"> >
<div className="flex-shrink-0"> <svg
<svg className="h-5 w-5 text-blue-400" fill="currentColor" viewBox="0 0 20 20"> className="h-6 w-6"
<path fillRule="evenodd" fill="none"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" viewBox="0 0 24 24"
clipRule="evenodd" /> stroke="currentColor"
</svg> >
</div> <path
<div className="ml-3"> strokeLinecap="round"
<h3 className="text-sm leading-5 font-medium text-blue-800"> strokeLinejoin="round"
Prerequisites strokeWidth={2}
</h3> d="M4 6h16M4 12h16M4 18h16"
<div className="mt-2 text-sm leading-5 text-blue-800"> />
<ul className="list-disc list-inside pl-3 space-y-1"> </svg>
{prereqs.map(renderPrerequisite)} </button>
</ul> </div>
</div> <main
</div> className="flex-1 relative z-0 overflow-y-auto sm:pt-2 pb-6 focus:outline-none lg:py-6"
</div> tabIndex={0}
</div>} >
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<div>
<div className="hidden lg:block">
<Breadcrumbs division={division} />
</div>
<div className="lg:mt-12 mb-4">
<div className="flex-1 min-w-0">
<h1 className="text-2xl font-bold text-gray-900 sm:text-3xl">
{mdx.frontmatter.title}
</h1>
<p className={`text-gray-500`}>
Author: {mdx.frontmatter.author}
</p>
</div>
</div>
</div>
<div className="py-4">
{prereqs && (
<div className="rounded-md bg-blue-50 p-4 mb-12">
<div className="flex">
<div className="flex-shrink-0">
<svg
className="h-5 w-5 text-blue-400"
fill="currentColor"
viewBox="0 0 20 20"
>
<path
fillRule="evenodd"
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z"
clipRule="evenodd"
/>
</svg>
</div>
<div className="ml-3">
<h3 className="text-sm leading-5 font-medium text-blue-800">
Prerequisites
</h3>
<div className="mt-2 text-sm leading-5 text-blue-800">
<ul className="list-disc list-inside pl-3 space-y-1">
{prereqs.map(renderPrerequisite)}
</ul>
</div>
</div>
</div>
</div>
)}
<Markdown body={body} className="markdown--module" />
<Markdown body={body} className="markdown--module" /> </div>
</div> </div>
</div> </main>
</main> </div>
</div> </div>
</div> </Layout>
</Layout> );
)
} }
export const pageQuery = graphql` export const pageQuery = graphql`
query($id: String!) { query($id: String!) {
mdx(frontmatter: { id: { eq: $id } }) { mdx(frontmatter: { id: { eq: $id } }) {
body body
frontmatter { frontmatter {
title title
author author
id id
prerequisites prerequisites
} }
} }
allMdx { allMdx {
edges { edges {
node { node {
frontmatter { frontmatter {
title title
id id
} }
} }
} }
} }
} }
`; `;

View file

@ -1,53 +1,57 @@
import React from "react" import React from 'react';
import Layout from "../components/layout" import Layout from '../components/layout';
import SEO from "../components/seo" import SEO from '../components/seo';
import { graphql, Link } from "gatsby"; import { graphql, Link } from 'gatsby';
import { divisionLabels, divisions } from "../../content/ordering"; import { divisionLabels, divisions } from '../../content/ordering';
import { getModule, graphqlToModulesObject } from "../utils"; import { getModule, graphqlToModulesObject } from '../utils';
import SyllabusModule from "../components/SyllabusModule"; import SyllabusModule from '../components/SyllabusModule';
const renderModule = (node, idx, parentIdx = -1) => { const renderModule = (node, idx, parentIdx = -1) => {
if (node.hasOwnProperty("items")) { if (node.hasOwnProperty('items')) {
return node.items.map((x, i) => renderModule(x, i, idx)); return node.items.map((x, i) => renderModule(x, i, idx));
} }
const data = node.frontmatter; const data = node.frontmatter;
if (!data.title) return; if (!data.title) return;
return ( return (
<SyllabusModule <SyllabusModule
title={`${parentIdx !== -1 ? (parentIdx+1)+"." : ""}${idx+1}. ${data.title}`} title={`${parentIdx !== -1 ? parentIdx + 1 + '.' : ''}${idx + 1}. ${
url={node.slug} data.title
key={node.slug} }`}
problems={data.problems} url={node.slug}
prerequisites={data.prerequisites} key={node.slug}
author={data.author} problems={data.problems}
> prerequisites={data.prerequisites}
{data.description} author={data.author}
</SyllabusModule> >
); {data.description}
</SyllabusModule>
);
}; };
export default function Template(props) { export default function Template(props) {
const data = props.data; const data = props.data;
const allModules = graphqlToModulesObject(data.modules); const allModules = graphqlToModulesObject(data.modules);
const [selectedDivision, setSelectedDivision] = React.useState(props.pageContext.division); const [selectedDivision, setSelectedDivision] = React.useState(
const colors = { props.pageContext.division
"intro": "blue", );
"general": "pink", const colors = {
"bronze": "orange", intro: 'blue',
"silver": "teal", general: 'pink',
"gold": "yellow", bronze: 'orange',
"plat": "purple" silver: 'teal',
}; gold: 'yellow',
const color = colors[selectedDivision]; plat: 'purple',
const module = getModule(allModules, selectedDivision); };
const color = colors[selectedDivision];
const module = getModule(allModules, selectedDivision);
// for purgecss, we have to list all the classes that are dynamically generated... // for purgecss, we have to list all the classes that are dynamically generated...
/* /*
bg-blue-500 hover:bg-blue-50 hover:text-blue-600 focus:shadow-outline-blue bg-blue-500 hover:bg-blue-50 hover:text-blue-600 focus:shadow-outline-blue
bg-pink-500 hover:bg-pink-50 hover:text-pink-600 focus:shadow-outline-pink bg-pink-500 hover:bg-pink-50 hover:text-pink-600 focus:shadow-outline-pink
bg-orange-500 hover:bg-orange-50 hover:text-orange-600 focus:shadow-outline-orange bg-orange-500 hover:bg-orange-50 hover:text-orange-600 focus:shadow-outline-orange
@ -61,149 +65,230 @@ export default function Template(props) {
border-yellow-500 text-yellow-600 focus:text-yellow-800 focus:border-yellow-700 border-yellow-300 focus:border-yellow-300 text-yellow-500 text-yellow-300 bg-yellow-600 border-yellow-500 text-yellow-600 focus:text-yellow-800 focus:border-yellow-700 border-yellow-300 focus:border-yellow-300 text-yellow-500 text-yellow-300 bg-yellow-600
border-purple-500 text-purple-600 focus:text-purple-800 focus:border-purple-700 border-purple-300 focus:border-purple-300 text-purple-500 text-purple-300 bg-purple-600 border-purple-500 text-purple-600 focus:text-purple-800 focus:border-purple-700 border-purple-300 focus:border-purple-300 text-purple-500 text-purple-300 bg-purple-600
*/ */
// alternatively we can just not dynamically generate classes, but that seems more tedious. // alternatively we can just not dynamically generate classes, but that seems more tedious.
const selectedTabClasses = `flex-1 py-4 px-1 text-center border-b-2 border-${color}-500 font-bold text-lg leading-5 text-${color}-600 focus:outline-none focus:text-${color}-800 focus:border-${color}-700`, const selectedTabClasses = `flex-1 py-4 px-1 text-center border-b-2 border-${color}-500 font-bold text-lg leading-5 text-${color}-600 focus:outline-none focus:text-${color}-800 focus:border-${color}-700`,
unselectedTabClasses = `flex-1 py-4 px-1 text-center border-b-2 border-transparent font-bold text-lg leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300`; unselectedTabClasses = `flex-1 py-4 px-1 text-center border-b-2 border-transparent font-bold text-lg leading-5 text-gray-500 hover:text-gray-700 hover:border-gray-300 focus:outline-none focus:text-gray-700 focus:border-gray-300`;
const handleDivisionChange = d => { const handleDivisionChange = d => {
setSelectedDivision(d); setSelectedDivision(d);
window.history.pushState(null, "", `/${d}/`); window.history.pushState(null, '', `/${d}/`);
}; };
return ( return (
<Layout> <Layout>
<SEO title="Home" /> <SEO title="Home" />
<div className="min-h-screen bg-gray-50"> <div className="min-h-screen bg-gray-50">
{/* Begin Hero Section */}
<div
className={`relative bg-${color}-600 overflow-hidden transition duration-300 pb-48`}
>
<div className="hidden sm:block sm:absolute sm:inset-y-0 sm:h-full sm:w-full">
<div className="relative h-full max-w-screen-xl mx-auto">
<svg
className="absolute right-full transform translate-y-1/4 translate-x-1/4 lg:translate-x-1/2"
width={404}
height={784}
fill="none"
viewBox="0 0 404 784"
>
<defs>
<pattern
id="f210dbf6-a58d-4871-961e-36d5016a0f49"
x={0}
y={0}
width={20}
height={20}
patternUnits="userSpaceOnUse"
>
<rect
x={0}
y={0}
width={4}
height={4}
className={`text-${color}-500 transition duration-300`}
fill="currentColor"
/>
</pattern>
</defs>
<rect
width={404}
height={784}
fill="url(#f210dbf6-a58d-4871-961e-36d5016a0f49)"
/>
</svg>
<svg
className="absolute left-full transform -translate-y-3/4 -translate-x-1/4 md:-translate-y-1/2 lg:-translate-x-1/2"
width={404}
height={784}
fill="none"
viewBox="0 0 404 784"
>
<defs>
<pattern
id="5d0dd344-b041-4d26-bec4-8d33ea57ec9b"
x={0}
y={0}
width={20}
height={20}
patternUnits="userSpaceOnUse"
>
<rect
x={0}
y={0}
width={4}
height={4}
className={`text-${color}-500 transition duration-300`}
fill="currentColor"
/>
</pattern>
</defs>
<rect
width={404}
height={784}
fill="url(#5d0dd344-b041-4d26-bec4-8d33ea57ec9b)"
/>
</svg>
</div>
</div>
<div className="relative pt-6 pb-12 sm:pb-16 md:pb-20 lg:pb-28 xl:pb-32">
<div className="mt-10 mx-auto max-w-screen-xl px-4 sm:mt-12 sm:px-6 md:mt-16 lg:mt-20 xl:mt-28">
<div className="text-center">
<h2 className="text-4xl tracking-tight leading-10 font-extrabold text-white sm:text-5xl sm:leading-none md:text-6xl">
USACO Guide
</h2>
<p
className={`mt-3 max-w-md mx-auto text-base text-${color}-300 sm:text-lg md:mt-5 md:text-xl md:max-w-3xl`}
>
A collection of curated, high-quality resources to take you
from Bronze to Platinum.
</p>
<div className="mt-5 max-w-md mx-auto sm:flex sm:justify-center md:mt-8">
<div className="rounded-md shadow">
<Link
to="/"
className={`w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-${color}-500 hover:bg-${color}-50 hover:text-${color}-600 focus:outline-none focus:shadow-outline-${color} transition duration-300 ease-in-out md:py-4 md:text-lg md:px-10`}
>
About This Guide
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
{/* End Hero Section */}
{/* Begin Hero Section */} <div className="pb-8" id="content">
<div className={`relative bg-${color}-600 overflow-hidden transition duration-300 pb-48`}> <div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 pb-4">
<div className="hidden sm:block sm:absolute sm:inset-y-0 sm:h-full sm:w-full"> <div
<div className="relative h-full max-w-screen-xl mx-auto"> className="mb-8 bg-white shadow-md rounded-lg relative"
<svg className="absolute right-full transform translate-y-1/4 translate-x-1/4 lg:translate-x-1/2" style={{ marginTop: '-12rem' }}
width={404} >
height={784} fill="none" viewBox="0 0 404 784"> <div className="sm:hidden">
<defs> <select
<pattern id="f210dbf6-a58d-4871-961e-36d5016a0f49" x={0} y={0} width={20} height={20} aria-label="Selected tab"
patternUnits="userSpaceOnUse"> className="form-select block w-full"
<rect x={0} y={0} width={4} height={4} className={`text-${color}-500 transition duration-300`} fill="currentColor" /> onChange={e => handleDivisionChange(e.target.value)}
</pattern> value={selectedDivision}
</defs> >
<rect width={404} height={784} fill="url(#f210dbf6-a58d-4871-961e-36d5016a0f49)" /> {divisions.map(division => (
</svg> <option key={division} value={division}>
<svg {divisionLabels[division]}
className="absolute left-full transform -translate-y-3/4 -translate-x-1/4 md:-translate-y-1/2 lg:-translate-x-1/2" </option>
width={404} height={784} fill="none" viewBox="0 0 404 784"> ))}
<defs> </select>
<pattern id="5d0dd344-b041-4d26-bec4-8d33ea57ec9b" x={0} y={0} width={20} height={20} </div>
patternUnits="userSpaceOnUse"> <div className="hidden sm:block border-b border-gray-200">
<rect x={0} y={0} width={4} height={4} className={`text-${color}-500 transition duration-300`} fill="currentColor" /> <nav className="flex -mb-px">
</pattern> {divisions.map(division => (
</defs> <a
<rect width={404} height={784} fill="url(#5d0dd344-b041-4d26-bec4-8d33ea57ec9b)" /> key={division}
</svg> href={`/${division}`}
</div> onClick={e => {
</div> e.preventDefault();
<div className="relative pt-6 pb-12 sm:pb-16 md:pb-20 lg:pb-28 xl:pb-32"> handleDivisionChange(division);
<div className="mt-10 mx-auto max-w-screen-xl px-4 sm:mt-12 sm:px-6 md:mt-16 lg:mt-20 xl:mt-28"> }}
<div className="text-center"> className={
<h2 selectedDivision === division
className="text-4xl tracking-tight leading-10 font-extrabold text-white sm:text-5xl sm:leading-none md:text-6xl"> ? selectedTabClasses
USACO Guide : unselectedTabClasses
</h2> }
<p className={`mt-3 max-w-md mx-auto text-base text-${color}-300 sm:text-lg md:mt-5 md:text-xl md:max-w-3xl`}> >
A collection of curated, high-quality resources to take you from Bronze to Platinum. {divisionLabels[division]}
</p> </a>
<div className="mt-5 max-w-md mx-auto sm:flex sm:justify-center md:mt-8"> ))}
<div className="rounded-md shadow"> </nav>
<Link to="/" </div>
className={`w-full flex items-center justify-center px-8 py-3 border border-transparent text-base leading-6 font-medium rounded-md text-white bg-${color}-500 hover:bg-${color}-50 hover:text-${color}-600 focus:outline-none focus:shadow-outline-${color} transition duration-300 ease-in-out md:py-4 md:text-lg md:px-10`}>
About This Guide
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
{/* End Hero Section */}
<div className="pb-8" id="content"> <ol className="list-inside py-8 px-8 text-lg space-y-1">
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 pb-4"> {module.map((m, idx) => {
<div className="mb-8 bg-white shadow-md rounded-lg relative" style={{ marginTop: "-12rem" }}> if (m.hasOwnProperty('items')) {
<div className="sm:hidden"> return (
<select aria-label="Selected tab" <li key={m.name}>
className="form-select block w-full" <span className="inline-block w-4 text-right">
onChange={e => handleDivisionChange(e.target.value)} {idx + 1}.{' '}
value={selectedDivision} </span>
> <span className="ml-2">{m.name}</span>
{divisions.map(division => ( <ol className="list-inside px-6 text-lg space-y-1 mb-2">
<option key={division} value={division}>{divisionLabels[division]}</option> {m.items.map((m, idx2) => (
))} <li key={m.slug}>
</select> <span className="inline-block w-8 text-right">
</div> {idx + 1}.{idx2 + 1}.{' '}
<div className="hidden sm:block border-b border-gray-200"> </span>
<nav className="flex -mb-px"> <Link
{divisions.map(division => ( className="ml-2 text-blue-600 underline"
<a key={division} to={m.slug}
href={`/${division}`} >
onClick={e => {e.preventDefault(); handleDivisionChange(division)}} {m.frontmatter.title}
className={selectedDivision === division ? selectedTabClasses : unselectedTabClasses}> </Link>
{divisionLabels[division]} </li>
</a> ))}
))} </ol>
</nav> </li>
</div> );
}
return (
<li key={m.frontmatter.id}>
<span className="inline-block w-4 text-right">
{idx + 1}.{' '}
</span>
<Link
className="ml-2 text-blue-600 underline"
to={m.slug}
>
{m.frontmatter.title}
</Link>
</li>
);
})}
</ol>
</div>
<ol className="list-inside py-8 px-8 text-lg space-y-1"> {module.map((x, idx) => renderModule(x, idx))}
{module.map((m, idx) => { </div>
if (m.hasOwnProperty("items")) { </div>
return ( </div>
<li key={m.name}> </Layout>
<span className="inline-block w-4 text-right">{idx+1}. </span><span className="ml-2">{m.name}</span> );
<ol className="list-inside px-6 text-lg space-y-1 mb-2">
{m.items.map((m, idx2) => (
<li key={m.slug}>
<span className="inline-block w-8 text-right">{idx+1}.{idx2+1}. </span><Link className="ml-2 text-blue-600 underline" to={m.slug}>{m.frontmatter.title}</Link>
</li>
))}
</ol>
</li>
)
}
return (
<li key={m.frontmatter.id}>
<span className="inline-block w-4 text-right">{idx+1}. </span><Link className="ml-2 text-blue-600 underline" to={m.slug}>{m.frontmatter.title}</Link>
</li>
);
})}
</ol>
</div>
{module.map((x, idx) => renderModule(x, idx))}
</div>
</div>
</div>
</Layout>
);
} }
export const pageQuery = graphql` export const pageQuery = graphql`
query { query {
modules: allMdx { modules: allMdx {
edges { edges {
node { node {
id id
frontmatter { frontmatter {
title title
id id
author author
problems problems
prerequisites prerequisites
description description
} }
} }
} }
} }
} }
`; `;

View file

@ -1,36 +1,36 @@
import ModuleOrdering from "../content/ordering"; import ModuleOrdering from '../content/ordering';
export const getModule = (allModules, division) => { export const getModule = (allModules, division) => {
return ModuleOrdering[division].map(k => { return ModuleOrdering[division].map(k => {
// rip spaghetti code, clean this up // rip spaghetti code, clean this up
if (typeof k === "object") { if (typeof k === 'object') {
return { return {
name: k.name, name: k.name,
items: k.items.map(k2 => { items: k.items.map(k2 => {
if (!allModules.hasOwnProperty(k2)) { if (!allModules.hasOwnProperty(k2)) {
throw "Module not found: " + k2; throw 'Module not found: ' + k2;
} }
return { return {
...allModules[k2], ...allModules[k2],
slug: `/${division}/${allModules[k2].frontmatter.id}` slug: `/${division}/${allModules[k2].frontmatter.id}`,
}; };
}) }),
} };
} else { } else {
if (!allModules.hasOwnProperty(k)) { if (!allModules.hasOwnProperty(k)) {
throw "Module not found: " + k; throw 'Module not found: ' + k;
} }
return { return {
...allModules[k], ...allModules[k],
slug: `/${division}/${allModules[k].frontmatter.id}` slug: `/${division}/${allModules[k].frontmatter.id}`,
}; };
} }
}); });
}; };
export const graphqlToModulesObject = (allMdx) => { export const graphqlToModulesObject = allMdx => {
return allMdx.edges.reduce((acc, cur) => { return allMdx.edges.reduce((acc, cur) => {
acc[cur.node.frontmatter.id] = cur.node; acc[cur.node.frontmatter.id] = cur.node;
return acc; return acc;
}, {}); }, {});
}; };

View file

@ -1,8 +1,6 @@
module.exports = { module.exports = {
plugins: [ plugins: [require('@tailwindcss/ui')],
require('@tailwindcss/ui'), purge: {
], content: ['./src/**/*.js', './src/**/*.ts', './src/**/*.tsx'],
purge: { },
content: ['./src/**/*.js', "./src/**/*.ts", "./src/**/*.tsx"], };
},
};

139
yarn.lock
View file

@ -2712,7 +2712,7 @@ ansi-align@^3.0.0:
dependencies: dependencies:
string-width "^3.0.0" string-width "^3.0.0"
ansi-colors@^3.0.0: ansi-colors@^3.0.0, ansi-colors@^3.2.1:
version "3.2.4" version "3.2.4"
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf"
integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==
@ -2722,7 +2722,7 @@ ansi-escapes@^3.0.0, ansi-escapes@^3.1.0, ansi-escapes@^3.2.0:
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b"
integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==
ansi-escapes@^4.2.1: ansi-escapes@^4.2.1, ansi-escapes@^4.3.0:
version "4.3.1" version "4.3.1"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.1.tgz#a5c47cc43181f1f38ffd7076837700d395522a61"
integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA== integrity sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==
@ -4232,7 +4232,7 @@ cli-table3@^0.5.1:
optionalDependencies: optionalDependencies:
colors "^1.1.2" colors "^1.1.2"
cli-truncate@^2.1.0: cli-truncate@2.1.0, cli-truncate@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7" resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-2.1.0.tgz#c39e28bf05edcde5be3b98992a22deed5a2b93c7"
integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg== integrity sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==
@ -4382,7 +4382,7 @@ commander@^2.11.0, commander@^2.19.0, commander@^2.20.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commander@^5.0.0: commander@^5.0.0, commander@^5.1.0:
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
@ -4404,6 +4404,11 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
compare-versions@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.6.0.tgz#1a5689913685e5a87637b8d3ffca75514ec41d62"
integrity sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==
component-bind@1.0.0: component-bind@1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1"
@ -5156,6 +5161,11 @@ decompress@^4.0.0, decompress@^4.2.0:
pify "^2.3.0" pify "^2.3.0"
strip-dirs "^2.0.0" strip-dirs "^2.0.0"
dedent@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c"
integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=
deep-equal@^1.0.1, deep-equal@^1.1.0: deep-equal@^1.0.1, deep-equal@^1.1.0:
version "1.1.1" version "1.1.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a"
@ -5760,6 +5770,13 @@ enhanced-resolve@^4.1.0:
memory-fs "^0.5.0" memory-fs "^0.5.0"
tapable "^1.0.0" tapable "^1.0.0"
enquirer@^2.3.5:
version "2.3.5"
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.5.tgz#3ab2b838df0a9d8ab9e7dff235b0e8712ef92381"
integrity sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==
dependencies:
ansi-colors "^3.2.1"
entities@^1.1.1, entities@~1.1.1: entities@^1.1.1, entities@~1.1.1:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
@ -6518,7 +6535,7 @@ figures@^2.0.0:
dependencies: dependencies:
escape-string-regexp "^1.0.5" escape-string-regexp "^1.0.5"
figures@^3.0.0: figures@^3.0.0, figures@^3.2.0:
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
@ -6687,7 +6704,7 @@ find-up@^4.0.0, find-up@^4.1.0:
locate-path "^5.0.0" locate-path "^5.0.0"
path-exists "^4.0.0" path-exists "^4.0.0"
find-versions@^3.0.0: find-versions@^3.0.0, find-versions@^3.2.0:
version "3.2.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e" resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.2.0.tgz#10297f98030a786829681690545ef659ed1d254e"
integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww== integrity sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==
@ -8538,6 +8555,22 @@ human-signals@^1.1.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
husky@^4.2.5:
version "4.2.5"
resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36"
integrity sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ==
dependencies:
chalk "^4.0.0"
ci-info "^2.0.0"
compare-versions "^3.6.0"
cosmiconfig "^6.0.0"
find-versions "^3.2.0"
opencollective-postinstall "^2.0.2"
pkg-dir "^4.2.0"
please-upgrade-node "^3.2.0"
slash "^3.0.0"
which-pm-runs "^1.0.0"
iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13: iconv-lite@0.4.24, iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13:
version "0.4.24" version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@ -9741,6 +9774,41 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00"
integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=
lint-staged@^10.2.11:
version "10.2.11"
resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-10.2.11.tgz#713c80877f2dc8b609b05bc59020234e766c9720"
integrity sha512-LRRrSogzbixYaZItE2APaS4l2eJMjjf5MbclRZpLJtcQJShcvUzKXsNeZgsLIZ0H0+fg2tL4B59fU9wHIHtFIA==
dependencies:
chalk "^4.0.0"
cli-truncate "2.1.0"
commander "^5.1.0"
cosmiconfig "^6.0.0"
debug "^4.1.1"
dedent "^0.7.0"
enquirer "^2.3.5"
execa "^4.0.1"
listr2 "^2.1.0"
log-symbols "^4.0.0"
micromatch "^4.0.2"
normalize-path "^3.0.0"
please-upgrade-node "^3.2.0"
string-argv "0.3.1"
stringify-object "^3.3.0"
listr2@^2.1.0:
version "2.1.8"
resolved "https://registry.yarnpkg.com/listr2/-/listr2-2.1.8.tgz#8af7ebc70cdbe866ddbb6c80909142bd45758f1f"
integrity sha512-Op+hheiChfAphkJ5qUxZtHgyjlX9iNnAeFS/S134xw7mVSg0YVrQo1IY4/K+ElY6XgOPg2Ij4z07urUXR+YEew==
dependencies:
chalk "^4.0.0"
cli-truncate "^2.1.0"
figures "^3.2.0"
indent-string "^4.0.0"
log-update "^4.0.0"
p-map "^4.0.0"
rxjs "^6.5.5"
through "^2.3.8"
load-bmfont@^1.3.1, load-bmfont@^1.4.0: load-bmfont@^1.3.1, load-bmfont@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b" resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b"
@ -9973,6 +10041,13 @@ lodash@4.17.15, lodash@^4.11.1, lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.13
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==
log-symbols@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920"
integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA==
dependencies:
chalk "^4.0.0"
log-update@^3.0.0: log-update@^3.0.0:
version "3.4.0" version "3.4.0"
resolved "https://registry.yarnpkg.com/log-update/-/log-update-3.4.0.tgz#3b9a71e00ac5b1185cc193a36d654581c48f97b9" resolved "https://registry.yarnpkg.com/log-update/-/log-update-3.4.0.tgz#3b9a71e00ac5b1185cc193a36d654581c48f97b9"
@ -9982,6 +10057,16 @@ log-update@^3.0.0:
cli-cursor "^2.1.0" cli-cursor "^2.1.0"
wrap-ansi "^5.0.0" wrap-ansi "^5.0.0"
log-update@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/log-update/-/log-update-4.0.0.tgz#589ecd352471f2a1c0c570287543a64dfd20e0a1"
integrity sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==
dependencies:
ansi-escapes "^4.3.0"
cli-cursor "^3.1.0"
slice-ansi "^4.0.0"
wrap-ansi "^6.2.0"
logalot@^2.0.0, logalot@^2.1.0: logalot@^2.0.0, logalot@^2.1.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552"
@ -11109,6 +11194,11 @@ open@^6.4.0:
dependencies: dependencies:
is-wsl "^1.1.0" is-wsl "^1.1.0"
opencollective-postinstall@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
opentracing@^0.14.4: opentracing@^0.14.4:
version "0.14.4" version "0.14.4"
resolved "https://registry.yarnpkg.com/opentracing/-/opentracing-0.14.4.tgz#a113408ea740da3a90fde5b3b0011a375c2e4268" resolved "https://registry.yarnpkg.com/opentracing/-/opentracing-0.14.4.tgz#a113408ea740da3a90fde5b3b0011a375c2e4268"
@ -11275,6 +11365,13 @@ p-map@^3.0.0:
dependencies: dependencies:
aggregate-error "^3.0.0" aggregate-error "^3.0.0"
p-map@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b"
integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==
dependencies:
aggregate-error "^3.0.0"
p-pipe@^1.1.0: p-pipe@^1.1.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9"
@ -11749,6 +11846,13 @@ pkg-up@^2.0.0:
dependencies: dependencies:
find-up "^2.1.0" find-up "^2.1.0"
please-upgrade-node@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==
dependencies:
semver-compare "^1.0.0"
pngjs@^3.0.0, pngjs@^3.3.3: pngjs@^3.0.0, pngjs@^3.3.3:
version "3.4.0" version "3.4.0"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
@ -12221,7 +12325,7 @@ prepend-http@^2.0.0:
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
prettier@2.0.5, prettier@^2.0.5: prettier@^2.0.5:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4"
integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==
@ -13413,7 +13517,7 @@ rx-lite@*, rx-lite@^4.0.8:
resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444"
integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=
rxjs@^6.5.3: rxjs@^6.5.3, rxjs@^6.5.5:
version "6.5.5" version "6.5.5"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.5.tgz#c5c884e3094c8cfee31bf27eb87e54ccfc87f9ec"
integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ== integrity sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==
@ -13541,6 +13645,11 @@ selfsigned@^1.10.7:
dependencies: dependencies:
node-forge "0.9.0" node-forge "0.9.0"
semver-compare@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w=
semver-diff@^2.0.0: semver-diff@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36"
@ -13833,6 +13942,15 @@ slice-ansi@^3.0.0:
astral-regex "^2.0.0" astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0" is-fullwidth-code-point "^3.0.0"
slice-ansi@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b"
integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==
dependencies:
ansi-styles "^4.0.0"
astral-regex "^2.0.0"
is-fullwidth-code-point "^3.0.0"
slugify@^1.4.0: slugify@^1.4.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.0.tgz#c9557c653c54b0c7f7a8e786ef3431add676d2cb" resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.4.0.tgz#c9557c653c54b0c7f7a8e786ef3431add676d2cb"
@ -14273,6 +14391,11 @@ strict-uri-encode@^2.0.0:
resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY= integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
string-argv@0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"
integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==
string-length@^3.1.0: string-length@^3.1.0:
version "3.1.0" version "3.1.0"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837" resolved "https://registry.yarnpkg.com/string-length/-/string-length-3.1.0.tgz#107ef8c23456e187a8abd4a61162ff4ac6e25837"