Finished HastySite site.
h3rald h3rald@h3rald.com
Sun, 12 Nov 2017 16:32:20 +0100
14 files changed,
404 insertions(+),
33 deletions(-)
jump to
M
hastysite.nim
→
hastysite.nim
@@ -38,7 +38,6 @@ contents: seq[JsonNode]
assets: seq[JsonNode] HastySite* = object settings*: JsonNode - metadata*: JsonNode checksums*: JsonNode scripts*: JsonNode dirs*: HastyDirs@@ -299,9 +298,6 @@ hs.dirs.output.removeDir
def.symbol("clean-temp") do (i: In): hs.dirs.temp.removeDir - - def.symbol("metadata") do (i: In): - i.push i.fromJson(hs.metadata) def.symbol("settings") do (i: In): i.push i.fromJson(hs.settings)
M
nifty.json
→
nifty.json
@@ -35,8 +35,8 @@ "src": "https://github.com/h3rald/min.git"
}, "moustachu": { "name": "moustachu", - "src": "https://github.com/h3rald/moustachu", + "src": "https://github.com/fenekku/moustachu", "git": true } } -}+}
M
site/assets/styles/site.css
→
site/assets/styles/site.css
@@ -1,3 +1,9 @@
#page-getting-started .unstyled li a::before { content: none; } + +footer p { + font-size: 0.8em; + line-height: 1em; + margin: 5px 0; +}
A
site/contents/_default-rules_.md
@@ -0,0 +1,7 @@
+* Ignores contents and assets starting with [.](class:kwd) or [\_](class:kwd). +* Pre-processes [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables) in all [.css](class:ext) files. +* Processes text as [HastyScribe](https://h3rald.com/hastysite)-compatible Markdown in all [.md](class:ext) content files. +* Associates contents to [mustache](https://mustache.github.io/) templates based on the value of the [content-type](class:kwd) metadata property. +* Copies each asset file "as-is" to the [output](class:dir) directory, respecting the source directory structure in the [asset](class:dir) directory. +* Copies each content file to a directory within the [output](class:dir) named after the source content ID, in an [index.html](class:file) file (to easily obtain "pretty URLs" ending with no extension). +
A
site/contents/_site-structure_.md
@@ -0,0 +1,17 @@
+* assets/ — _Your site assets_ + * fonts/ + * styles/ +* contents/ — _Your site contents._ +* output/ — _Your static web site._ +* rules.min — _Rules to process your contents and assets._ +* scripts/ — _Scripts to manage your site._ +* settings.json — _Your site configuration._ +* temp/ — _Temporary files and folders will be placed here._ +* templates/ — _Mustache templates._ + + +> %tip% +> Tip +> +> Default folder paths can be configured in your [settings.json](class:file) file. +
M
site/contents/about.md
→
site/contents/about.md
@@ -4,3 +4,29 @@ title: "About"
content-type: page ----- +HastySite is a static-site generator, similar to [hundreds](https://www.staticgen.com/) of others. Why bother with yet another one then? + +Because HastySite: + +* has been designed with minimalism in mind. It does not provide many features on its own, but it can be extended do do almost anything you'd want it to do. +* is only comprised by a single executable file, available pre-compiled for all major desktop platforms, and it can be compiled to run on even more via [Nim](https://nim-lang.org). +* embeds a concatenative programming language in it, that can be used to customize almost every aspect of it. +* can be extended, from the way it processes files to creating custom commands to do literally what you want. +* provides a simple but functional fully-working site template out-of-the-box, which is also the same template used for its [web site](https://hastysite.h3rald.com). +* provides out-of-the-box Markdown support. But not just any markdown, [HastyScribe](https://h3rald.com/hastyscribe)-compatible markdown, which extends the alredy-amazing and powerful [Discount](https://www.pell.portland.or.us/~orc/Code/discount/) engine with more useful features such as snippets, macros, fields and transclusion. +* provides a robust logic-less templating engine based on [mustache](https://mustache.github.io/). +* provides support for [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables), which doesn't substitute a full fledged CSS preprocessor like LESS or SASS, but it does help. + + +## Technology and Credits + +HastySite has been built leveraging the following open source projects: + +* The [min](https://min-lang.org) programming language. +* The [HastyScribe](https://h3rald.com/hastyscribe) markdown compiler. +* The [moustachu](https://github.com/fenekku/moustachu) mustache template engine. + +Special thanks also to the creators and maintainers of the following projects, that made HastySite possible: + +* The [Nim](https://nim-lang.org) programming language, used to develop HastySite and all the above-mentioned projects. +* The [Discount](https://www.pell.portland.or.us/~orc/Code/discount/) markdown compiler, used as the basis for HastyScribe.
M
site/contents/customization.md
→
site/contents/customization.md
@@ -4,18 +4,111 @@ title: "Customization"
content-type: page ----- +By default, HastySite provide all the scripts and rules necessary to build a simple blog with static pages and timestamped blog posts. While this may work for a simple blogging site, you may need additional features like support for tags, or maybe group articles by months, or project pages with custom metadata, and so on. + +HastySite can be customized to your heart content essentially in the following ways: + +* By modifying the [rules.min](class:file) file and tweak the build pipeline. +* By creating custom scripts to create generators for custom content types, or any other task you deem useful for your use case. +* By leveraging HastyScribe advanced features for content reuse, like snippets, fields, macros, and transclusions. ## Default Build Pipeline +Before diving into customization techniques, you should be familiar with the way HastySite builds your site out-of-the-box. If you have a look at the [scripts/build.min](class:file) file, it looks like this: + +``` +;Builds a site by processing contents and assets. +'hastysite import + +"Preprocessing..." notice +preprocess +"Processing rules..." notice +process-rules +"Postprocessing..." notice +postprocess +"All done." notice +``` + +Even if you are not familiar with the [min](https://minl-lang.org) programming language, this code looks straightforward enough. as part of the build process, three actions are performed: + +1. preprocess +2. process-rules +3. post-process ### Preprocess +During this phase, the following operations are performed: + +1. Some maintenance of temporary files is performed, e.g. the [temp](class:dir) directory is created and populated with a [checksums.json](class:file) file if needed, temporary contents from the previous build are deleted, and so on. +2. All contents are loaded, and metadata in the content header is processed and saved in memory. +3. All assets are loaded and bare-bones metadata is generated for them and saved in memory, as they have no header. + +If you are wondering what this content header is, it's a section at the start of a content file delimited by five dashes, and containing metadata properties, like this: + +``` +----- +id: getting-started +title: "Getting Started" +content-type: page +----- +``` + +Now, this *looks* like [YAML](http://yaml.org/), but it is actually Nim's own [configuration file format](https://nim-lang.org/docs/parsecfg.html), which is a bit more limited, but it does the job. Just remember to wrap strings with spaces in double quotes and everything will be good. + +Internally, after the preprocessing phase all contents and assets will have the following metadata: + +id +: An identifier for the content or asset, corresponding to the path to the file relative to the [contents](class:dir) or [assets](class:dir) folder, without extension. +path +: The path to the file relative to the [contents](class:dir) or [assets](class:dir) folder, *including* extension. +type +: Either **content** or **asset**. +ext +: The file extension (including the leading [.](class:kwd)). ### Process Rules +In this phase, the control of the build process is passed to the [rules.min](class:file) script. It is important to point out that in case of an empty [rules.min](class:file) file, *nothing* will be done and no output file will be generated. + +Luckily, a default [rules.min](class:file) file is provided, which: + +{@ _default-rules_.md || 1 @} + +Typically, you only need to modify this file to change how HastySite builds your site. ### Postprocess +In this phase, the [temp/checksums.json](class:file) is updated with the latest checksums of the generated output files. + ## Modifying the [rules.min](class:kwd) File -## Creating Scripts +The [rules.min](class:kwd) file is used to build your site. This file is nothing but a [min](https://min-lang-org) script, and therefore you should have at least a basic understanding of the min programming language before diving in and modifying it. + +In particular, you should get acquainted with the following min modules, whose symbols and sigils are typically used to create [rules.min](class:kwd) files: + +* [lang](https://min-lang.org/reference-lang/) +* [seq](https://min-seq.org/reference-seq/) +* [str](https://min-str.org/reference-str/) +* [time](https://min-time.org/reference-time/) + +Additionally, a dedicated [hastysite](class:kwd) module is also provided specifically for HastySite, which is described in the Reference section. + +## Creating Commands + +Once you are comfortable with witing min scripts and maybe after you modified the [rules.min](class:file) file, you could try modifying or adding new HastySite commands. To do so, you must: + +1. Create a new [.min](class:ext) file named after your command (e.g. [project.min](class:file)) and place it in the [scripts](class:dir) folder of your site. +2. On the first line, enter a min comment corresponding to the description of your command. This description will be used by HastySite help system. +3. On the subsequent lines, write the logic of your command in min. + +For more information and examples, have a look at the default scripts generated by the <samp>hastysite init</samp> command. + +## Leveraging HastyScribe Advanced Features + +In some cases, you may not even need to edit [.min](class:kwd) files to customize the way your site pages are rendered. In particular, [HastyScribe](https://h3rald.com/hastyscribe), the Markdown engine that powers HastySite, provide a lot of extra feature aimed at improving content reuse, such as: + +* [Transclusion](https://h3rald.com/hastyscribe/HastyScribe_UserGuide.htm#Transclusion), to basically load the contents of a Markdown file into another. +* [Snippets](https://h3rald.com/hastyscribe/HastyScribe_UserGuide.htm#Snippets), to reuse chunks of text in the same file (and transcluded files). +* [Fields](https://h3rald.com/hastyscribe/HastyScribe_UserGuide.htm#Fields), to specify things like current date and time, but also custom properties defined at run time. +* [Macros](https://h3rald.com/hastyscribe/HastyScribe_UserGuide.htm#Macros), to create chunks of reusable text with placeholders. +
M
site/contents/getting-started.md
→
site/contents/getting-started.md
@@ -48,23 +48,7 @@ > hastysite init
This will create the following default directory structure: - -* assets/ — _Your site assets_ - * fonts/ - * styles/ -* contents/ — _Your site contents._ -* output/ — _Your static web site._ -* rules.min — _Rules to process your contents and assets._ -* scripts/ — _Scripts to manage your site._ -* settings.json — _Your site configuration._ -* temp/ — _Temporary files and folders will be placed here._ -* templates/ — _Mustache templates._ - - -> %tip% -> Tip -> -> Default folder paths can be configured in your [settings.json](class:file) file. +{@ _site-structure_.md || 1 @} Then, create your first page by running the following command and specifying the page ID and Title:
M
site/contents/home.md
→
site/contents/home.md
@@ -16,5 +16,6 @@ > * [](class:check) Fully configurable content and asset processing pipeline, using the [min](https://min-lang.org) programming language.
> * [](class:check) Custom script definition, using the [min](https://min-lang.org) programming language. > * [](class:check) Default stylesheet and fonts from [HastyScribe](https://h3rald.com/hastyscribe). > * [](class:check) Default scripts and rules to get started quickly. +> * [](class:check) All packed in a single executable file, with no dependencies, available for the most common desktop platforms.
M
site/contents/reference.md
→
site/contents/reference.md
@@ -4,6 +4,170 @@ title: "Reference"
content-type: page ----- -## Default Content Metadata +This section provides some reference information related to the default metadata of contents and assets, as well as the full documentation of the [hastysite](class:kwd) min Module. + +## Default Content and Asset Metadata + +The following table lists all the default metadata properties available for contents and assets, and also after which build phase they become available. + +> %note% +> Note +> +> You can define your own custom metadata for contents in a header section delimited by five dashes, at the start of each content file. + +> %responsive% +> Property | Content | Asset +> ---------------|-----------------------|----------------- +> id | [](class:check) | [](class:check) +> path | [](class:check) | [](class:check) +> ext | [](class:check) | [](class:check) +> type | [](class:check) | [](class:check) +> title | [](class:check)^1 | [](class:square) +> content-type | [](class:check)^1 | [](class:square) +> date | [](class:check)^(1,2) | [](class:square) +> timestamp | [](class:check)^(1,2) | [](class:square) +> contents | [](class:check)^3 | [](class:check)^3 + +> %unstyled% +> * <sup>1</sup> This property is defined for all **page** and **post** contents created using the default [page](class:kwd) and [post](class:kwd) commands. +> * <sup>2</sup> This property is defined for all **post** contents created using the default [post](class:kwd) command. +> * <sup>3</sup> This property *must* be added to contents and assets before they can be written to the output folder. This can be done implicitly using symbols provided with the [hastysite](class:kwd) min module. ## [hastysite](class:kwd) min Module + +This [min](https://min-lang.org) module can be imported in the [rules.min](class:kwd) file or in any script file and can be used to perform common operations such as ready and writing files, and interact with HastySite data at build time. + +{{null => ∅}} +{{d => [dict](class:kwd)}} +{{q => [quot](class:kwd)}} +{{m => [meta](class:kwd)}} +{{qm => [(meta<sub>\*</sub>)](class:kwd)}} +{{q1 => [quot<sub>1</sub>](class:kwd)}} +{{q2 => [quot<sub>2</sub>](class:kwd)}} +{{s => [string](class:kwd)}} +{{s1 => [string<sub>1</sub>](class:kwd)}} +{{s2 => [string<sub>2</sub>](class:kwd)}} + +{#op => +<a id="op-$1"></a> +### [$1](class:kwd) + +> %operator% +> [ $2 **⇒** $3](class:kwd) +> +> $4 + #} + +{#op||assets||{{null}}||{{qm}}|| +Returns a quotation of metadata dictionaries {{qm}} containing the metadata of each asset file. + #} + +{#op||clean-output||{{null}}||{{null}}|| +Deletes all the contents of the [output](class:dir) directory. + #} + +{#op||clean-temp||{{null}}||{{null}}|| +Deletes all the contents of the [temp](class:dir) directory. + #} + +{#op||contents||{{null}}||{{qm}}|| +Returns a quotation of metadata dictionaries {{qm}} containing the metadata of each content file. + #} + +{#op||input-fread||{{m}}||{{s}}|| +Reads the contents of the file identified by the metadata dictionary {{m}} (such as those returned by the [contents](class:kwd) and [assets](class:kwd) parameters). + +Note that: + +* The source directory is determined by the value of the [type](class:kwd) metadata property. +* The path within the source directory is determined by the value of the [path](class:kwd) metadata property. + #} + +{#op||markdown||{{s1}} {{d}}||{{s2}}|| +Converts the [HastyScribe](https://h3rald.com/hastyscribe) Markdown string {{s1}} into the HTML fragment {{s2}}, using the properties of {{d}} as custom fields (accessible therefore via HastyScribe's [\{\{$<field-name>\}\}](class:kwd) syntax). + #} + +{#op||mustache||{{s1}} {{d}}||{{s2}}|| +Renders mustache template {{s1}} into {{s2}}, using dictionary {{d}} as context. + +> %note% +> Note +> +> {{s1}} is the path to the mustache template file, relative to the [templates](class:dir) directory and without [.mustache](class:ext). + #} + +{#op||output||{{null}}||{{s}}|| +Returns the full path to the [output](class:dir) directory. + #} + +{#op||output-cp||{{m}}||{{null}}|| +Copies a file from the source directory ([contents](class:dir) or [assets](class:dir) depending on its [type](class:kwd)) to the [output](class:dir) directory. + +Note that: + +* The source directory is determined by the value of the [type](class:kwd) metadata property. +* The path within the source directory is determined by the value of the [path](class:kwd) metadata property. +* The destination path within the output directory is determined by the value of concatenation of the [id](class:kwd) and [ext](class:kwd) metadata properties. +* The contents of the file are retrieved from the [contents](class:kwd) metadata property (in case of contents) or the contents of the original file (in case of assets). + + #} + +{#op||output-fwrite||{{m}}||{{null}}|| +Writes the contents of the file identified by the metadata dictionary {{m}} (such as those returned by the [contents](class:kwd) and [assets](class:kwd) parameters). + +Note that: + +* The destination path within the output directory is determined by the value of concatenation of the [id](class:kwd) and [ext](class:kwd) metadata properties. +* The contents of the file are retrieved from the [contents](class:kwd) metadata property (in case of contents) or the contents of the original file (in case of assets). + + #} + +{#op||postprocess||{{null}}||{{null}}|| +Starts the postprocessing phase of the build. + #} + +{#op||preprocess||{{null}}||{{null}}|| +Starts the preprocessing phase of the build. + #} + +{#op||preprocess-css||{{s1}}||{{s2}}|| +Pre-process [CSS variable](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables) declarations and usages within {{s1}}, returning the resulting CSS code {{s2}}. + +For example, the following CSS code: + +``` +:root { + --standard-gray: #cccccc; +} + +.note { + background-color: var(--standard-gray); +} +``` + +Will be converted to the following: + +``` +:root { + --standard-gray: #cccccc; +} + +.note { + background-color: #cccccc; +} +``` + +> %warning% +> Limitation +> +> Only basic support for CSS variables is provided, e.g. no fallback values are supported. + #} + +{#op||process-rules||{{null}}||{{null}}|| +Starts the processing phase of the build, and interprets the [rules.min](class:file) file. + #} + +{#op||settings||{{null}}||{{d}}|| +Returns a dictionary {{d}} containing all the settings defined in the [settings.json](class:file) file. + #} +
M
site/contents/usage.md
→
site/contents/usage.md
@@ -4,29 +4,101 @@ title: "Usage"
content-type: page ----- -HastySite is a simple command-line program that supports some default commands and options, described in the following sections. Additionally, you can configure your own programs by creating your own [min](https://min-lang.org) scripts. +HastySite is a simple command-line program that supports some default commands and options, described in the following sections. + +## Syntax + +<code> +**hastysite** *command* [ *options* ] +</code> + ## Default Commands +The following sections define the default commands provided by HastySite. All of them except for [init](class:kwd) can be modified, and you can also configure your own commands by creating your own [min](https://min-lang.org) scripts and placing them in the [scripts](class:dir) directory. + +{#customizable-command => +> %note% +> Note +> +> This command can be customized by modifying the [scripts/$1.min](class:file) file within your site directory. + #} + ### build +Builds the site by preprocessing contents and assets, processing rules defined in the [rules.min](class:file) file, and creating a temporary file containing the checksums of all newly-generated files. By doing so, the next time this command is executed, only the files that have actually been modified will be copied to the [output](class:dir) directory. + +The [rules.min](class:file) file processed by this command: + +{@ _default-rules_.md || 1 @} + +{#customizable-command||build#} ### clean +Deletes all files and directories in the [output](class:dir) and [temp](class:dir) directories. + +{#customizable-command||clean#} + +### init + +Initializes a new HastySite site directory, by creating the following directory structure: + +{@ _site-structure_.md || 1 @} + ### page +Generates an empty page content file containing initial metadata. This command asks the user for the following information: + +* A valid ID composed only by letters, numbers, and dashes that has not yet been used for another page. +* The title of the page. + +After information has been provided, a new content will be created in the [contents](class:dir) directory containing the following metadata properties: + +* id +* title +* content-type (set to **page**) + +{#customizable-command||page#} ### post +Generates an empty post content file containing initial metadata. This command asks the user for the following information: + +* A valid ID composed only by letters, numbers, and dashes that has not yet been used for another post. +* The title of the post. + +After information has been provided, a new content will be created in the [contents/posts](class:dir) directory containing the following metadata properties: + +* id +* title +* content-type (set to **post**) +* timestamp (set to the Unix timestamp of the creation of the content) +* data (set to a date string corresponding to the creation of the content) + +{#customizable-command||post#} ## Options +By default, HastySite provides the following options to display information about the program or alter its behavior. ### -h, \-\-help +Displays the description of all HastySite commands and options. -### -l, \-\-loglevel + +### -l=_level_, \-\-loglevel=_level_ + +Sets the log level to one the following values: +* debug +* info +* notice (default) +* warn +* error +* fatal ### -v, \-\-version + +Displays the HastySite version string.
M
site/rules.min
→
site/rules.min
@@ -30,7 +30,6 @@ meta /content-type :tpl
meta ( (input-fread @contents meta) (settings /title %site-title) - (settings /base-url %site-base-url) (=temp contents temp markdown @contents temp) (contents %contents) (=temp tpl temp mustache @page temp)@@ -53,13 +52,19 @@
;;; Main ;;; ;Filter and sort posts by timestamp -contents (/content-type "post" ==) filter (=a =b a /timestamp b /timestamp >) sort =posts +contents + (?content-type) filter + (/content-type "post" ==) filter + (=a =b a /timestamp b /timestamp >) sort =posts ;Process contents contents ( (dict) expect -> =content content (/id "news" ==) (content posts %posts #content) when - content process-content set-destination output-fwrite + ( + ((content /id "/" split last "^[._]" match) ()) ;Ignore files starting with a dot or underscore + ((true) (content process-content set-destination output-fwrite)) + ) case ) foreach ;Process assets@@ -68,7 +73,7 @@ (dict) expect ->
dup ( ((/ext ".css" match) (process-css-asset)) - ((/id "^\." match) ()) ;Ignore hidden files + ((/id "/" split last "^[._]" match) ()) ;Ignore files starting with a dot or underscore ((true) (output-cp)) ) case ) foreach
M
site/settings.json
→
site/settings.json
@@ -6,6 +6,5 @@ "temp": "temp",
"output": "output", "scripts": "scripts", "title": "HastySite", - "base-url": "", "rules": "rules.min" }