Button
Button
Paradoc

Instantly write, deploy, and enjoy docs

Workflow

<script src="site/Paradoc.js"></script>
Everything _after_ the first line is
plain **markdown**.

Try It Out

This website was created from the Paradoc repo’s main README.html markdown file. Clone this repo and double click README.html to turn it into this webpage.

  1. git clone git@github.com:jordwalke/paradoc.git
  2. Double click README.html

Note: The script include in this README.html looks complicated because it uses Advanced Features that allows a single README.html to act as a website, and a Github README, always kept in sync. Your files will probably use the very simple script include already discussed.

Looks

Split View

Paradoc comes with a UI theme that supports a left/right responsive split layout. As you increase the window size, code samples and block quotes are split into a right hand column.

Note: The style for this split view comes from Paradoc’s use of flatdoc, but has been heavily modified. The split view can be disabled in your siteTemplate.

Some of the additional markdown extension features control the behavior of this split view.

Markdown Extensions

Paradoc supports extended markdown features specified in Github Flavored markdown, and also supports some additional Paradoc specific features.

Code highlighting

With GitHub Flavored Markdown you can use Markdown code fences to make syntax-highlighted text. In Paradoc, codeblocks will be rendered in the right column of the split view if the window is sufficiently wide.

```javascript
console.log("This", "is a log");
```

Blockquotes

Blockquotes also show up in the right hand column when the window is sufficiently large. This is useful for providing extra information or non-code examples that move out of the way of the main document.

Blockquotes are blocks that begin with >.

Smart quotes

Single quotes, double quotes, and double-hyphens are replaced to their “typographically-accurate” equivalent. This does not apply to <code> and <pre> blocks.

“Check out this quote here. Look how how correct the quotes are” —me

<continueRight/>

Paradoc adds an additional feature that allows a right column element to continue flowing.

This blockquote comes immediately after the text “Paradoc adds an additional feature that allows a right column element to continue flowing” but notice how this blockquote also continues to “flow” into the list that comes after it? This is important for creating a better balance of left and right content. Doing so requires the author to opt into having particular blockquote/code blocks flow into subsequent left content when it makes sense.

Images In Right Column

Images may also be placed into the right column of the document by placing them in blockquotes.

> ![Another Beach](site/images/beach2.jpg)

Like all other elements, you may place a <continueRight/> after blockquote containing the image to get subsequent content to flow alongside the image on its left side:

Another Beach

Code Tabs

You can create Docusaurus style code toggle switches for viewing multiple different code samples. In this example, clicking on the headers (reason, javascript, ocaml) will toggle between different syntaxes for a particular print command.

reasonjavascriptocaml
Console.log(["This", "Logs", "Reason", "Lists"]);
Library.callSomeFunction(10, 200);
Console.log(["This", "Logs", "Reason", "Arrays"]);
library.callSomeFunction(10, 200);
Console.log ["This", "Logs", "Ocaml", "Lists"]
Library.callSomeFunction 10 200;

To create code tabs, place multiple code blocks between special CODE_TABS HTML comments as follows.

 <!--CODE_TABS-->
 ... multiple code blocks go here...
 <!--END_CODE_TABS-->

Custom Tab Titles

By default, code tab titles are inferred from the code block syntaxes, but you may give custom names to the tabs by including an HTML comment before each code example.

 <!--CODE_TABS-->
 <!--My JS Code Block-->
 ...js code block...
 <!--My Python Code Block-->
 ...python code block...
 <!--END_CODE_TABS-->

Note: Specifying the title from this code block syntax is a Paradoc feature, not supported in Docusaurus.

The previous example produces the following result:

My JS Code BlockMy Python Code Block
console.log('Hello, world!');
print('Hello, world!')

UI Enhancements

Medium-Zoom Images

Images are specified using standard markdown syntax, but they are enhanced with a plugin called Medium Zoom.

![Beach](site/logo.svg)

Beach

Click on the image to view a full view. Click, or scroll a small amount to cause the image to animate back into place.

Buttons

Include a > at the end of your link text (for instance: Continue >), to turn them into buttons. This is a feature from flatdoc.

Go To Github

YAML Headers

Paradoc parses valid key/value items from “YAML headers”. These headers are where you specify information that applies to that entire document. YAML headers consist of an unlimited number of key:value lines sandwiched between two --- at the start of the document, immediately after the initial Paradoc <script>.

You can specify any key/value pairs you like - but Paradoc will look for certain keys to configure your website and rendering. See Configuring Pages.

<script src="site/Paradoc.js"></script>
---
title: me
description: "Hi there here is an escaped quote \" inside of quotes"
anythingYouWant: hey
---

Multi-Doc Pages

