use spaces over tabs
This commit is contained in:
parent
952776c608
commit
0265353bd3
14
.prettierrc
14
.prettierrc
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"endOfLine": "lf",
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"useTabs": true,
|
||||
"trailingComma": "es5",
|
||||
"arrowParens": "avoid"
|
||||
"endOfLine": "lf",
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"trailingComma": "es5",
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
|
|
@ -3,84 +3,84 @@ import React from 'react';
|
|||
import { MDXProvider } from '@mdx-js/react';
|
||||
|
||||
const SpoilerComponent = ({ children, title }) => {
|
||||
const [show, setShow] = React.useState(false);
|
||||
const [show, setShow] = React.useState(false);
|
||||
|
||||
return (
|
||||
<div className={`border border-gray-200 rounded-md`}>
|
||||
<p
|
||||
className="p-4 flex items-start"
|
||||
onClick={e => setShow(!show)}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
{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>
|
||||
return (
|
||||
<div className={`border border-gray-200 rounded-md`}>
|
||||
<p
|
||||
className="p-4 flex items-start"
|
||||
onClick={e => setShow(!show)}
|
||||
style={{ marginBottom: 0 }}
|
||||
>
|
||||
{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>}
|
||||
</div>
|
||||
);
|
||||
{show && <div className="p-4 pt-0 spoiler-body">{children}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const components = {
|
||||
wrapper: ({ excerptOnly = false, children }) => {
|
||||
if (excerptOnly) {
|
||||
for (let child of children) {
|
||||
if (child.props.originalType === 'module-excerpt') return child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
wrapper: ({ excerptOnly = false, children }) => {
|
||||
if (excerptOnly) {
|
||||
for (let child of children) {
|
||||
if (child.props.originalType === 'module-excerpt') return child;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
return children;
|
||||
},
|
||||
'module-excerpt': props => <div {...props} />,
|
||||
spoiler: SpoilerComponent,
|
||||
'info-block': ({ children }) => (
|
||||
<div className="rounded-md bg-blue-50 p-4 info-block mb-4">
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<svg
|
||||
className="h-5 w-5 text-blue-400"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<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">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
return children;
|
||||
},
|
||||
'module-excerpt': props => <div {...props} />,
|
||||
spoiler: SpoilerComponent,
|
||||
'info-block': ({ children }) => (
|
||||
<div className="rounded-md bg-blue-50 p-4 info-block mb-4">
|
||||
<div className="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<svg
|
||||
className="h-5 w-5 text-blue-400"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<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">{children}</div>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
};
|
||||
|
||||
export const wrapRootElement = ({ element }) => (
|
||||
<MDXProvider components={components}>{element}</MDXProvider>
|
||||
<MDXProvider components={components}>{element}</MDXProvider>
|
||||
);
|
||||
|
|
156
gatsby-config.js
156
gatsby-config.js
|
@ -4,82 +4,82 @@ const tailwindConfig = require('./tailwind.config.js');
|
|||
const fullConfig = resolveConfig(tailwindConfig);
|
||||
|
||||
module.exports = {
|
||||
siteMetadata: {
|
||||
title: `USACO Guide`,
|
||||
description: `A collection of curated, high-quality resources to take you from Bronze to Platinum.`,
|
||||
author: `@usacoteam`,
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/content`,
|
||||
name: `content`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-plugin-mdx`,
|
||||
options: {
|
||||
extensions: [`.mdx`, `.md`],
|
||||
gatsbyRemarkPlugins: [
|
||||
`gatsby-remark-autolink-headers`,
|
||||
{
|
||||
resolve: 'gatsby-remark-custom-blocks',
|
||||
options: {
|
||||
blocks: {
|
||||
info: {
|
||||
containerElement: 'info-block',
|
||||
title: 'optional',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-katex`,
|
||||
options: {
|
||||
// Add any KaTeX options from https://github.com/KaTeX/KaTeX/blob/master/docs/options.md here
|
||||
strict: `ignore`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-prismjs`,
|
||||
options: {
|
||||
noInlineHighlight: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
plugins: [`gatsby-remark-autolink-headers`],
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-plugin-postcss`,
|
||||
options: {
|
||||
postCssPlugins: [
|
||||
require(`tailwindcss`)(tailwindConfig),
|
||||
require(`autoprefixer`),
|
||||
...(process.env.NODE_ENV === `production`
|
||||
? [require(`cssnano`)]
|
||||
: []),
|
||||
],
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-react-helmet`,
|
||||
`gatsby-transformer-sharp`,
|
||||
`gatsby-plugin-sharp`,
|
||||
// {
|
||||
// resolve: `gatsby-plugin-manifest`,
|
||||
// options: {
|
||||
// name: `gatsby-starter-default`,
|
||||
// short_name: `starter`,
|
||||
// start_url: `/`,
|
||||
// background_color: `#663399`,
|
||||
// theme_color: `#663399`,
|
||||
// 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
|
||||
// `gatsby-plugin-offline`,
|
||||
],
|
||||
siteMetadata: {
|
||||
title: `USACO Guide`,
|
||||
description: `A collection of curated, high-quality resources to take you from Bronze to Platinum.`,
|
||||
author: `@usacoteam`,
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
resolve: `gatsby-source-filesystem`,
|
||||
options: {
|
||||
path: `${__dirname}/content`,
|
||||
name: `content`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-plugin-mdx`,
|
||||
options: {
|
||||
extensions: [`.mdx`, `.md`],
|
||||
gatsbyRemarkPlugins: [
|
||||
`gatsby-remark-autolink-headers`,
|
||||
{
|
||||
resolve: 'gatsby-remark-custom-blocks',
|
||||
options: {
|
||||
blocks: {
|
||||
info: {
|
||||
containerElement: 'info-block',
|
||||
title: 'optional',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-katex`,
|
||||
options: {
|
||||
// Add any KaTeX options from https://github.com/KaTeX/KaTeX/blob/master/docs/options.md here
|
||||
strict: `ignore`,
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-remark-prismjs`,
|
||||
options: {
|
||||
noInlineHighlight: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
plugins: [`gatsby-remark-autolink-headers`],
|
||||
},
|
||||
},
|
||||
{
|
||||
resolve: `gatsby-plugin-postcss`,
|
||||
options: {
|
||||
postCssPlugins: [
|
||||
require(`tailwindcss`)(tailwindConfig),
|
||||
require(`autoprefixer`),
|
||||
...(process.env.NODE_ENV === `production`
|
||||
? [require(`cssnano`)]
|
||||
: []),
|
||||
],
|
||||
},
|
||||
},
|
||||
`gatsby-plugin-react-helmet`,
|
||||
`gatsby-transformer-sharp`,
|
||||
`gatsby-plugin-sharp`,
|
||||
// {
|
||||
// resolve: `gatsby-plugin-manifest`,
|
||||
// options: {
|
||||
// name: `gatsby-starter-default`,
|
||||
// short_name: `starter`,
|
||||
// start_url: `/`,
|
||||
// background_color: `#663399`,
|
||||
// theme_color: `#663399`,
|
||||
// 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
|
||||
// `gatsby-plugin-offline`,
|
||||
],
|
||||
};
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
import ModuleOrdering, { divisions } from './content/ordering';
|
||||
|
||||
exports.createPages = async ({ actions, graphql, reporter }) => {
|
||||
const { createPage } = actions;
|
||||
const { createPage } = actions;
|
||||
|
||||
// Generate Module Pages //
|
||||
const moduleTemplate = require.resolve(`./src/templates/moduleTemplate.tsx`);
|
||||
Object.keys(ModuleOrdering).forEach(division => {
|
||||
const processItem = item => {
|
||||
if (typeof item === 'object') {
|
||||
// this is a nested module
|
||||
item.items.forEach(x => processItem(x));
|
||||
} else {
|
||||
createPage({
|
||||
path: `/${division}/${item}`,
|
||||
component: moduleTemplate,
|
||||
context: {
|
||||
// additional data can be passed via context
|
||||
id: item,
|
||||
division: division,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
ModuleOrdering[division].forEach(item => processItem(item));
|
||||
});
|
||||
// End Generate Module Pages //
|
||||
// Generate Module Pages //
|
||||
const moduleTemplate = require.resolve(`./src/templates/moduleTemplate.tsx`);
|
||||
Object.keys(ModuleOrdering).forEach(division => {
|
||||
const processItem = item => {
|
||||
if (typeof item === 'object') {
|
||||
// this is a nested module
|
||||
item.items.forEach(x => processItem(x));
|
||||
} else {
|
||||
createPage({
|
||||
path: `/${division}/${item}`,
|
||||
component: moduleTemplate,
|
||||
context: {
|
||||
// additional data can be passed via context
|
||||
id: item,
|
||||
division: division,
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
ModuleOrdering[division].forEach(item => processItem(item));
|
||||
});
|
||||
// End Generate Module Pages //
|
||||
|
||||
// Generate Syllabus Pages //
|
||||
const syllabusTemplate = require.resolve(
|
||||
`./src/templates/syllabusTemplate.js`
|
||||
);
|
||||
divisions.forEach(division => {
|
||||
createPage({
|
||||
path: `/${division}`,
|
||||
component: syllabusTemplate,
|
||||
context: {
|
||||
division: division,
|
||||
},
|
||||
});
|
||||
});
|
||||
// End Generate Syllabus Pages //
|
||||
// Generate Syllabus Pages //
|
||||
const syllabusTemplate = require.resolve(
|
||||
`./src/templates/syllabusTemplate.js`
|
||||
);
|
||||
divisions.forEach(division => {
|
||||
createPage({
|
||||
path: `/${division}`,
|
||||
component: syllabusTemplate,
|
||||
context: {
|
||||
division: division,
|
||||
},
|
||||
});
|
||||
});
|
||||
// End Generate Syllabus Pages //
|
||||
};
|
||||
|
||||
exports.createSchemaCustomization = ({ actions }) => {
|
||||
const { createTypes } = actions;
|
||||
const typeDefs = `
|
||||
const { createTypes } = actions;
|
||||
const typeDefs = `
|
||||
type MarkdownRemarkFrontmatter implements Node {
|
||||
prerequisites: [[String]]
|
||||
}
|
||||
`;
|
||||
createTypes(typeDefs);
|
||||
createTypes(typeDefs);
|
||||
};
|
||||
|
|
|
@ -6,11 +6,11 @@ import '../styles/prism-theme.css';
|
|||
import { MDXRenderer } from 'gatsby-plugin-mdx';
|
||||
|
||||
const Markdown = ({ body, className, excerptOnly = false }) => {
|
||||
return (
|
||||
<div className={`markdown ${className}`}>
|
||||
<MDXRenderer excerptOnly={excerptOnly}>{body}</MDXRenderer>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className={`markdown ${className}`}>
|
||||
<MDXRenderer excerptOnly={excerptOnly}>{body}</MDXRenderer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Markdown;
|
||||
|
|
|
@ -2,118 +2,118 @@ import React from 'react';
|
|||
import { Link } from 'gatsby';
|
||||
|
||||
const CompletedCheck = () => (
|
||||
<svg
|
||||
className="h-6 w-6 mr-2 text-green-500"
|
||||
fill="currentColor"
|
||||
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>
|
||||
<svg
|
||||
className="h-6 w-6 mr-2 text-green-500"
|
||||
fill="currentColor"
|
||||
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"
|
||||
>
|
||||
<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>
|
||||
<svg
|
||||
className="h-6 w-6 mr-2 text-gray-200"
|
||||
fill="currentColor"
|
||||
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) => {
|
||||
return (
|
||||
<li className="flex items-center" key={problem}>
|
||||
{idx > 0 ? <IncompleteCheck /> : <CompletedCheck />}
|
||||
{/* todo make url legit */}
|
||||
<a className="text-blue-600" href="https://google.com/">
|
||||
{problem}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
return (
|
||||
<li className="flex items-center" key={problem}>
|
||||
{idx > 0 ? <IncompleteCheck /> : <CompletedCheck />}
|
||||
{/* todo make url legit */}
|
||||
<a className="text-blue-600" href="https://google.com/">
|
||||
{problem}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const renderPrerequisite = prerequisite => {
|
||||
const link = prerequisite.length > 1 ? prerequisite[1] : null;
|
||||
return (
|
||||
<li key={prerequisite[0]}>
|
||||
{link && (
|
||||
<a href={link} className="text-blue-600">
|
||||
{prerequisite[0]}
|
||||
</a>
|
||||
)}
|
||||
{!link && prerequisite[0]}
|
||||
</li>
|
||||
);
|
||||
const link = prerequisite.length > 1 ? prerequisite[1] : null;
|
||||
return (
|
||||
<li key={prerequisite[0]}>
|
||||
{link && (
|
||||
<a href={link} className="text-blue-600">
|
||||
{prerequisite[0]}
|
||||
</a>
|
||||
)}
|
||||
{!link && prerequisite[0]}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const SyllabusModule = ({
|
||||
title,
|
||||
children,
|
||||
author,
|
||||
problems,
|
||||
prerequisites,
|
||||
url,
|
||||
title,
|
||||
children,
|
||||
author,
|
||||
problems,
|
||||
prerequisites,
|
||||
url,
|
||||
}) => {
|
||||
// in the future, fetch this data either from localStorage or from server.
|
||||
const isComplete = title === 'Prerequisites' || title === 'Getting Started';
|
||||
// in the future, fetch this data either from localStorage or from server.
|
||||
const isComplete = title === 'Prerequisites' || title === 'Getting Started';
|
||||
|
||||
return (
|
||||
<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">
|
||||
<h2 className="font-bold text-xl mr-2">{title}</h2>
|
||||
{isComplete && (
|
||||
<svg
|
||||
className="h-8 w-8 text-green-500"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</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}
|
||||
return (
|
||||
<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">
|
||||
<h2 className="font-bold text-xl mr-2">{title}</h2>
|
||||
{isComplete && (
|
||||
<svg
|
||||
className="h-8 w-8 text-green-500"
|
||||
fill="none"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
)}
|
||||
</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>}
|
||||
</div>
|
||||
<Link
|
||||
to={url || '/'}
|
||||
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"
|
||||
>
|
||||
View Module
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
{author && <p className="mt-2">Author: {author}</p>}
|
||||
</div>
|
||||
<Link
|
||||
to={url || '/'}
|
||||
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"
|
||||
>
|
||||
View Module
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default SyllabusModule;
|
||||
|
|
|
@ -3,108 +3,108 @@ import * as React from 'react';
|
|||
import { useRef, useEffect, useContext } from 'react';
|
||||
|
||||
const TransitionContext = React.createContext({
|
||||
parent: {},
|
||||
parent: {},
|
||||
});
|
||||
|
||||
function useIsInitialRender() {
|
||||
const isInitialRender = useRef(true);
|
||||
useEffect(() => {
|
||||
isInitialRender.current = false;
|
||||
}, []);
|
||||
return isInitialRender.current;
|
||||
const isInitialRender = useRef(true);
|
||||
useEffect(() => {
|
||||
isInitialRender.current = false;
|
||||
}, []);
|
||||
return isInitialRender.current;
|
||||
}
|
||||
|
||||
function CSSTransition({
|
||||
show,
|
||||
enter = '',
|
||||
enterFrom = '',
|
||||
enterTo = '',
|
||||
leave = '',
|
||||
leaveFrom = '',
|
||||
leaveTo = '',
|
||||
appear,
|
||||
children,
|
||||
show,
|
||||
enter = '',
|
||||
enterFrom = '',
|
||||
enterTo = '',
|
||||
leave = '',
|
||||
leaveFrom = '',
|
||||
leaveTo = '',
|
||||
appear,
|
||||
children,
|
||||
}) {
|
||||
const enterClasses = enter.split(' ').filter(s => s.length);
|
||||
const enterFromClasses = enterFrom.split(' ').filter(s => s.length);
|
||||
const enterToClasses = enterTo.split(' ').filter(s => s.length);
|
||||
const leaveClasses = leave.split(' ').filter(s => s.length);
|
||||
const leaveFromClasses = leaveFrom.split(' ').filter(s => s.length);
|
||||
const leaveToClasses = leaveTo.split(' ').filter(s => s.length);
|
||||
const enterClasses = enter.split(' ').filter(s => s.length);
|
||||
const enterFromClasses = enterFrom.split(' ').filter(s => s.length);
|
||||
const enterToClasses = enterTo.split(' ').filter(s => s.length);
|
||||
const leaveClasses = leave.split(' ').filter(s => s.length);
|
||||
const leaveFromClasses = leaveFrom.split(' ').filter(s => s.length);
|
||||
const leaveToClasses = leaveTo.split(' ').filter(s => s.length);
|
||||
|
||||
function addClasses(node, classes) {
|
||||
classes.length && node.classList.add(...classes);
|
||||
}
|
||||
function addClasses(node, classes) {
|
||||
classes.length && node.classList.add(...classes);
|
||||
}
|
||||
|
||||
function removeClasses(node, classes) {
|
||||
classes.length && node.classList.remove(...classes);
|
||||
}
|
||||
function removeClasses(node, classes) {
|
||||
classes.length && node.classList.remove(...classes);
|
||||
}
|
||||
|
||||
return (
|
||||
<ReactCSSTransition
|
||||
appear={appear}
|
||||
unmountOnExit
|
||||
in={show}
|
||||
addEndListener={(node, done) => {
|
||||
node.addEventListener('transitionend', done, false);
|
||||
}}
|
||||
onEnter={node => {
|
||||
addClasses(node, [...enterClasses, ...enterFromClasses]);
|
||||
}}
|
||||
onEntering={node => {
|
||||
removeClasses(node, enterFromClasses);
|
||||
addClasses(node, enterToClasses);
|
||||
}}
|
||||
onEntered={node => {
|
||||
removeClasses(node, [...enterToClasses, ...enterClasses]);
|
||||
}}
|
||||
onExit={node => {
|
||||
addClasses(node, [...leaveClasses, ...leaveFromClasses]);
|
||||
}}
|
||||
onExiting={node => {
|
||||
removeClasses(node, leaveFromClasses);
|
||||
addClasses(node, leaveToClasses);
|
||||
}}
|
||||
onExited={node => {
|
||||
removeClasses(node, [...leaveToClasses, ...leaveClasses]);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ReactCSSTransition>
|
||||
);
|
||||
return (
|
||||
<ReactCSSTransition
|
||||
appear={appear}
|
||||
unmountOnExit
|
||||
in={show}
|
||||
addEndListener={(node, done) => {
|
||||
node.addEventListener('transitionend', done, false);
|
||||
}}
|
||||
onEnter={node => {
|
||||
addClasses(node, [...enterClasses, ...enterFromClasses]);
|
||||
}}
|
||||
onEntering={node => {
|
||||
removeClasses(node, enterFromClasses);
|
||||
addClasses(node, enterToClasses);
|
||||
}}
|
||||
onEntered={node => {
|
||||
removeClasses(node, [...enterToClasses, ...enterClasses]);
|
||||
}}
|
||||
onExit={node => {
|
||||
addClasses(node, [...leaveClasses, ...leaveFromClasses]);
|
||||
}}
|
||||
onExiting={node => {
|
||||
removeClasses(node, leaveFromClasses);
|
||||
addClasses(node, leaveToClasses);
|
||||
}}
|
||||
onExited={node => {
|
||||
removeClasses(node, [...leaveToClasses, ...leaveClasses]);
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</ReactCSSTransition>
|
||||
);
|
||||
}
|
||||
|
||||
function Transition({ show, appear, ...rest }: any) {
|
||||
const { parent }: { parent: any } = useContext(TransitionContext);
|
||||
const isInitialRender = useIsInitialRender();
|
||||
const isChild = show === undefined;
|
||||
const { parent }: { parent: any } = useContext(TransitionContext);
|
||||
const isInitialRender = useIsInitialRender();
|
||||
const isChild = show === undefined;
|
||||
|
||||
if (isChild) {
|
||||
return (
|
||||
// @ts-ignore
|
||||
<CSSTransition
|
||||
appear={parent.appear || !parent.isInitialRender}
|
||||
show={parent.show}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
if (isChild) {
|
||||
return (
|
||||
// @ts-ignore
|
||||
<CSSTransition
|
||||
appear={parent.appear || !parent.isInitialRender}
|
||||
show={parent.show}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TransitionContext.Provider
|
||||
value={{
|
||||
parent: {
|
||||
show,
|
||||
isInitialRender,
|
||||
appear,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
return (
|
||||
<TransitionContext.Provider
|
||||
value={{
|
||||
parent: {
|
||||
show,
|
||||
isInitialRender,
|
||||
appear,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{/*
|
||||
// @ts-ignore*/}
|
||||
<CSSTransition appear={appear} show={show} {...rest} />
|
||||
</TransitionContext.Provider>
|
||||
);
|
||||
<CSSTransition appear={appear} show={show} {...rest} />
|
||||
</TransitionContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export default Transition;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import * as React from 'react';
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
return <>{children}</>;
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
export default Layout;
|
||||
|
|
|
@ -11,78 +11,78 @@ import { Helmet } from 'react-helmet';
|
|||
import { useStaticQuery, graphql } from 'gatsby';
|
||||
|
||||
function SEO({ description, lang, meta, title }) {
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
description
|
||||
author
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
const { site } = useStaticQuery(
|
||||
graphql`
|
||||
query {
|
||||
site {
|
||||
siteMetadata {
|
||||
title
|
||||
description
|
||||
author
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
const metaDescription = description || site.siteMetadata.description;
|
||||
const metaDescription = description || site.siteMetadata.description;
|
||||
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={title}
|
||||
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: `description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: `og:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:type`,
|
||||
content: `website`,
|
||||
},
|
||||
{
|
||||
name: `twitter:card`,
|
||||
content: `summary`,
|
||||
},
|
||||
{
|
||||
name: `twitter:creator`,
|
||||
content: site.siteMetadata.author,
|
||||
},
|
||||
{
|
||||
name: `twitter:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: `twitter:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
].concat(meta)}
|
||||
/>
|
||||
);
|
||||
return (
|
||||
<Helmet
|
||||
htmlAttributes={{
|
||||
lang,
|
||||
}}
|
||||
title={title}
|
||||
titleTemplate={`%s | ${site.siteMetadata.title}`}
|
||||
meta={[
|
||||
{
|
||||
name: `description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
property: `og:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
{
|
||||
property: `og:type`,
|
||||
content: `website`,
|
||||
},
|
||||
{
|
||||
name: `twitter:card`,
|
||||
content: `summary`,
|
||||
},
|
||||
{
|
||||
name: `twitter:creator`,
|
||||
content: site.siteMetadata.author,
|
||||
},
|
||||
{
|
||||
name: `twitter:title`,
|
||||
content: title,
|
||||
},
|
||||
{
|
||||
name: `twitter:description`,
|
||||
content: metaDescription,
|
||||
},
|
||||
].concat(meta)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
SEO.defaultProps = {
|
||||
lang: `en`,
|
||||
meta: [],
|
||||
description: ``,
|
||||
lang: `en`,
|
||||
meta: [],
|
||||
description: ``,
|
||||
};
|
||||
|
||||
SEO.propTypes = {
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
description: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
meta: PropTypes.arrayOf(PropTypes.object),
|
||||
title: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default SEO;
|
||||
|
|
56
src/html.js
56
src/html.js
|
@ -2,35 +2,35 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
export default function HTML(props) {
|
||||
return (
|
||||
<html {...props.htmlAttributes}>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
{props.headComponents}
|
||||
</head>
|
||||
<body {...props.bodyAttributes}>
|
||||
{props.preBodyComponents}
|
||||
<div
|
||||
key={`body`}
|
||||
id="___gatsby"
|
||||
dangerouslySetInnerHTML={{ __html: props.body }}
|
||||
/>
|
||||
{props.postBodyComponents}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
return (
|
||||
<html {...props.htmlAttributes}>
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
{props.headComponents}
|
||||
</head>
|
||||
<body {...props.bodyAttributes}>
|
||||
{props.preBodyComponents}
|
||||
<div
|
||||
key={`body`}
|
||||
id="___gatsby"
|
||||
dangerouslySetInnerHTML={{ __html: props.body }}
|
||||
/>
|
||||
{props.postBodyComponents}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
HTML.propTypes = {
|
||||
htmlAttributes: PropTypes.object,
|
||||
headComponents: PropTypes.array,
|
||||
bodyAttributes: PropTypes.object,
|
||||
preBodyComponents: PropTypes.array,
|
||||
body: PropTypes.string,
|
||||
postBodyComponents: PropTypes.array,
|
||||
htmlAttributes: PropTypes.object,
|
||||
headComponents: PropTypes.array,
|
||||
bodyAttributes: PropTypes.object,
|
||||
preBodyComponents: PropTypes.array,
|
||||
body: PropTypes.string,
|
||||
postBodyComponents: PropTypes.array,
|
||||
};
|
||||
|
|
|
@ -4,448 +4,448 @@ import Layout from '../components/layout';
|
|||
import SEO from '../components/seo';
|
||||
|
||||
export default function IndexPage(props: PageProps) {
|
||||
return (
|
||||
<Layout>
|
||||
<SEO title="" />
|
||||
return (
|
||||
<Layout>
|
||||
<SEO title="" />
|
||||
|
||||
{/* Begin Hero */}
|
||||
<div className="relative bg-white overflow-hidden">
|
||||
<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"
|
||||
fill="none"
|
||||
viewBox="0 0 640 784"
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id="9ebea6f4-a1f5-4d96-8c4e-4c2abf658047"
|
||||
x="118"
|
||||
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>
|
||||
{/* Begin Hero */}
|
||||
<div className="relative bg-white overflow-hidden">
|
||||
<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"
|
||||
fill="none"
|
||||
viewBox="0 0 640 784"
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id="9ebea6f4-a1f5-4d96-8c4e-4c2abf658047"
|
||||
x="118"
|
||||
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' }}
|
||||
>
|
||||
<main className="mt-8 mx-auto max-w-6xl px-4 sm:mt-12 sm:px-6 md:mt-20 xl:mt-24">
|
||||
<div className="lg:grid lg:grid-cols-12 lg:gap-8">
|
||||
<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 className="text-sm font-semibold uppercase tracking-wide text-gray-500 sm:text-base lg:text-sm xl:text-base">
|
||||
Pre-Release
|
||||
</div>
|
||||
<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">
|
||||
USACO <span className="text-blue-600">Guide</span>
|
||||
</h2>
|
||||
<p className="mt-3 text-base text-gray-500 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
|
||||
A free collection of <b>curated, high-quality resources</b> to
|
||||
take you from Bronze to Platinum and beyond.
|
||||
</p>
|
||||
<div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start">
|
||||
<div className="rounded-md shadow">
|
||||
<Link
|
||||
to="/intro"
|
||||
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"
|
||||
>
|
||||
View Guide
|
||||
</Link>
|
||||
</div>
|
||||
<div className="mt-3 sm:mt-0 sm:ml-3">
|
||||
<a
|
||||
href="#learn-more"
|
||||
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"
|
||||
>
|
||||
Learn More
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<svg
|
||||
className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-8 scale-75 origin-top sm:scale-100 lg:hidden"
|
||||
width="640"
|
||||
height="784"
|
||||
fill="none"
|
||||
viewBox="0 0 640 784"
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id="4f4f415c-a0e9-44c2-9601-6ded5a34a13e"
|
||||
x="118"
|
||||
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(#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="relative pt-6 pb-16 md:pb-20 lg:pb-24 xl:pb-32 border-blue-600"
|
||||
style={{ borderTopWidth: '12px' }}
|
||||
>
|
||||
<main className="mt-8 mx-auto max-w-6xl px-4 sm:mt-12 sm:px-6 md:mt-20 xl:mt-24">
|
||||
<div className="lg:grid lg:grid-cols-12 lg:gap-8">
|
||||
<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 className="text-sm font-semibold uppercase tracking-wide text-gray-500 sm:text-base lg:text-sm xl:text-base">
|
||||
Pre-Release
|
||||
</div>
|
||||
<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">
|
||||
USACO <span className="text-blue-600">Guide</span>
|
||||
</h2>
|
||||
<p className="mt-3 text-base text-gray-500 sm:mt-5 sm:text-xl lg:text-lg xl:text-xl">
|
||||
A free collection of <b>curated, high-quality resources</b> to
|
||||
take you from Bronze to Platinum and beyond.
|
||||
</p>
|
||||
<div className="mt-5 sm:mt-8 sm:flex sm:justify-center lg:justify-start">
|
||||
<div className="rounded-md shadow">
|
||||
<Link
|
||||
to="/intro"
|
||||
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"
|
||||
>
|
||||
View Guide
|
||||
</Link>
|
||||
</div>
|
||||
<div className="mt-3 sm:mt-0 sm:ml-3">
|
||||
<a
|
||||
href="#learn-more"
|
||||
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"
|
||||
>
|
||||
Learn More
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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">
|
||||
<svg
|
||||
className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-8 scale-75 origin-top sm:scale-100 lg:hidden"
|
||||
width="640"
|
||||
height="784"
|
||||
fill="none"
|
||||
viewBox="0 0 640 784"
|
||||
>
|
||||
<defs>
|
||||
<pattern
|
||||
id="4f4f415c-a0e9-44c2-9601-6ded5a34a13e"
|
||||
x="118"
|
||||
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(#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="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="lg:text-center">
|
||||
<p className="text-base leading-6 text-blue-600 font-semibold tracking-wide uppercase">
|
||||
About This Guide
|
||||
</p>
|
||||
<h3 className="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10">
|
||||
Not Just Another Resource.
|
||||
</h3>
|
||||
<p className="mt-4 max-w-4xl text-xl leading-7 text-gray-500 lg:mx-auto">
|
||||
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="py-12 bg-white" id="learn-more">
|
||||
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="lg:text-center">
|
||||
<p className="text-base leading-6 text-blue-600 font-semibold tracking-wide uppercase">
|
||||
About This Guide
|
||||
</p>
|
||||
<h3 className="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10">
|
||||
Not Just Another Resource.
|
||||
</h3>
|
||||
<p className="mt-4 max-w-4xl text-xl leading-7 text-gray-500 lg:mx-auto">
|
||||
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="flex">
|
||||
<div className="flex-shrink-0">
|
||||
<svg
|
||||
className="h-5 w-5 text-yellow-400"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<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"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="ml-3 flex-1 md:flex md:justify-between">
|
||||
<p className="text-sm leading-5 text-yellow-700 text-left">
|
||||
This guide is not a syllabus. Topics on this guide reflect{' '}
|
||||
<i>past</i> problems, not future problems.
|
||||
</p>
|
||||
<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 →
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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-shrink-0">
|
||||
<svg
|
||||
className="h-5 w-5 text-yellow-400"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
>
|
||||
<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"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="ml-3 flex-1 md:flex md:justify-between">
|
||||
<p className="text-sm leading-5 text-yellow-700 text-left">
|
||||
This guide is not a syllabus. Topics on this guide reflect{' '}
|
||||
<i>past</i> problems, not future problems.
|
||||
</p>
|
||||
<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 →
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-16">
|
||||
<ul className="md:grid md:grid-cols-2 md:col-gap-8 md:row-gap-10">
|
||||
<li>
|
||||
<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"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
<h4 className="text-lg leading-6 font-medium text-gray-900">
|
||||
Experienced Authors
|
||||
</h4>
|
||||
<p className="mt-2 text-base leading-6 text-gray-500">
|
||||
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>
|
||||
.
|
||||
</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"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
<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">
|
||||
This guide is targeted towards all contestants, regardless
|
||||
of their division. You'll find problems suitable for you.
|
||||
</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"
|
||||
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="mt-16">
|
||||
<ul className="md:grid md:grid-cols-2 md:col-gap-8 md:row-gap-10">
|
||||
<li>
|
||||
<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"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
<h4 className="text-lg leading-6 font-medium text-gray-900">
|
||||
Experienced Authors
|
||||
</h4>
|
||||
<p className="mt-2 text-base leading-6 text-gray-500">
|
||||
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>
|
||||
.
|
||||
</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"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth="2"
|
||||
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"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-4">
|
||||
<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">
|
||||
This guide is targeted towards all contestants, regardless
|
||||
of their division. You'll find problems suitable for you.
|
||||
</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"
|
||||
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="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">
|
||||
Unsure how to get started?
|
||||
<br />
|
||||
Overwhelmed by too many resources?
|
||||
<br />
|
||||
Looking to take your CP skills to the next level?
|
||||
<br />
|
||||
</p>
|
||||
<div className="bg-blue-900">
|
||||
<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">
|
||||
Unsure how to get started?
|
||||
<br />
|
||||
Overwhelmed by too many resources?
|
||||
<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="rounded-md shadow">
|
||||
<Link
|
||||
to="/intro"
|
||||
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"
|
||||
>
|
||||
View Guide
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-8 flex justify-center">
|
||||
<div className="rounded-md shadow">
|
||||
<Link
|
||||
to="/intro"
|
||||
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"
|
||||
>
|
||||
View Guide
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Begin FAQ */}
|
||||
<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">
|
||||
<h2 className="text-3xl leading-9 font-extrabold text-gray-900">
|
||||
Frequently asked questions
|
||||
</h2>
|
||||
<div className="mt-6 border-t-2 border-gray-100 pt-10">
|
||||
<dl className="md:grid md:grid-cols-2 md:gap-8">
|
||||
<div>
|
||||
<div>
|
||||
<dt className="text-lg leading-6 font-medium text-gray-900">
|
||||
Is this a Syllabus?
|
||||
</dt>
|
||||
<dd className="mt-2">
|
||||
<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.
|
||||
</p>
|
||||
</dd>
|
||||
</div>
|
||||
<div className="mt-12">
|
||||
<dt className="text-lg leading-6 font-medium text-gray-900">
|
||||
How can I contribute/report a problem?
|
||||
</dt>
|
||||
<dd className="mt-2">
|
||||
<p className="text-base leading-6 text-gray-500">
|
||||
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>
|
||||
.
|
||||
</p>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-12 md:mt-0">
|
||||
<div>
|
||||
<dt className="text-lg leading-6 font-medium text-gray-900">
|
||||
Is this guide for Platinum contestants?
|
||||
</dt>
|
||||
<dd className="mt-2">
|
||||
<p className="text-base leading-6 text-gray-500">
|
||||
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>
|
||||
</dd>
|
||||
</div>
|
||||
<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>
|
||||
);
|
||||
{/* Begin FAQ */}
|
||||
<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">
|
||||
<h2 className="text-3xl leading-9 font-extrabold text-gray-900">
|
||||
Frequently asked questions
|
||||
</h2>
|
||||
<div className="mt-6 border-t-2 border-gray-100 pt-10">
|
||||
<dl className="md:grid md:grid-cols-2 md:gap-8">
|
||||
<div>
|
||||
<div>
|
||||
<dt className="text-lg leading-6 font-medium text-gray-900">
|
||||
Is this a Syllabus?
|
||||
</dt>
|
||||
<dd className="mt-2">
|
||||
<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.
|
||||
</p>
|
||||
</dd>
|
||||
</div>
|
||||
<div className="mt-12">
|
||||
<dt className="text-lg leading-6 font-medium text-gray-900">
|
||||
How can I contribute/report a problem?
|
||||
</dt>
|
||||
<dd className="mt-2">
|
||||
<p className="text-base leading-6 text-gray-500">
|
||||
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>
|
||||
.
|
||||
</p>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-12 md:mt-0">
|
||||
<div>
|
||||
<dt className="text-lg leading-6 font-medium text-gray-900">
|
||||
Is this guide for Platinum contestants?
|
||||
</dt>
|
||||
<dd className="mt-2">
|
||||
<p className="text-base leading-6 text-gray-500">
|
||||
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>
|
||||
</dd>
|
||||
</div>
|
||||
<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>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,155 +1,155 @@
|
|||
/*! purgecss start ignore */
|
||||
/* Additional vertical padding used by kbd tag. */
|
||||
.py-05 {
|
||||
padding-top: 0.125rem;
|
||||
padding-bottom: 0.125rem;
|
||||
padding-top: 0.125rem;
|
||||
padding-bottom: 0.125rem;
|
||||
}
|
||||
|
||||
.markdown {
|
||||
@apply text-gray-900 leading-normal break-words;
|
||||
@apply text-gray-900 leading-normal break-words;
|
||||
}
|
||||
|
||||
.markdown > * + * {
|
||||
@apply mt-0 mb-4;
|
||||
@apply mt-0 mb-4;
|
||||
}
|
||||
|
||||
.markdown li + li {
|
||||
@apply mt-1;
|
||||
@apply mt-1;
|
||||
}
|
||||
|
||||
.markdown li > p + p {
|
||||
@apply mt-6;
|
||||
@apply mt-6;
|
||||
}
|
||||
|
||||
.markdown strong {
|
||||
@apply font-semibold;
|
||||
@apply font-semibold;
|
||||
}
|
||||
|
||||
.markdown a {
|
||||
@apply text-blue-600 font-semibold;
|
||||
@apply text-blue-600 font-semibold;
|
||||
}
|
||||
|
||||
.markdown strong a {
|
||||
@apply font-bold;
|
||||
@apply font-bold;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@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 {
|
||||
@apply leading-snug text-lg font-semibold mb-4 mt-6;
|
||||
@apply leading-snug text-lg font-semibold mb-4 mt-6;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@apply leading-tight text-sm font-semibold mb-4 mt-6;
|
||||
@apply leading-tight text-sm font-semibold mb-4 mt-6;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@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-']) {
|
||||
@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 {
|
||||
@apply rounded;
|
||||
@apply rounded;
|
||||
}
|
||||
.markdown pre:not([class*='language-']) {
|
||||
@apply bg-gray-100 p-4;
|
||||
@apply bg-gray-100 p-4;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@apply text-base list-disc mb-4;
|
||||
@apply text-base list-disc mb-4;
|
||||
}
|
||||
|
||||
.markdown ul ul {
|
||||
list-style-type: circle;
|
||||
list-style-type: circle;
|
||||
}
|
||||
|
||||
.markdown ul ul ul {
|
||||
list-style-type: square;
|
||||
list-style-type: square;
|
||||
}
|
||||
|
||||
.markdown--module ul {
|
||||
@apply pl-8;
|
||||
@apply pl-8;
|
||||
}
|
||||
|
||||
.markdown--syllabus ul {
|
||||
@apply pl-5;
|
||||
@apply pl-5;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
@apply mb-4;
|
||||
@apply mb-4;
|
||||
}
|
||||
|
||||
.markdown ul ul {
|
||||
@apply mb-0;
|
||||
@apply mb-0;
|
||||
}
|
||||
|
||||
.markdown ul p {
|
||||
@apply mb-0;
|
||||
@apply mb-0;
|
||||
}
|
||||
|
||||
.markdown ol {
|
||||
@apply text-base pl-8 list-decimal mb-4;
|
||||
@apply text-base pl-8 list-decimal mb-4;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@apply text-base border-gray-600;
|
||||
@apply text-base border-gray-600;
|
||||
}
|
||||
|
||||
.markdown th {
|
||||
@apply border py-1 px-3;
|
||||
@apply border py-1 px-3;
|
||||
}
|
||||
|
||||
.markdown td {
|
||||
@apply border py-1 px-3;
|
||||
@apply border py-1 px-3;
|
||||
}
|
||||
|
||||
/* Override pygments style background color. */
|
||||
.markdown .highlight pre {
|
||||
@apply bg-gray-100 !important;
|
||||
@apply bg-gray-100 !important;
|
||||
}
|
||||
|
||||
.markdown--module .syllabus-only {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.spoiler-body pre {
|
||||
margin-left: -1rem !important;
|
||||
margin-right: -1rem !important;
|
||||
margin-bottom: -1rem !important;
|
||||
margin-left: -1rem !important;
|
||||
margin-right: -1rem !important;
|
||||
margin-bottom: -1rem !important;
|
||||
}
|
||||
|
||||
.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 {
|
||||
@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 {
|
||||
@apply mb-0;
|
||||
@apply mb-0;
|
||||
}
|
||||
/*! purgecss end ignore */
|
||||
|
|
|
@ -1,212 +1,212 @@
|
|||
/*! purgecss start ignore */
|
||||
code[class*='language-'],
|
||||
pre[class*='language-'] {
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
color: #c3cee3;
|
||||
background: #263238;
|
||||
font-family: Roboto Mono, monospace;
|
||||
font-size: 1em;
|
||||
line-height: 1.5em;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
color: #c3cee3;
|
||||
background: #263238;
|
||||
font-family: Roboto Mono, monospace;
|
||||
font-size: 1em;
|
||||
line-height: 1.5em;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
code[class*='language-']::-moz-selection,
|
||||
pre[class*='language-']::-moz-selection,
|
||||
code[class*='language-'] ::-moz-selection,
|
||||
pre[class*='language-'] ::-moz-selection {
|
||||
background: #363636;
|
||||
background: #363636;
|
||||
}
|
||||
|
||||
code[class*='language-']::selection,
|
||||
pre[class*='language-']::selection,
|
||||
code[class*='language-'] ::selection,
|
||||
pre[class*='language-'] ::selection {
|
||||
background: #363636;
|
||||
background: #363636;
|
||||
}
|
||||
|
||||
:not(pre) > code[class*='language-'] {
|
||||
white-space: normal;
|
||||
border-radius: 0.2em;
|
||||
padding: 0.1em;
|
||||
white-space: normal;
|
||||
border-radius: 0.2em;
|
||||
padding: 0.1em;
|
||||
}
|
||||
|
||||
pre[class*='language-'] {
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
margin: 0.5em 0;
|
||||
padding: 1.25em 1em;
|
||||
overflow: auto;
|
||||
position: relative;
|
||||
margin: 0.5em 0;
|
||||
padding: 1.25em 1em;
|
||||
}
|
||||
|
||||
.language-css > code,
|
||||
.language-sass > code,
|
||||
.language-scss > code {
|
||||
color: #fd9170;
|
||||
color: #fd9170;
|
||||
}
|
||||
|
||||
[class*='language-'] .namespace {
|
||||
opacity: 0.7;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.token.atrule {
|
||||
color: #c792ea;
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.attr-name {
|
||||
color: #ffcb6b;
|
||||
color: #ffcb6b;
|
||||
}
|
||||
|
||||
.token.attr-value {
|
||||
color: #c3e88d;
|
||||
color: #c3e88d;
|
||||
}
|
||||
|
||||
.token.attribute {
|
||||
color: #c3e88d;
|
||||
color: #c3e88d;
|
||||
}
|
||||
|
||||
.token.boolean {
|
||||
color: #c792ea;
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.builtin {
|
||||
color: #ffcb6b;
|
||||
color: #ffcb6b;
|
||||
}
|
||||
|
||||
.token.cdata {
|
||||
color: #80cbc4;
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.char {
|
||||
color: #80cbc4;
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.class {
|
||||
color: #ffcb6b;
|
||||
color: #ffcb6b;
|
||||
}
|
||||
|
||||
.token.class-name {
|
||||
color: #f2ff00;
|
||||
color: #f2ff00;
|
||||
}
|
||||
|
||||
.token.color {
|
||||
color: #f2ff00;
|
||||
color: #f2ff00;
|
||||
}
|
||||
|
||||
.token.comment {
|
||||
color: #546e7a;
|
||||
color: #546e7a;
|
||||
}
|
||||
|
||||
.token.constant {
|
||||
color: #c792ea;
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.deleted {
|
||||
color: #f07178;
|
||||
color: #f07178;
|
||||
}
|
||||
|
||||
.token.doctype {
|
||||
color: #546e7a;
|
||||
color: #546e7a;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
color: #f07178;
|
||||
color: #f07178;
|
||||
}
|
||||
|
||||
.token.function {
|
||||
color: #c792ea;
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.hexcode {
|
||||
color: #f2ff00;
|
||||
color: #f2ff00;
|
||||
}
|
||||
|
||||
.token.id {
|
||||
color: #c792ea;
|
||||
font-weight: bold;
|
||||
color: #c792ea;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.important {
|
||||
color: #c792ea;
|
||||
font-weight: bold;
|
||||
color: #c792ea;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.inserted {
|
||||
color: #80cbc4;
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.keyword {
|
||||
color: #c792ea;
|
||||
font-style: italic;
|
||||
color: #c792ea;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.number {
|
||||
color: #fd9170;
|
||||
color: #fd9170;
|
||||
}
|
||||
|
||||
.token.operator {
|
||||
color: #89ddff;
|
||||
color: #89ddff;
|
||||
}
|
||||
|
||||
.token.prolog {
|
||||
color: #546e7a;
|
||||
color: #546e7a;
|
||||
}
|
||||
|
||||
.token.property {
|
||||
color: #80cbc4;
|
||||
color: #80cbc4;
|
||||
}
|
||||
|
||||
.token.pseudo-class {
|
||||
color: #c3e88d;
|
||||
color: #c3e88d;
|
||||
}
|
||||
|
||||
.token.pseudo-element {
|
||||
color: #c3e88d;
|
||||
color: #c3e88d;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #89ddff;
|
||||
color: #89ddff;
|
||||
}
|
||||
|
||||
.token.regex {
|
||||
color: #f2ff00;
|
||||
color: #f2ff00;
|
||||
}
|
||||
|
||||
.token.selector {
|
||||
color: #f07178;
|
||||
color: #f07178;
|
||||
}
|
||||
|
||||
.token.string {
|
||||
color: #c3e88d;
|
||||
color: #c3e88d;
|
||||
}
|
||||
|
||||
.token.symbol {
|
||||
color: #c792ea;
|
||||
color: #c792ea;
|
||||
}
|
||||
|
||||
.token.tag {
|
||||
color: #f07178;
|
||||
color: #f07178;
|
||||
}
|
||||
|
||||
.token.unit {
|
||||
color: #f07178;
|
||||
color: #f07178;
|
||||
}
|
||||
|
||||
.token.url {
|
||||
color: #fd9170;
|
||||
color: #fd9170;
|
||||
}
|
||||
|
||||
.token.variable {
|
||||
color: #f07178;
|
||||
color: #f07178;
|
||||
}
|
||||
/*! purgecss end ignore */
|
||||
|
|
|
@ -9,363 +9,363 @@ import Transition from '../components/Transition';
|
|||
import { graphqlToModulesObject } from '../utils';
|
||||
|
||||
const renderPrerequisite = prerequisite => {
|
||||
const link = prerequisite.length > 1 ? prerequisite[1] : null;
|
||||
return (
|
||||
<li key={prerequisite[0]}>
|
||||
{link && (
|
||||
<a href={link} className="text-blue-600 underline">
|
||||
{prerequisite[0]}
|
||||
</a>
|
||||
)}
|
||||
{!link && prerequisite[0]}
|
||||
</li>
|
||||
);
|
||||
const link = prerequisite.length > 1 ? prerequisite[1] : null;
|
||||
return (
|
||||
<li key={prerequisite[0]}>
|
||||
{link && (
|
||||
<a href={link} className="text-blue-600 underline">
|
||||
{prerequisite[0]}
|
||||
</a>
|
||||
)}
|
||||
{!link && prerequisite[0]}
|
||||
</li>
|
||||
);
|
||||
};
|
||||
|
||||
const Breadcrumbs = ({ division }) => (
|
||||
<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"
|
||||
>
|
||||
Home
|
||||
</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>
|
||||
<Link
|
||||
to={`/${division}`}
|
||||
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>
|
||||
<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"
|
||||
>
|
||||
Home
|
||||
</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>
|
||||
<Link
|
||||
to={`/${division}`}
|
||||
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 = () => (
|
||||
<>
|
||||
<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="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
Report an Issue
|
||||
</button>
|
||||
</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>
|
||||
</>
|
||||
<>
|
||||
<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="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
Report an Issue
|
||||
</button>
|
||||
</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 {
|
||||
kind: 'link';
|
||||
label: string;
|
||||
href: string;
|
||||
kind: 'link';
|
||||
label: string;
|
||||
href: string;
|
||||
}
|
||||
|
||||
interface NavLinkGroup {
|
||||
kind: 'group';
|
||||
label: string;
|
||||
children: NavLink[];
|
||||
kind: 'group';
|
||||
label: string;
|
||||
children: NavLink[];
|
||||
}
|
||||
|
||||
type NavLinkItem = NavLink | NavLinkGroup;
|
||||
|
||||
const SidebarNavLinks = ({ links }) => {
|
||||
const renderLink = link => {
|
||||
if (link.kind === 'link') {
|
||||
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.label}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<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}
|
||||
</div>
|
||||
{link.children.map(renderLink)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return <>{links.map(renderLink)}</>;
|
||||
const renderLink = link => {
|
||||
if (link.kind === 'link') {
|
||||
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.label}
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<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}
|
||||
</div>
|
||||
{link.children.map(renderLink)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
return <>{links.map(renderLink)}</>;
|
||||
};
|
||||
|
||||
export default function Template(props) {
|
||||
const { mdx, allMdx } = props.data; // data.markdownRemark holds your post data
|
||||
const { body } = mdx;
|
||||
const prereqs = mdx.frontmatter.prerequisites;
|
||||
const division = props.pageContext.division;
|
||||
const { mdx, allMdx } = props.data; // data.markdownRemark holds your post data
|
||||
const { body } = mdx;
|
||||
const prereqs = mdx.frontmatter.prerequisites;
|
||||
const division = props.pageContext.division;
|
||||
|
||||
const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
|
||||
const navLinks: NavLinkItem[] = React.useMemo(() => {
|
||||
const modules = graphqlToModulesObject(allMdx);
|
||||
const getLinks = module => {
|
||||
if (module.hasOwnProperty('name')) {
|
||||
return {
|
||||
kind: 'group',
|
||||
label: module.name,
|
||||
children: module.items.map(getLinks),
|
||||
};
|
||||
}
|
||||
if (!modules.hasOwnProperty(module)) {
|
||||
throw `${module} not found!`;
|
||||
}
|
||||
return {
|
||||
kind: 'link',
|
||||
label: modules[module].frontmatter.title,
|
||||
href: `/${division}/${module}`,
|
||||
};
|
||||
};
|
||||
return ModuleOrdering[division].map(getLinks);
|
||||
}, []);
|
||||
const [isMobileNavOpen, setIsMobileNavOpen] = useState(false);
|
||||
const navLinks: NavLinkItem[] = React.useMemo(() => {
|
||||
const modules = graphqlToModulesObject(allMdx);
|
||||
const getLinks = module => {
|
||||
if (module.hasOwnProperty('name')) {
|
||||
return {
|
||||
kind: 'group',
|
||||
label: module.name,
|
||||
children: module.items.map(getLinks),
|
||||
};
|
||||
}
|
||||
if (!modules.hasOwnProperty(module)) {
|
||||
throw `${module} not found!`;
|
||||
}
|
||||
return {
|
||||
kind: 'link',
|
||||
label: modules[module].frontmatter.title,
|
||||
href: `/${division}/${module}`,
|
||||
};
|
||||
};
|
||||
return ModuleOrdering[division].map(getLinks);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<div className="h-screen flex overflow-hidden bg-white">
|
||||
{/* Off-canvas menu for mobile */}
|
||||
<Transition show={isMobileNavOpen}>
|
||||
<div className="lg:hidden">
|
||||
<div className="fixed inset-0 flex z-40">
|
||||
<Transition
|
||||
enter="transition-opacity ease-linear duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="transition-opacity ease-linear duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div
|
||||
className="fixed inset-0"
|
||||
onClick={() => setIsMobileNavOpen(false)}
|
||||
>
|
||||
<div className="absolute inset-0 bg-gray-600 opacity-75" />
|
||||
</div>
|
||||
</Transition>
|
||||
return (
|
||||
<Layout>
|
||||
<div className="h-screen flex overflow-hidden bg-white">
|
||||
{/* Off-canvas menu for mobile */}
|
||||
<Transition show={isMobileNavOpen}>
|
||||
<div className="lg:hidden">
|
||||
<div className="fixed inset-0 flex z-40">
|
||||
<Transition
|
||||
enter="transition-opacity ease-linear duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="transition-opacity ease-linear duration-300"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div
|
||||
className="fixed inset-0"
|
||||
onClick={() => setIsMobileNavOpen(false)}
|
||||
>
|
||||
<div className="absolute inset-0 bg-gray-600 opacity-75" />
|
||||
</div>
|
||||
</Transition>
|
||||
|
||||
<Transition
|
||||
enter="transition ease-in-out duration-300 transform"
|
||||
enterFrom="-translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="-translate-x-full"
|
||||
>
|
||||
<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">
|
||||
<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)}
|
||||
>
|
||||
<svg
|
||||
className="h-6 w-6 text-white"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-1 h-0 pt-5 pb-4 overflow-y-auto">
|
||||
<div className="flex-shrink-0 flex items-center px-4">
|
||||
<img
|
||||
className="h-8 w-auto"
|
||||
src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg"
|
||||
alt="Workflow"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-8 px-6">
|
||||
<Breadcrumbs division={division} />
|
||||
</div>
|
||||
<nav className="mt-2">
|
||||
<SidebarNavLinks links={navLinks} />
|
||||
</nav>
|
||||
</div>
|
||||
<SidebarBottomButtons />
|
||||
</div>
|
||||
</Transition>
|
||||
<div className="flex-shrink-0 w-14">
|
||||
{/* Force sidebar to shrink to fit close icon */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
{/* Static sidebar for desktop */}
|
||||
<div className="hidden lg:flex lg:flex-shrink-0">
|
||||
<div className="flex flex-col w-64 border-r border-gray-200 bg-white">
|
||||
<div className="h-0 flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
|
||||
<div className="flex items-center flex-shrink-0 px-4">
|
||||
<img
|
||||
className="h-8 w-auto"
|
||||
src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg"
|
||||
alt="Workflow"
|
||||
/>
|
||||
</div>
|
||||
{/* Sidebar component, swap this element with another sidebar if you like */}
|
||||
<nav className="mt-5 flex-1 bg-white">
|
||||
<SidebarNavLinks links={navLinks} />
|
||||
</nav>
|
||||
</div>
|
||||
<SidebarBottomButtons />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col w-0 flex-1 overflow-hidden">
|
||||
<div className="lg:hidden pl-1 pt-1 sm:pl-3 sm:pt-3">
|
||||
<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"
|
||||
onClick={() => setIsMobileNavOpen(true)}
|
||||
>
|
||||
<svg
|
||||
className="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M4 6h16M4 12h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<main
|
||||
className="flex-1 relative z-0 overflow-y-auto sm:pt-2 pb-6 focus:outline-none lg:py-6"
|
||||
tabIndex={0}
|
||||
>
|
||||
<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>
|
||||
)}
|
||||
<Transition
|
||||
enter="transition ease-in-out duration-300 transform"
|
||||
enterFrom="-translate-x-full"
|
||||
enterTo="translate-x-0"
|
||||
leave="transition ease-in-out duration-300 transform"
|
||||
leaveFrom="translate-x-0"
|
||||
leaveTo="-translate-x-full"
|
||||
>
|
||||
<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">
|
||||
<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)}
|
||||
>
|
||||
<svg
|
||||
className="h-6 w-6 text-white"
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M6 18L18 6M6 6l12 12"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex-1 h-0 pt-5 pb-4 overflow-y-auto">
|
||||
<div className="flex-shrink-0 flex items-center px-4">
|
||||
<img
|
||||
className="h-8 w-auto"
|
||||
src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg"
|
||||
alt="Workflow"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-8 px-6">
|
||||
<Breadcrumbs division={division} />
|
||||
</div>
|
||||
<nav className="mt-2">
|
||||
<SidebarNavLinks links={navLinks} />
|
||||
</nav>
|
||||
</div>
|
||||
<SidebarBottomButtons />
|
||||
</div>
|
||||
</Transition>
|
||||
<div className="flex-shrink-0 w-14">
|
||||
{/* Force sidebar to shrink to fit close icon */}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Transition>
|
||||
{/* Static sidebar for desktop */}
|
||||
<div className="hidden lg:flex lg:flex-shrink-0">
|
||||
<div className="flex flex-col w-64 border-r border-gray-200 bg-white">
|
||||
<div className="h-0 flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
|
||||
<div className="flex items-center flex-shrink-0 px-4">
|
||||
<img
|
||||
className="h-8 w-auto"
|
||||
src="https://tailwindui.com/img/logos/workflow-logo-on-white.svg"
|
||||
alt="Workflow"
|
||||
/>
|
||||
</div>
|
||||
{/* Sidebar component, swap this element with another sidebar if you like */}
|
||||
<nav className="mt-5 flex-1 bg-white">
|
||||
<SidebarNavLinks links={navLinks} />
|
||||
</nav>
|
||||
</div>
|
||||
<SidebarBottomButtons />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col w-0 flex-1 overflow-hidden">
|
||||
<div className="lg:hidden pl-1 pt-1 sm:pl-3 sm:pt-3">
|
||||
<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"
|
||||
onClick={() => setIsMobileNavOpen(true)}
|
||||
>
|
||||
<svg
|
||||
className="h-6 w-6"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke="currentColor"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M4 6h16M4 12h16M4 18h16"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<main
|
||||
className="flex-1 relative z-0 overflow-y-auto sm:pt-2 pb-6 focus:outline-none lg:py-6"
|
||||
tabIndex={0}
|
||||
>
|
||||
<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" />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
<Markdown body={body} className="markdown--module" />
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
export const pageQuery = graphql`
|
||||
query($id: String!) {
|
||||
mdx(frontmatter: { id: { eq: $id } }) {
|
||||
body
|
||||
frontmatter {
|
||||
title
|
||||
author
|
||||
id
|
||||
prerequisites
|
||||
}
|
||||
}
|
||||
allMdx {
|
||||
edges {
|
||||
node {
|
||||
frontmatter {
|
||||
title
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
query($id: String!) {
|
||||
mdx(frontmatter: { id: { eq: $id } }) {
|
||||
body
|
||||
frontmatter {
|
||||
title
|
||||
author
|
||||
id
|
||||
prerequisites
|
||||
}
|
||||
}
|
||||
allMdx {
|
||||
edges {
|
||||
node {
|
||||
frontmatter {
|
||||
title
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
|
|
@ -8,50 +8,50 @@ import { getModule, graphqlToModulesObject } from '../utils';
|
|||
import SyllabusModule from '../components/SyllabusModule';
|
||||
|
||||
const renderModule = (node, idx, parentIdx = -1) => {
|
||||
if (node.hasOwnProperty('items')) {
|
||||
return node.items.map((x, i) => renderModule(x, i, idx));
|
||||
}
|
||||
if (node.hasOwnProperty('items')) {
|
||||
return node.items.map((x, i) => renderModule(x, i, idx));
|
||||
}
|
||||
|
||||
const data = node.frontmatter;
|
||||
if (!data.title) return;
|
||||
const data = node.frontmatter;
|
||||
if (!data.title) return;
|
||||
|
||||
return (
|
||||
<SyllabusModule
|
||||
title={`${parentIdx !== -1 ? parentIdx + 1 + '.' : ''}${idx + 1}. ${
|
||||
data.title
|
||||
}`}
|
||||
url={node.slug}
|
||||
key={node.slug}
|
||||
problems={data.problems}
|
||||
prerequisites={data.prerequisites}
|
||||
author={data.author}
|
||||
>
|
||||
{data.description}
|
||||
</SyllabusModule>
|
||||
);
|
||||
return (
|
||||
<SyllabusModule
|
||||
title={`${parentIdx !== -1 ? parentIdx + 1 + '.' : ''}${idx + 1}. ${
|
||||
data.title
|
||||
}`}
|
||||
url={node.slug}
|
||||
key={node.slug}
|
||||
problems={data.problems}
|
||||
prerequisites={data.prerequisites}
|
||||
author={data.author}
|
||||
>
|
||||
{data.description}
|
||||
</SyllabusModule>
|
||||
);
|
||||
};
|
||||
|
||||
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 colors = {
|
||||
intro: 'blue',
|
||||
general: 'pink',
|
||||
bronze: 'orange',
|
||||
silver: 'teal',
|
||||
gold: 'yellow',
|
||||
plat: 'purple',
|
||||
};
|
||||
const color = colors[selectedDivision];
|
||||
const module = getModule(allModules, selectedDivision);
|
||||
const [selectedDivision, setSelectedDivision] = React.useState(
|
||||
props.pageContext.division
|
||||
);
|
||||
const colors = {
|
||||
intro: 'blue',
|
||||
general: 'pink',
|
||||
bronze: 'orange',
|
||||
silver: 'teal',
|
||||
gold: 'yellow',
|
||||
plat: 'purple',
|
||||
};
|
||||
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-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
|
||||
|
@ -65,230 +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-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`,
|
||||
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 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`;
|
||||
|
||||
const handleDivisionChange = d => {
|
||||
setSelectedDivision(d);
|
||||
window.history.pushState(null, '', `/${d}/`);
|
||||
};
|
||||
const handleDivisionChange = d => {
|
||||
setSelectedDivision(d);
|
||||
window.history.pushState(null, '', `/${d}/`);
|
||||
};
|
||||
|
||||
return (
|
||||
<Layout>
|
||||
<SEO title="Home" />
|
||||
return (
|
||||
<Layout>
|
||||
<SEO title="Home" />
|
||||
|
||||
<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 */}
|
||||
<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 */}
|
||||
|
||||
<div className="pb-8" id="content">
|
||||
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 pb-4">
|
||||
<div
|
||||
className="mb-8 bg-white shadow-md rounded-lg relative"
|
||||
style={{ marginTop: '-12rem' }}
|
||||
>
|
||||
<div className="sm:hidden">
|
||||
<select
|
||||
aria-label="Selected tab"
|
||||
className="form-select block w-full"
|
||||
onChange={e => handleDivisionChange(e.target.value)}
|
||||
value={selectedDivision}
|
||||
>
|
||||
{divisions.map(division => (
|
||||
<option key={division} value={division}>
|
||||
{divisionLabels[division]}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="hidden sm:block border-b border-gray-200">
|
||||
<nav className="flex -mb-px">
|
||||
{divisions.map(division => (
|
||||
<a
|
||||
key={division}
|
||||
href={`/${division}`}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
handleDivisionChange(division);
|
||||
}}
|
||||
className={
|
||||
selectedDivision === division
|
||||
? selectedTabClasses
|
||||
: unselectedTabClasses
|
||||
}
|
||||
>
|
||||
{divisionLabels[division]}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
<div className="pb-8" id="content">
|
||||
<div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 pb-4">
|
||||
<div
|
||||
className="mb-8 bg-white shadow-md rounded-lg relative"
|
||||
style={{ marginTop: '-12rem' }}
|
||||
>
|
||||
<div className="sm:hidden">
|
||||
<select
|
||||
aria-label="Selected tab"
|
||||
className="form-select block w-full"
|
||||
onChange={e => handleDivisionChange(e.target.value)}
|
||||
value={selectedDivision}
|
||||
>
|
||||
{divisions.map(division => (
|
||||
<option key={division} value={division}>
|
||||
{divisionLabels[division]}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
<div className="hidden sm:block border-b border-gray-200">
|
||||
<nav className="flex -mb-px">
|
||||
{divisions.map(division => (
|
||||
<a
|
||||
key={division}
|
||||
href={`/${division}`}
|
||||
onClick={e => {
|
||||
e.preventDefault();
|
||||
handleDivisionChange(division);
|
||||
}}
|
||||
className={
|
||||
selectedDivision === division
|
||||
? selectedTabClasses
|
||||
: unselectedTabClasses
|
||||
}
|
||||
>
|
||||
{divisionLabels[division]}
|
||||
</a>
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<ol className="list-inside py-8 px-8 text-lg space-y-1">
|
||||
{module.map((m, idx) => {
|
||||
if (m.hasOwnProperty('items')) {
|
||||
return (
|
||||
<li key={m.name}>
|
||||
<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>
|
||||
<ol className="list-inside py-8 px-8 text-lg space-y-1">
|
||||
{module.map((m, idx) => {
|
||||
if (m.hasOwnProperty('items')) {
|
||||
return (
|
||||
<li key={m.name}>
|
||||
<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>
|
||||
);
|
||||
{module.map((x, idx) => renderModule(x, idx))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
export const pageQuery = graphql`
|
||||
query {
|
||||
modules: allMdx {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
frontmatter {
|
||||
title
|
||||
id
|
||||
author
|
||||
problems
|
||||
prerequisites
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
query {
|
||||
modules: allMdx {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
frontmatter {
|
||||
title
|
||||
id
|
||||
author
|
||||
problems
|
||||
prerequisites
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
|
58
src/utils.js
58
src/utils.js
|
@ -1,36 +1,36 @@
|
|||
import ModuleOrdering from '../content/ordering';
|
||||
|
||||
export const getModule = (allModules, division) => {
|
||||
return ModuleOrdering[division].map(k => {
|
||||
// rip spaghetti code, clean this up
|
||||
if (typeof k === 'object') {
|
||||
return {
|
||||
name: k.name,
|
||||
items: k.items.map(k2 => {
|
||||
if (!allModules.hasOwnProperty(k2)) {
|
||||
throw 'Module not found: ' + k2;
|
||||
}
|
||||
return {
|
||||
...allModules[k2],
|
||||
slug: `/${division}/${allModules[k2].frontmatter.id}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
if (!allModules.hasOwnProperty(k)) {
|
||||
throw 'Module not found: ' + k;
|
||||
}
|
||||
return {
|
||||
...allModules[k],
|
||||
slug: `/${division}/${allModules[k].frontmatter.id}`,
|
||||
};
|
||||
}
|
||||
});
|
||||
return ModuleOrdering[division].map(k => {
|
||||
// rip spaghetti code, clean this up
|
||||
if (typeof k === 'object') {
|
||||
return {
|
||||
name: k.name,
|
||||
items: k.items.map(k2 => {
|
||||
if (!allModules.hasOwnProperty(k2)) {
|
||||
throw 'Module not found: ' + k2;
|
||||
}
|
||||
return {
|
||||
...allModules[k2],
|
||||
slug: `/${division}/${allModules[k2].frontmatter.id}`,
|
||||
};
|
||||
}),
|
||||
};
|
||||
} else {
|
||||
if (!allModules.hasOwnProperty(k)) {
|
||||
throw 'Module not found: ' + k;
|
||||
}
|
||||
return {
|
||||
...allModules[k],
|
||||
slug: `/${division}/${allModules[k].frontmatter.id}`,
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const graphqlToModulesObject = allMdx => {
|
||||
return allMdx.edges.reduce((acc, cur) => {
|
||||
acc[cur.node.frontmatter.id] = cur.node;
|
||||
return acc;
|
||||
}, {});
|
||||
return allMdx.edges.reduce((acc, cur) => {
|
||||
acc[cur.node.frontmatter.id] = cur.node;
|
||||
return acc;
|
||||
}, {});
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module.exports = {
|
||||
plugins: [require('@tailwindcss/ui')],
|
||||
purge: {
|
||||
content: ['./src/**/*.js', './src/**/*.ts', './src/**/*.tsx'],
|
||||
},
|
||||
plugins: [require('@tailwindcss/ui')],
|
||||
purge: {
|
||||
content: ['./src/**/*.js', './src/**/*.ts', './src/**/*.tsx'],
|
||||
},
|
||||
};
|
||||
|
|
Reference in a new issue