Table of Contents
FrontmatterExample FrontmatterModule OrderingLinking to ModulesTable of ContentsMDX and Custom ComponentsSpoilersInfo BlockWarning BlockOptional ContentProblem ListsFocus ProblemResource ListsTooltips<TextTooltip><Asterisk>Incomplete SectionCode Blocks and Code SnippetsKattioC++ Short TemplateLanguage-Specific ContentA heading that only appears in C++A heading that only appears in C++QuizzesWorking With MDX
Author: Nathan Wang
Explanation of the frontmatter that precedes every module and solution, and a list of custom components that may be used within modules or solutions.
Prerequisites
Table of Contents
FrontmatterExample FrontmatterModule OrderingLinking to ModulesTable of ContentsMDX and Custom ComponentsSpoilersInfo BlockWarning BlockOptional ContentProblem ListsFocus ProblemResource ListsTooltips<TextTooltip><Asterisk>Incomplete SectionCode Blocks and Code SnippetsKattioC++ Short TemplateLanguage-Specific ContentA heading that only appears in C++A heading that only appears in C++QuizzesWe're using MDX, a superset of Markdown, using the XDM compiler. HTML and React components are supported, so it is possible to add interactivity / custom components to each module.
Frontmatter
Frontmatter is the stuff in the beginning of each module that's surrounded by three dashes. Frontmatter is written in YAML. It stores the "metadata" for each module.
- ID: Required. The ID of the module. Ex:
getting-started
, orcontainers
. This ID is used to identify the module, so make sure it is unique and all lowercase with dashes only. The URL will be generated based off this. - Title: Required. The title of the module. Ex:
Getting Started
- Author: Required. The author of the module. Ex:
Unknown
- Contributors: Optional. The people who contributed code and/or short explanations to the module.
- Description: Required. A short description of the module, similar to what codecademy has in their syllabus. Markdown/LaTeX does not work in the description field.
- Prerequisites: Optional. Any prerequisites for this module. If you want to reference a module as a prerequisite, list it as a module ID. A link will be auto-generated.
- Frequency: Optional. Takes a number 0-4 inclusive, where 0 = never shown up before and 4 = shows up ~once a contest. Leave this field out if you don't want to show the frequency.
- Redirects: Optional. Takes a list of URLs that will redirect to the current module. Add a redirect whenever you change the module ID or move the module to a different division.
Example Frontmatter
--- id: getting-started title: Getting Started description: Welcome to the guide! We'll introduce what programming competitions are and how this guide is organized. author: Nathan Wang order: 1 prerequisites: - Dummy prerequisite - running-cpp redirects: - /silver/bipartite --- # Getting Started ...
Module Ordering
Located at content/ordering.ts
, this file stores the ordering of the modules.
The format should be self-explanatory (it matches based on the ID).
Linking to Modules
Linking to another module within the guide looks like this:
[insert text here](/general/practicing)
.
Don't use relative links like practicing
, as that will break our
link checker.
Table of Contents
A table of contents will be auto-generated based off of the headings in the Markdown. Keep this in mind when formatting your module.
MDX and Custom Components
Optional: XDM and MDX
We use the XDM compiler, which has a few differences from MDX v1:
- Markdown interleaved in JSX is fully supported; ie. this works as expected:
<Info>some **markdown**</Info>
- As an extension of (1), indentation is fully supported. You can indent the markdown nested in JSX tags. This also means that indenting text with four spaces doesn't make it a code block; explicitly wrap the code block with three backticks instead.
<
and>
need to be escaped with backslashes; ie.\<
Note that JSX comments ({/* ... */}
) don't work well with Prettier, so use
HTML comments instead.
Internally we map HTML comments to JSX comments before passing the markdown to
XDM. Don't worry if you don't understand all of this yet.
Some components are globally available in every module (without having to be imported):
<Spoiler>
<Info>
<Warning>
<Optional>
<Problems>
<FocusProblem>
<Resources>
<Resource>
<TextTooltip>
<LanguageSection>
<CPPSection>
<JavaSection>
<PySection>
<CPPOnly>
<JavaOnly>
<PyOnly>
<IncompleteSection>
<Asterisk>
<Quiz>
These are all documented below.
Spoilers
Spoilers are collapsible elements that only show themselves when the user clicks on it. It's useful when writing hints or solutions to problems. As a convention, we do not use spoilers for module solutions.
<Spoiler title="Show Hint"> - Insert hint here </Spoiler>
Show Hint
Info Block
<Info title="Insert Title Here"> **Markdown is Supported!!** </Info>
Insert Title Here
Markdown is Supported!!
Warning Block
<Warning title="Insert Title Here"> Fun fact: the title attribute is optional. </Warning>
Warning: Insert Title Here
Fun fact: the title attribute is optional.
Optional Content
<Optional title="Insert Title Here"> Fun fact: the title attribute is optional. </Optional>
Optional: Insert Title Here
Fun fact: the title attribute is optional.
Problem Lists
Each module has two corresponding files, a .mdx
file and a .problems.json
file. The .problems.json
file stores the focus problems and problem lists used
in that module; it is also indexed by Algolia for problem search.
The .problems.json
file holds an object, where keys are problem list names (or
focus problem names) and values are arrays of ProblemMetadata
objects. For
focus problems, the array should have length exactly one. Additionally, the
.problems.json
file should have a MODULE_ID
key with value equal to a string
that represents the module ID.
For more information on problem definitions, refer to src/models/problem.ts
.
Example usage:
<Problems problems="problems" />
[module].problems.json
should have a key of problems
that maps to an array
of ProblemMetadata
.
There is a distinction between ProblemInfo
and ProblemMetadata
.
ProblemMetadata
is what is stored in [module].problems.json
. Gatsby takes
ProblemMetadata
and converts it into ProblemInfo
at build time; React
components use ProblemInfo
when interacting with problem information. The
documentation below is for ProblemMetadata
, which is what content authors will
be writing.
ProblemMetadata
fields:
uniqueId
-- The uniqueId of the problem. Problem progress is linked to this,
so don't change this (otherwise problem progress will be lost). By convention,
it's [source]-[SlugifiedProblemNameCamelCased]
.
- If the problem name is only one word, the word is lower cased.
- If the problem is USACO or CSES, the unique ID is instead
usaco-[USACO URL Number]
orcses-[CSES number]
. - If the problem is Codeforces, the unique ID is
cf-[contestNumber][problemLetter]
. If it's CF Gym, it'scfgym-[gymNumber][problemLetter]
. - If the problem is an OI with a year, the unique ID is
[oiName]-[twodigityear]-[slugifiedName]
.
Here are some example unique ID's:
cses-2177 poi-08-blockade apio-18-duathlon dmoj-investment infoarena-xortransform usaco-949 cses-1691 kattis-chineseremainder cfgym-102538F cf-1209H spoj-LexicographicalStringSearch ys-AssociativeArray
Problems with the same unique ID are expected to have identical names, sources, and URL's.
name
-- The name of the problem. Should not include source.
Examples:
2009 - Beetle Greedy Pie Eaters Zuma 2014 - The Stables of Genghis Khan
source
-- The source of the problem. Restricted to: todo, refer to
src/models/problem.ts
contests
and probSources
difficulty
-- The difficulty of the problem relative to the module it is
in. Valid options are Very Easy
, Easy
, Normal
, Hard
, Very Hard
,
Insane
isStarred
-- Whether this problem should be starred or not.
tags
-- List of tags for this problem.
solutionMetadata
-- Information about the solution.
export type ProblemMetadata = Omit<ProblemInfo, 'solution'> & { solutionMetadata: | { // auto generate problem solution label based off of the given site // For sites like Codeforces: "Check contest materials, located to the right of the problem statement." kind: 'autogen-label-from-site'; // The site to generate it from. Sometimes this may differ from the source; for example, Codeforces could be the site while Baltic OI could be the source if Codeforces was hosting a Baltic OI problem. site: string; } | { // internal solution kind: 'internal'; } | { // URL solution // Use this for links to PDF solutions, etc kind: 'link'; url: string; } | { // Competitive Programming Handbook // Ex: 5.3 or something kind: 'CPH'; section: string; } | { // USACO solution, generates it based off of the USACO problem ID // ex. 1113 is mapped to sol_prob1_gold_feb21.html kind: 'USACO'; usacoId: string; } | { // IOI solution, generates it based off of the year // ex. Maps year = 2001 to https://ioinformatics.org/page/ioi-2001/27 kind: 'IOI'; year: number; } | { // no solution exists kind: 'none'; } | { // for focus problems, when the solution is presented in the module of the problem kind: 'in-module'; moduleId: string; } | { kind: 'sketch'; sketch: string; }; };
Editorials are also written in MDX. The frontmatter has four fields:
--- id: cses-1621 source: CSES title: Distinct Numbers author: Nathan Wang --- ... solution
The ID of the solution frontmatter must be the same as the unique ID of the
problem. Make sure to also update the kind
of the solutionMetadata
to
'internal'
for any associated problems. We assume that if there is an internal
solution, we should use it; therefore, the build will throw an error if there is
an internal solution but the solutionMetadata
's kind
isn't set to
'internal'
. The Adding Solutions module describes
how to add a new solution.
Focus Problem
Displays a singular problem as a "focus problem."
<FocusProblem problem="genPermutations" />
[module].problems.json
should have a key of genPermutations
that maps to an
array of length 1.
Resource Lists
<Resources> <Resource source="Errichto" title="Video - How to test your solution" url="https://www.youtube.com/watch?v=JXTVOyQpSGM" starred > using a script to stress test </Resource> ... </Resources>
Resources | ||||
---|---|---|---|---|
Errichto | using a script to stress test |
Special functionality based on source:
- If the source is a book, it'll automatically set the URL to point to the book.
- Supported books:
GCP
(Guide to Competitive Programming)CPH
(Competitive Programming Handbook)PAPS
(Principles of Algorithmic Problem Solving)CP2
(Competitive Programming 2)IUSACO
(Darren's book; will auto-set URL based on user language; uses C++ for Python users)
- Some sources will automatically have tooltips generated for them (listed here).
Tooltips
There are two main types of tooltips: text tooltips, which display a dotted underline under the text, and asterisk tooltips, which render an asterisk that can be hovered over.
<TextTooltip>
short text goes here<TextTooltip content="Popup text goes here">short text goes here</TextTooltip>
<Asterisk>
<Asterisk>Popup text goes here</Asterisk>
Incomplete Section
<IncompleteSection> - this list is optional and can be used to specify what is missing - missing 32-bit integer explanation </IncompleteSection>
This section is not complete.
- this list is optional and can be used to specify what is missing
- missing 32-bit integer explanation
Code Blocks and Code Snippets
Code blocks are separated by three backticks, just like in normal markdown. Additionally, we have support for collapsible code snippets. An example for how to use them can be found below:
With title
// Before // BeginCodeSnip{Optional Code Snippet Title} // Code snippet goes here // You can indent the entire BeginCodeSnip block (including the BeginCodeSnip line) and it will function as expected // EndCodeSnip // After
// BeforeCode Snippet: Optional Code Snippet Title (Click to expand)
Without title:
// BeginCodeSnip{} // My snippet code goes here // EndCodeSnip // My non-snippet code goes here
Code Snippet (Click to expand)// My non-snippet code goes here
Some common snippets have shorthand notations, as defined in
src/mdx-plugins/rehype-snippets.js
.
They can be accessed using CodeSnip{Snip ID}
.
Kattio
CodeSnip{Kattio}
gets replaced with an indented version (based off of
indentation of CodeSnip
):
import java.io.*;import java.util.*;public class myClass {Code Snippet: Kattio (Click to expand)public static void main...}
C++ Short Template
CodeSnip{CPP Short Template}
is replaced with
Code Snippet: C++ Short Template (Click to expand)
Language-Specific Content
<LanguageSection> <CPPSection> #### A heading that only appears in C++ ```cpp C++ code here ``` </CPPSection> <JavaSection> #### A heading that only appears in Java ```java Java code here ``` </JavaSection> <PySection /> </LanguageSection>
In the example above, nothing will be rendered for Python.
C++
A heading that only appears in C++
C++ code here
Java
A heading that only appears in Java
Java code here
Python
If you want to render content for only a single language, it is more convenient
to use CPPOnly
, JavaOnly
, or PyOnly
:
<CPPOnly> #### A heading that only appears in C++ ```cpp C++ code here ``` </CPPOnly>
C++
A heading that only appears in C++
C++ code here
Java
Python
Quizzes
<Quiz> <Quiz.Question> Binary search <Quiz.Answer> $O(\log n)$ <Quiz.Explanation> Almost. Prefer $\mathcal{O}$ over $O$. </Quiz.Explanation> </Quiz.Answer> <Quiz.Answer correct> $\mathcal{O}(\log n)$ <Quiz.Explanation> That's correct! </Quiz.Explanation> </Quiz.Answer> <Quiz.Answer> O(log n) <Quiz.Explanation> That's not right. Latex is important... </Quiz.Explanation> </Quiz.Answer> </Quiz.Question> <Quiz.Question> ```cpp for (int i = 0; i < 100; i++) { for (int j = 0; j < m; j++) { // constant time code here } } ``` <Quiz.Answer> $O(100m)$ <Quiz.Explanation> That's not correct. Constant factors are ignored. </Quiz.Explanation> </Quiz.Answer> <Quiz.Answer correct> $O(m)$ <Quiz.Explanation> That's correct! </Quiz.Explanation> </Quiz.Answer> </Quiz.Question> </Quiz>
Binary search
Module Progress:
Join the USACO Forum!
Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!