To add another doc page, have an existing page specify the new page as its nextPage: in the Page Header . Then make sure that new page actually exists, and has the Paradoc script include as usual.

Note: All pages should also supply a rootPage: header property that specifies the “first page” in the list.

The following header specifies that the next markdown page should be my-next-page.html, and that the starting “root page” should be README.html.

<script src="site/Paradoc.js"></script>
---
title: me
nextPage: my-next-page
rootPage: readme
---

See how to Add More Pages

Search Features

Paradoc supports offline search across all of the documents that are added. No build steps or servers are required to search, and no subscriptions to search services are required. Content is searched interactively while authoring docs locally, when users consume your deployed site, and when users save local copies of your deployed site to disk.

Keyboard Interactions

Keyboard Action
/ Focus the Search input
Esc Close search results and blur search input
Ctrl+c or Ctrl+[ Toggle search results open when focused
Down or Ctrl+n When results open, move up / down in results
Up or Ctrl+p When results open, move up / down in results
Enter or Click Go to currently selected result

Change Resistant Deep Linking

All content in Paradoc pages can be “deep linked” to. This means that you can create a url link to a specific paragraph, code sample, or table row (not just the headers).

These links are “change resistant”, meaning that the content can be moved to another location in the document, and all the links that have proliferated on the internet will still work correctly.

It also means that the contents that are linked can be changed (fixing typos, refactoring sentence structure), and all proliferated links to that specific content will still usually work (up to a certain amount of changes).

This works by creating a text fingerprint of the content and when loading the page, finding the content that most closely matches that fingerprint in the url. Even if the text has changed changes Paradoc will find the best match possible.

Try It Out

Hit / to search for anything, and hit enter on a search result. Then copy/paste the url into a new browser window. The search results encode the change resistant deep link in the url, and you can share that specific search result with anyone or link to it from a blog while feeling confident your links won’t break.

Deploying

Easy Optimizing With Chrome

Just “Save As” in Chrome, select “Complete Webpage” to generated an optimized, pre-rendered version of the site with all docs served as a single page application with working online/offline search.

Packing Into A Single .html file.

“Save As” in Chrome generates an optimized rendered build of your website as a single page application, but it will generate a folder with assets/styles and images for your docs to be distributed/deployed along with your main html page. You can take it even further also optimize your docs page into a single, minified .html file which bundles all of its resources including fonts and images! There are many benefits to the way Paradoc compresses your docs site into a single, shareable .html file.

cd site
npm install
node ./Paradoc.js ../readme.html

Now you can deploy ../readme.bookmark-inlined.html as a single file to any web host, and it will operate as a single page application.

With this mode:

More

Issues:

You must only load markdown html files that you authored and trust. Currently, the way that the marked library is being used does not sanitize the output before injecting it into the DOM.

Acknowledgements

See ORIGINS.md for links and licenses of various components that are embedded in this project.

Configuring Paradoc Pages

Configuring Your Pages

Header Properties

Page properties are configured in YAML Headers. The following table lists header properties that Paradoc pays attention to and uses to render your page.

YAML Header Properties

Property Purpose
title: Title rendered at top of page as <h0>
subtitle: Subtle rendered below the title in the page.
description: Description of page.
hideInNav: Whether or not to hide in the sticky page navigation.
hideInSearch: Hide page and contents in search results.
siteTemplate: HTML page template to use to control overall layout of page (optional defaults to siteTemplate.html)
linkText: Text for links to the page (in the sticky navigation header)
nextPage: Page that should come after this page in navigation header and search results ordering.
rootPage: Root “main” page that (usually readme.html/index.html etc)

Adding Pages

To Add a new page after your current page:

  1. Set the nextPage: property of your current page’s YAML header to be the root name of the new page (myNextPage).
  2. Make sure myNextPage.html exists and has the proper Paradoc script include.
  3. As always make sure your current page and next page both include a rootPage: header property pointing back to the “first” page they are child pages of (usually readme or index).
The current page would be configured similar to:
<script src="site/Paradoc.js"></script>
---
title: My Current Page
nextPage: myNextPage
rootPage: readme
---
myNextPage.html would be configured as:
<script src="site/Paradoc.js"></script>
---
title: My Next Page
rootPage: readme
---

The Site Template

TODO: Document this.

Styles

Paradoc Style Support

Styles And Stuff

Styles can be authored in plain .css and included in your siteTemplate as a regular css file, but Paradoc also supports Stylus files also without any build step/server. Stylus config goes into files with a .html file (or preferably a .styl.html file - for clarity), and use standard Stylus syntax, with the exception of requiring a single single script tag on the first line, just as with markdown files.

<script src="site/Paradoc.js"></script>
.title-area
  min-height: 100px
  box-sizing: border-box
  antialias()
  text-align: center

The default Stylus file is theme-white/theme.styl.html. You may edit it and reload the page to see the changes.

Note: Check the console for errors parsing your Stylus syntax.

Create more .styl.html files and add them to the list of files in the stylusFetcher loaded as explained in Adding Files section.

Fonts

Paradoc comes with two vendored fonts.

These two font names are referenced in theme-white/theme.styl.html. CodingFont is actually Fira, and WordFont is actually Roboto, but they have been renamed. See their respective licenses in fonts/.

Customizing Font

You can either replace CodingFont and WordFont with two css files that contain your desired fonts, but rename those fonts to be CodingFont/WordFont respectively. This would work well if you are replacing those fonts with an open licensed font.

If you want to use a proprietary font when publishing your page online, but want to keep your documentation open source, Paradoc also supports a “layered” approach. Two additional custom fonts (PrivateCodingFont and PrivateWordFont) are automatically prioritized if they are present in the repo.

These allow you to keep the CodingFont/WordFont in a public Github repo, but then locally define these private fonts which are never pushed publicly to a repo. This allows you to easily open source every part of your docs site except private fonts, which you personally use locally, and will push to production.

Once you create the propper css files in those locations that define fonts named PrivateCodingFont and PrivateWordFont respectively, those fonts will be used to render code examples and text respectively, otherwise the included CodingFont and WordFont fonts will be used as a fallback.

Note: These private fonts are not present in this github repo, but you may populate them with your custom fonts as follows:

Creating Font Files:

Creating Your Own Private Font Files: To create your own PrivateCodingFont.css/PrivateWordFont.css use a site like https://transfonter.org/ to turn your prefered fonts into inlined CSS fonts (Select woff, and select the base64 option). Then edit the resulting CSS file to change the name of the font to PrivateCodingFont or PrivateWordFont and place them at ./fonts/PrivateCodingFont.css and ./fonts/PrivateWordFont.css respectively.

Integration

Playing Well With Github and Editors

This page tells you how to:

If none of that is interesting to you then this page is not for you. You just keep writing .html markdown files with a single script tag at the top, and (optional) YAML headers:

<script src="site/Paradoc.js"> </script>
---
title: You don't even need to include this --- YAML header
---
Nothing fancy  for you!
- Just regular markdown files
- With a single <script></script> tag at the top.

For the rest of you, read on.

All The Integrations

The rest of this page explains each of the Github/editor/browser integration options in detail. Here’s a quick example of using all the integrations at once at the start of an html markdown file. This example:

[//]: # ( vim: set filetype=Markdown: )
[//]: # (<style type="text/css">body {visibility: hidden} </style>)
[//]: # (<meta charset="utf-8">)
[//]: # (<script src="site/Paradoc.js"> </script>)
---
title: My Page Title
rootPage: readme
---

Hiding The YAML headers in Github preview

To take it a step further, you can hide the YAML headers in Github’s preview rendering, while still providing that header information to Paradoc for configuring your page. Just include the YAML yeader lines in comments as well. The previous example becomes:

[//]: # ( vim: set filetype=Markdown: )
[//]: # (<style type="text/css">body {visibility: hidden} </style>)
[//]: # (<meta charset="utf-8">)
[//]: # (<script src="site/Paradoc.js"> </script>)
[//]: # (---)
[//]: # (title: My Page Title)
[//]: # (rootPage: bookmark)
[//]: # (---)

Background

Github by default will not render a README.html (or any .html file) as markdown, unless it knows it’s a markdown file. Similarly, vim/emacs will not highlight an html file as markdown unless you instruct it to.

The way that you instruct Github and Vim to treat the html file as a markdown file is the same. You must include the text vim: set filetype=Markdown: somewhere in the first line. You could stick the text vim: set filetype=Markdown: at the top of your file, and it would work but Github would also render that literal text which is not what you want.

Comments To The Rescue

Markdown supports comments of the following form:

[//]: # (you can put anything you want here)

The text between the ( ) will not be rendered by Github’s preview, and Paradoc will also ignore then when rendering the page.

Make Github Render Markdown Preview

While it won’t be rendered, fortunately Vim/Github will still search for vim: set filetype=Markdown: inside the parenthesis, so we can include a markdown comment at the top of the document that tells Github/editors to treat this file as markdown even though it has an html extension.

[//]: # ( vim: set filetype=Markdown: )

Hide The Script Tag In Github Preview

Github will also render the initial <script> include at the top of files as plain text which is not what you want. You wanted to use a single .html source of truth as your main Paradoc page, and have it render nicely on Github! We can use the same markdown comment trick that we used with the vim filetype line to hide the script tag in Github’s preview. Let’s add this to the previous example:

[//]: # ( vim: set filetype=Markdown: )
[//]: # (<script src="site/Paradoc.js"> </script>)
Your regular markdown _here_.

Now Github will render your Paradoc .html page as a markdown preview in your repo. Pretty cool! There’s one small problem. When in development mode (locally authoring/reloading) there might be a small flash of unstyled text when reloading depending on how fast you reload (the contents up until the script tag). We can fix that by including a page hider in yet another markdown comment (inserted before the script include).

[//]: # ( vim: set filetype=Markdown: )
[//]: # (<style type="text/css">body {visibility: hidden} </style>)
[//]: # (<script src="site/Paradoc.js"> </script>)
Your regular markdown _here_.

So now we have a single source of truth .html page that can function as both a Paradoc website, and render nicely in your Github repo’s markdown preview, and it feels great when reloading it locally in development mode.

Hide The YAML header In Github Preview

[//]: # ( vim: set filetype=Markdown: )
[//]: # (<style type="text/css">body {visibility: hidden} </style>)
[//]: # (<script src="site/Paradoc.js"> </script>)
Your regular markdown _here_.

Silent Github YAML Headers

If you are using a single source of truth for both Github markdown preview and your Paradoc website, you might want to hide the YAML headers in the Github preview (Github renders them as a nice looking table, but maybe you want to omit them entirely).

Paradoc provides a solution using - you guessed it - markdown comments! Paradoc supports embedding (“silent”) YAML headersl in markdown comments. This is a bookmark specific feature. Github and all other markdown tooling will ignore these headers, but Paradoc will still pay attention to them to configure your page. We’ll continue building from the previous example, and addd silent YAML headers.

[//]: # ( vim: set filetype=Markdown: )
[//]: # (<style type="text/css">body {visibility: hidden} </style>)
[//]: # (<script src="site/Paradoc.js"> </script>)
[//]: # (---)
[//]: # (title: My Page Title)
[//]: # (rootPage: readme)
[//]: # (---)
Your regular markdown _here_.

This prevents the header metadata from being rendered as a table in Github’s viewer, but Paradoc will still extract them just as if they were YAML headers. The result is a single Paradoc doc that serves as a Github viewable markdown page, as well as powering a website.

Developing In Safari:

Safari does not interpret the encoding of files as utf-8 by default unless the html document has <meta charset="utf-8"> at the top of the file. That means any .html page, or style .html page must have <meta charset="utf-8"> at the top, if you want to be able to load it in Safari. This only effects development mode because normally you would perform a build of the site before deploying it, where the encoding issue doesn’t arise.

Putting everything together gives us the following file:

[//]: # ( vim: set filetype=Markdown: )
[//]: # (<style type="text/css">body {visibility: hidden} </style>)
[//]: # (<meta charset="utf-8">)
[//]: # (<script src="site/Paradoc.js"> </script>)
[//]: # (---)
[//]: # (title: My Page Title)
[//]: # (rootPage: readme)
[//]: # (---)
Your regular markdown _here_.

More Options:

Emacs File Detection

Instead of using the Vim file detection line to trick Github into rendering yor preview, you could use the following line using the emacs file detection form. This is the same as the Vim form except it will tell Emacs to highlight as Markdown instead of telling Vim to do so.

[//]: # (-*-mode:markdown-*-)

How Paradoc Works

README.md.html is both a valid html page and a valid markdown page. Because browsers allow loading of html pages in iframes across origins, no web server is needed to develop and reload docs entirely in the browser without a build step/web server.

README.md.html looks like:

<script src="site/Paradoc.js"></script>
Everything _after_ the first line is
plain **markdown**.
1. Nothing needs to be escaped.
2. Not even if your markdown contains
  a `<script>` tag.

Everything after the first line is plain markdown. There is nothing special you need to do to your markdown even though it is in an .html file. You can include literally any markdown after that first script tag line, and you don’t have to escape any of it. The browser won’t even think you’re starting a script region if you include a <script> tag somewhere after the first line. How? The inclusion of the first Paradoc.js script forces the rest of the document to be interpreted as plain text that needn’t be escaped.

When you have your script include be specified in a markdown comment like this:

[//]: # (<script src="site/Paradoc.js"> </script>)
Everything _after_ the first line is
plain **markdown**.
- Even this `<script>` text.

Then the browser will still run the script tag as usual, and Paradoc will delete all the text content that was included before the first line’s ‘<script. The fact that the script include is inside of a markdown comment tells Github rendering to not show the <script> tag.

.gitattributes Approach:

There is an approach to getting Github to render your .html page as markdown that uses .gitattributes. This is left as an exercize to the reader.