alistair
3 years ago
5 changed files with 456 additions and 269 deletions
@ -1,172 +0,0 @@
@@ -1,172 +0,0 @@
|
||||
--- |
||||
title: stgen3 |
||||
author: Alistair Michael |
||||
date-in-format: %Y |
||||
date: 2021 |
||||
notemplating: yes |
||||
--- |
||||
|
||||
`stgen3` is a static site generator written in C++17, which uses the MultiMarkdown |
||||
markdown parser to generate html. It aims to be fast, portable, and simple to use |
||||
without configuration. |
||||
|
||||
### Features |
||||
|
||||
- minimalistic templating system |
||||
- single static binary with no dependencies |
||||
- no config required |
||||
- templates and configuration exist alongside the markdown source |
||||
- configuration and templates are inherited down the directory structure |
||||
- [Multimarkdown 6 syntax](https://fletcher.github.io/MultiMarkdown-6/) |
||||
|
||||
Note: not all of the following functionality is supported yet. |
||||
|
||||
### Dependencies |
||||
|
||||
- nlohmann json |
||||
- MultiMarkdown (clone into the directory `MultiMarkdown` and compile) |
||||
- enable the token pool |
||||
- date.h (hopefully can be replaced with C++20 `std::chrono` one day) |
||||
- spdlog |
||||
- xxd |
||||
|
||||
### Building |
||||
|
||||
1. Clone project |
||||
2. Clone MultiMarkdown 6 into the folder `MultiMarkdown`, enable the token pool |
||||
and compile it. |
||||
2. Ensure xxd is installed and run the script `defaults.sh` |
||||
3. `mkdir build && cd build && cmake .. && make` |
||||
|
||||
### Basic Behaviour |
||||
|
||||
Provided with a source directory, and an output directory, it recurses through |
||||
the source directory compiling all markdown files to html and writing them to |
||||
the destination directory, while copying all other files that are not on the |
||||
ignored list. |
||||
|
||||
Ignored files list: |
||||
|
||||
- `stgen.json` |
||||
- anything ending in `.template` |
||||
|
||||
### Example |
||||
|
||||
Running the following command where, the `src` and `dest` directories do not |
||||
exist will create a new template site and build it into the dets directory. |
||||
|
||||
```sh |
||||
$ stgen3 src dest |
||||
``` |
||||
|
||||
### Configuration |
||||
|
||||
Configuration files must be named `stgen.json`, and contain a json string-string |
||||
map of attributes. These files can be placed anywhere in the site and their |
||||
values are inherited down the file tree from that point. Repeatedly specifying |
||||
the same attribute overwrites it. |
||||
|
||||
The main attributes that should be set are |
||||
|
||||
- `url` : the root url of the site |
||||
- `name` : the name of the site |
||||
|
||||
For sub-directories, `date` can be set to determine its position in directory |
||||
listings sorted by date. |
||||
|
||||
### Per-Article Configuration |
||||
|
||||
Behaviour can be modified by configuration in the article's heading block. |
||||
Heading blocks must start at the first line of the file. They may have `---` on |
||||
the first and last line. |
||||
|
||||
- `notemplating`: disable templating for the file |
||||
- `template`: the html template to substitute content into |
||||
|
||||
## Templating |
||||
|
||||
### Syntax |
||||
|
||||
Templates are surrounded by `{{ }}` braces, they consist of a command name |
||||
followed by a colon separated list of arguments. Any starting or trailing |
||||
whitespace on commands or arguments is ignored. |
||||
|
||||
Templates can be escaped using a preceding backslash `\{{ }}`. By default, |
||||
templating is run against all markdown documents only, and there is no way to |
||||
disable this yet. |
||||
|
||||
### Variable substitution |
||||
|
||||
Templates that are replaced with variables are simply a colon followed by the |
||||
variable name. |
||||
|
||||
``` |
||||
{{ :date }} |
||||
``` |
||||
|
||||
Variables are set in both article headers and `stgen.json`. |
||||
|
||||
Some variables are guaranteed to exist for any article in the system, this |
||||
includes: |
||||
|
||||
- `url` : The website's url, it defaults to the output directory absolute path |
||||
- `page_url` : The absolute url of the page. |
||||
- `name` : The name of the site, it defaults to the input directory name |
||||
- `last_updated` : Set to the last write time of the file |
||||
- `current_file` : The absolute path of the file in the compiling machine |
||||
- `current_directory` : the directory containing the file |
||||
- `current file` : the file being processed |
||||
|
||||
Any metavalues set in page headers are accessible as variables. Generally `title` |
||||
and `date` should be set. |
||||
|
||||
- `title`: the article's title |
||||
- `date`: the publish date of the article |
||||
- `author`: the article's author |
||||
|
||||
|
||||
### Directory listings |
||||
|
||||
``` |
||||
{{ postlist:relative/path/to/directory }} |
||||
``` |
||||
|
||||
Directory listings are sorted by the date of the post. Subfolders are ordered |
||||
first by their date set in `stgen.json`, then the date of the most recent |
||||
article in them, or placed last. |
||||
|
||||
Dates are expected to be in the format `yyyy-mm-dd`. |
||||
|
||||
### Flow Control |
||||
|
||||
``` |
||||
{{ ifdef:attribute: |
||||
Content to include |
||||
}} |
||||
``` |
||||
|
||||
The content of the last argument is included in the document if the specified |
||||
attribute is set to something. |
||||
|
||||
The `ifndef` command includes content if the attribute is _not_ set. Template tags can be |
||||
nested in this case. |
||||
|
||||
``` |
||||
{{ ifdef:title |
||||
{{ :title }} |
||||
}} |
||||
{{ifndef:title |
||||
Title not set :( |
||||
}} |
||||
``` |
||||
|
||||
### Template Files |
||||
|
||||
The default template markdown files are written to can be overridden by writing |
||||
a file called `html.template`. This needs to contain the variable substitution |
||||
`{{ :body }}` in order to substitute the compiled markdown content into it. |
||||
|
||||
Templates are also inherited down the directory hierarchy. |
||||
|
||||
The default templates are compiled into the binary. |
||||
|
@ -0,0 +1,244 @@
@@ -0,0 +1,244 @@
|
||||
code { |
||||
white-space: pre-wrap; |
||||
background: #eee; |
||||
border-color: #eee; |
||||
border-radius: 6px; |
||||
border-style: solid; |
||||
border-left-width: 4px; |
||||
border-right-width: 4px; |
||||
border-top-width:1px; |
||||
border-bottom-width:1px; |
||||
} |
||||
|
||||
div.sourceCode { |
||||
background: #eee; |
||||
border-radius: 7px; |
||||
} |
||||
|
||||
pre code { |
||||
border-style: none; |
||||
background: none; |
||||
} |
||||
|
||||
code { |
||||
font-family: 'Bitstream Vera Sans Mono', 'Monospace', monospace; |
||||
} |
||||
|
||||
pre { |
||||
font-family: 'Bitstream Vera Sans Mono', 'Monospace', monospace; |
||||
background: #eee; |
||||
border-radius:6px; |
||||
padding: 0.7em; |
||||
} |
||||
|
||||
span.smallcaps { |
||||
font-variant: small-caps; |
||||
} span.underline { |
||||
text-decoration: underline; |
||||
} |
||||
div.column { |
||||
display: inline-block; |
||||
vertical-align: top; |
||||
width: 50%; |
||||
} |
||||
|
||||
dl { |
||||
padding-left:1.5em; |
||||
} |
||||
|
||||
dl dt { |
||||
font-size:0.6em; |
||||
font-weight:200; |
||||
} |
||||
|
||||
dl dd { |
||||
margin-bottom:0.7em; |
||||
|
||||
margin-left:0px; |
||||
|
||||
} |
||||
|
||||
dl dd a { |
||||
color:black; |
||||
} |
||||
|
||||
body { |
||||
font-family: 'Bitrstream Vera Sans', Helvetica Neue, Helvetica, sans-serif, sans; |
||||
font-size: 18px; |
||||
} |
||||
|
||||
|
||||
body .main_page p { |
||||
line-height:1.3em; |
||||
} |
||||
|
||||
.main_page li { |
||||
margin-top:0.3em; |
||||
margin-bottom:0.3em; |
||||
} |
||||
|
||||
img { |
||||
margin: auto; |
||||
max-width: 90%; |
||||
display: block; |
||||
} |
||||
dd { |
||||
margin-top: 5px; |
||||
margin-bottom: 7px; |
||||
} |
||||
h1 { |
||||
margin-bottom: 10px; |
||||
margin-top: 10px; |
||||
} |
||||
|
||||
h1, h2, h3, h4, h5, h6 { |
||||
font-weight:400; |
||||
} |
||||
|
||||
|
||||
a { |
||||
text-decoration:none; |
||||
color: #0066cc; |
||||
} |
||||
|
||||
|
||||
div.main_page { |
||||
padding-top: 0; |
||||
} |
||||
|
||||
hr { |
||||
border-style: solid; |
||||
color: #bbb; |
||||
border-width:0.1em; |
||||
} |
||||
pre.numberSource { |
||||
margin-left: 4; |
||||
} |
||||
|
||||
q { |
||||
quotes: "“" "”" "‘" "’"; |
||||
} |
||||
|
||||
|
||||
.grid-container { |
||||
display: grid; |
||||
grid-template-columns: 2fr 3fr 3fr 4fr; |
||||
grid-template-rows: 0.5fr repeat(0.5, 1fr); |
||||
gap: 1px 1px; |
||||
grid-template-areas: "header_group header_group header_group header_group" "menu_group main_page main_page table_of_contents" "menu_group main_page main_page table_of_contents"; |
||||
} |
||||
|
||||
.header_group { grid-area: header_group; } |
||||
|
||||
.menu_group { |
||||
grid-area: menu_group; |
||||
position:fixed; |
||||
} |
||||
|
||||
.table_of_contents { |
||||
grid-area: table_of_contents; |
||||
max-width: 100%; |
||||
} |
||||
|
||||
.main_page { |
||||
grid-area: main_page; |
||||
max-width:100%; |
||||
} |
||||
|
||||
.menu_item { |
||||
display:block; |
||||
padding:5px; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
} |
||||
|
||||
|
||||
@media (max-width: 1200px) { |
||||
.grid-container { |
||||
display: grid; |
||||
gap: 1px 1px; |
||||
grid-template-areas: "header_group header_group header_group header_group" "menu_group menu_group menu_group menu_group " "table_of_contents table_of_contents table_of_contents table_of_contents" "main_page main_page main_page main_page"; |
||||
padding-left:10px; |
||||
padding-right:10px; |
||||
max-width: 45em; |
||||
margin:auto; |
||||
} |
||||
.menu_item { |
||||
display:inline-block; |
||||
} |
||||
|
||||
.menu_group { |
||||
position:inherit; |
||||
} |
||||
|
||||
.menu_group ul { |
||||
padding:0; |
||||
} |
||||
|
||||
} |
||||
|
||||
blockquote { |
||||
border-left: #bbb; |
||||
border-left-style: solid; |
||||
border-left-width: 0.2em; |
||||
padding:0.6em; |
||||
padding-left:1em; |
||||
} |
||||
|
||||
blockquote p { |
||||
margin:0px; |
||||
} |
||||
|
||||
|
||||
|
||||
tr:nth-child(even) {background-color: #eee;} |
||||
|
||||
table { |
||||
border-collapse: collapse; |
||||
display:block; |
||||
overflow:auto; |
||||
width:100%; |
||||
margin: 0, auto; |
||||
} |
||||
|
||||
.header th { |
||||
|
||||
text-align: left; |
||||
border-bottom-style:solid; |
||||
border-left:none; |
||||
border-right:none; |
||||
|
||||
border-bottom-width:1px; |
||||
} |
||||
|
||||
td { |
||||
padding-top:0.3em; |
||||
padding-bottom:0.3em; |
||||
padding-left: 0.7em; |
||||
padding-right:0.7em; |
||||
} |
||||
|
||||
thead { |
||||
border-bottom-width: 1px; |
||||
border-bottom-style: solid; |
||||
border-bottom-color: black; |
||||
line-height: 2em; |
||||
} |
||||
|
||||
|
||||
.microblog_date { |
||||
font-size: 0.7em; |
||||
text-align: right; |
||||
} |
||||
|
||||
.microblog_post .microblog_content p { |
||||
margin-top: 0.1em; |
||||
} |
||||
|
||||
.microblog_post { |
||||
background: var(--secondary-bg); |
||||
border-radius: 0.4em; |
||||
padding: 0.5em; |
||||
margin-top:0.1em; |
||||
margin-bottom:0.1em; |
||||
} |
Loading…
Reference in new issue