rhodochrosite
v0.2.41
Published
simple static site generator with neat mind-mapping features including inline hashtags and automatic tag pages. also utility features like image minification, gallery pages and pre-configured rss/atom feeds. written in typescript, powered by metalsmith. w
Downloads
522
Maintainers
Readme
rhodochrosite
node package || git repo || discord || my website
rhodochrosite is a batteries-included, mind-mappy, multimedia-forward static site generator for node.js, built on metalsmith, with a tiny command-line interface to control it. it transforms a folder-tree of markdown files and attachments into a static, no-javascript html website, featuring blog and art gallery layouts, inline and property-based tags, rss and atom feeds, automatic image processing with sharp, and customizable layouts and styling using njk, html and css. it also includes a pre-configured dev server using five server, for testing and live-previewing the site. builds are highly incremental, and changes update quickly!
install
to install rhodochrosite, first install node.js and npm. next, create or choose a project folder. this will be the root directory of your website project; throughout this guide, this folder will be assumed to be the current working directory, and paths will be written relative to it. if you're starting a new project, this can just be a new blank folder; or, you can download a copy of this template project, and use the outermost folder rhodo-template . in any case, navigate to the folder in a terminal and use the command:
npm install rhodochrositeto install. (if you'd rather install globally, use npm install rhodochrosite -g ; but you'll need to pass some extra options to some of the commands.)
usage
rhodochrosite is controlled via a little cli made in commander.js. to use it, navigate to your project folder and use the command:
npx rhodoto show a list of all commands and options. commands follow the syntax npx rhodo command --option value . some basic commands:
npx rhodo build: build the site once and stop, using default folder names
npx rhodo watch: watch the source folder for changes and continually update the build folder; also start a dev server for live-previewing the site in a web browser.
npx rhodo build -p: build a "production version" of the site, omitting drafts, to a different default location
source files
rhodochrosite looks for markdown files to transform into web pages. a markdown file is a text file with the extension .md . markdown files for rhodochrosite have two parts, frontmatter and a body.
frontmatter
frontmatter appears at the beginning of a markdown file, between two special lines made of three hyphens. frontmatter is used in markdown files in the source to set properties of the corresponding page in the build. here is a complete example frontmatter section:
---
title: my first blog post
tags: [recipe, soup]
---this sets one property, the page's title, to "my first blog post," and adds a couple of tags (another property) - "recipe" and "soup".
body
this is the rest of the markdown file; it can contain paragraphs of text, code blocks, markdown links and embedded-image links, bits of inline html or njk, etc. for an overview of markdown syntax, start here
building the site
when building the site, rhodochrosite looks in the project folder for a source folder (called src by default) and uses it to create a build folder (called build by default) containing the finished website. each markdown file in the source folder becomes a web page on the resulting site, consisting of a folder and an index.html file.
each page has two main sections, a body and an index. the page body is where the transformed body of the markdown file is displayed; this can be paragraphs of text, links, embedded media, etc, as written in by the user.
following the body is the page index, which shows a list of titles and excerpts of other pages. which pages are listed is determined in two ways: using the folder tree, and using tags. this part is generated automatically by rhodochrosite.
the folder tree
the structure of subfolders in the source folder determines the corresponding web page's location on the site: the file src/blog/mypost.md would wind up at mywebsite.com/blog/mypost/ . since web pages in rhodochrosite consist of a folder and an index.html file, in the build folder this page would actually look like this: build/blog/mypost/index.html . but because of how web browsers look at things, the index.html part doesn't appear in the web address - just the folder name. this folder name, created from the name of the markdown file in the source folder, is a property of the page called its slug.
to recap this transformation: a folder has been created with the same name as the markdown file, and the contents of the markdown file have been transformed into an html webpage and moved to a file called index.html inside the folder. (links are also updated as necessary to work with the folder change.)
if a markdown file is named index.md, it gets special treatment. it's still transformed to index.html, but instead of being placed in a new folder, this file simply stays in place and becomes the index.html of its existing parent folder. so for example, src/blog/index.md becomes a page at mywebsite.com/blog/, with the slug blog . in the build folder, it looks like build/blog/index.html .
the structure of the surrounding folder tree of pages is the first of two criteria for building a page's index section. since each page consists of a folder (with the name being that page's slug) and an index.html file, pages can contain other pages. for example, and combining our earlier examples, the page mywebsite.com/blog/ (build/blog/index.html) contains the page mywebsite.com/blog/mypost/ (build/blog/mypost/index.html) in the folder part of its page structure. when a page contains another page like this, that inner page will be included in the outer page's index section.
- src/
- blog/
- index.md
- mypost.md
- blog/
- build/
- blog/
- index.html
- mypost/
- index.html
- blog/
this shows a basic blog setup. each blog post starts as a markdown file like src/blog/mypost.md and becomes a page like mysite.com/blog/mypost/, nested within the outer page mysite.com/blog/; and that outer page, that started as src/blog/index.md, indexes all the posts because they're one level down in the folder tree of pages. actually, it's not even necessary to include that src/blog/index.md file in the source folder - if rhodochrosite sees a folder which contains pages, but has no index.md to transform, it will automatically create an index page there instead. pagination is also added to the footer of each post, for navigating to next/previous entries.
of course, the inner pages could be folders, too - in our example, src/blog/mypost.md could be replaced with src/blog/mypost/index.md and get the same results. this makes for a nice way to bundle attachments; say our blog post includes an image, we might structure the source folder so that src/blog/mypost/ includes both src/blog/mypost/index.md and src/blog/mypost/mypic.png . then we can link to the image like so in the markdown file:
and, since the inner page is now a folder itself, it can contain and index yet more pages nested one level deeper; and those could contain further pages and so on, as deep as you like. indexing goes exactly one level deeper starting at the current page; mysite.com/media/ indexes mysite.com/media/books/ but not mysite.com/media/books/fiction/, mysite.com/media/books/ indexes mysite.com/media/books/fiction/ but not mysite.com/media/books/fiction/romance/, and so on. here's one valid example of how all that could look:
src/
- media/
- index.md
- books/
- fiction/
- index.md
- romance.md
- fiction/
- media/
build/
- media/
- index.html
- books/
- index.html
- fiction/
- index.html
- romance/
- index.html
- media/
and since every page in the finished site has an index.html file, we can just assume they're all there, and omit them in our digram to simplify its appearance; leaving only the nested structure of pages on the site.
- mysite.com/
- media/
- books/
- fiction/
- romance/
- fiction/
- books/
- media/
tags
the second criteria for building a page's index section is tags. tags are a way of identifying a page for inclusion in another page's index, based on a property of that other page called its tagslug. they can be used in two ways, inline and in frontmatter.
tagslugs
tagslugs are the receiving counterpart to tags; if page A's tagslug matches any tags on any other page B, page B will be included in page A's index section. tags mark a page to be listed by another page, and tagslugs tell a page which other pages to list. by default, a page's tagslug is just its slug, but something else can be specified in frontmatter. if src/cookbook.md had this frontmatter:
---
title: my cookbook
tagslug: recipe
---then the page mysite.com/cookbook/ would have the slug "cookbook" and the tagslug "recipe". if it had no frontmatter, both the slug and the tagslug would be "cookbook".
tagslugs should be unique for everything to work right. slugs, on the other hand, don't need to be unique; two pages with the same slug can coexist, so long as they're in different folders. if two pages have the same slug, and neither one has a different tagslug set in the frontmatter, rhodochrosite will add the rest of the path to the beginning of one page's tagslug, separated by hyphens. if the pages are nested at different depths, it will default to altering the tagslug of the more-deeply-nested page. take this website, for example:
- mysite.com/
- books/
- sff/
- scifi/
- fantasy/
- sff/
- movies/
- horror/
- scifi/
- books/
in this site, two pages have the slug scifi. since books/sff/scifi/ is more deeply nested, its tagslug will be updated to books-sff-scifi. (if two pages with duplicate slugs are nested at the same depth in different places, one is picked to alter more or less arbitrarily. when using tags in conjunction with duplicate page slugs, specify your own tagslugs in frontmatter to avoid confusion.)
inline tags
to use a tag inline, simply include it in the body of a markdown file following the # character, so that it appears in the body of a page. say src/blog/goodsoup.md includes the text
here's the #recipe for my great soupsomewhere in its body. then the page mysite.com/blog/goodsoup/ will have the tag "recipe" as one of its properties. if that tag matches any page's tagslug, for example, our mysite.com/cookbook/ from earlier, then mysite.com/blog/goodsoup/ will appear listed in mysite.com/cookbook/'s index section. also, the inline tag itself in the body of mysite.com/blog/goodsoup/ will be made into a link to mysite.com/cookbook/ .
frontmatter tags
tags can also be included in frontmatter, by setting the "tag" or "tags" property. multiple tags must be enclosed by brackets. examples:
---
tag: soup
------
tag: [soup, carrot, broccoli]
---automatic tag pages
let's say mysite.com/blog/goodsoup/ has the tag "recipe," and "recipe" does not match any page's tagslug. then, a new page will be made at mysite.com/tags/recipe/ . this page will list mysite.com/blog/goodsoup/ in its index section, as well as any other pages with the tag "recipe". so, inline tags can be used even when no page would exist to index them; again, necessary index pages are created automatically. all that's needed to initialize a new tag is to include it in a page for the first time !
lists
markdown in rhodochrosite (and most implementations) includes a syntax for ordered and unordered lists; rhodochrosite also includes task lists. in addition to normal usage, rhodochrosite uses list syntax for two special purposes: gallery pages and subtags. a basic unordered list somewhere in the body of a markdown file, using hyphens for delimiters and tabs for indentation, could appear like this:
- milk
- eggs
- fruit
- bananas
- apples
- red delicious
- breadgallery pages
rhodochrosite can apply some special formatting to a page for making a media gallery. to set up a gallery page, first set the page type (another property of the page) to "gallery" in the markdown file's frontmatter like so:
---
type: gallery
---then, enclose parts of the markdown file's body in an html span with the class gal, like so:
---
title: my picture gallery
type: gallery
---
<span class="gal">
- 
- this is my favorite picture :)
- 
- this is another picture i like
</span>
---(note that, in our markdown files, inline html must be surrounded with a blank line on either side.) within the span, a gallery is written as a markdown list. each top-level list item is a media item in the gallery; in the above example, they're embedded images. list items nested beneath these can be used to provide titles or other text below the image. other media types can be included with html embeds like so:
<span class="gal">
- <video controls src="video.mp4">title of my video</video>
- this is a video i took
- [title of my audio](mysounds/myaudio.mp3)
- <audio controls src="mysounds/myaudio.mp3">my audio alt text</audio>
- this is a sound i recorded!
</span>
in the second item here, the top-level item is a text link to the file, and the embed appears below it. this accomplishes basically the same thing, it just puts a little more visual emphasis on the title.
subtags
subtags are like tags, except instead of applying to a whole page, they apply to just one list item within the page; and instead of being indexed somewhere else, they're indexed right there in the same page's footer. subtags allow us to make little bundles of list items within a single page, just as tags allow us to make bundles of pages within the website.
to use a subtag, include it in an indented list item following a double hash mark, ## . the subtag will be applied to the outer list item within which that indented item is nested. for example, take a markdown file in the source folder which contains this list:
- milk
- ##dairy
- eggs
- butter
- ##dairy
- ##yellow
- produce
- apples
- this is a ##red ##fruit
- tomatoes
- ##red
- bananas
- this is a ##fruit
- this is ##yellowin this example, the list item milk has the subtag dairy, the list item apples has the subtags red and fruit, and so on. here's the subtag index that would be generated for the above list, and appear in the footer of the page that contains the list:
subtag index
##dairy
milk, butter
##yellow
butter
##red
apples, tomatoes
##fruit
apples
the subtags system uses URI fragments to make links for jumping around the page. every entry in the subtag index (milk, butter and so on) is a link to its corresponding list item, and every subtag in the list is made into a link to its corresponding header in the subtag index.
subtag index entries are usually rendered as the full text of the list item. if the item is a piece of media embedded with html like the examples shown in the gallery section, rhodochrosite will use the text between the html tags to render the entry. for example, this list:
- <video controls src="myvideo.mp4">my favorite skating video</video>
- ##skateboardingwould generate this subtag index:
subtag index
##skateboarding
my favorite skating video
thumbnails
if subtags are used on a gallery of images, something fun happens: instead of the usual text links, the entries in the subtag index are rendered as thumbnails of the images. for this to work, the page type should be set to gallery, and images should be embedded using markdown syntax. here's our previous example gallery updated to include some subtags:
---
title: my picture gallery
type: gallery
---
<span class="gal">
- 
- this is my favorite picture :)
- ##sunset ##ocean
- 
- this is another ##sunset picture i like
- ##mountain ##winter
</span>
---this arrangement will generate a subtag index with image thumbnails instead of text links!
further reading
this guide aims to get one up and running, explain the main features and define some terms; but it doesn't cover everything. the old readme had some more information, but this guide is formatted better; still, it's available until i put together some more extensive documentation
CLI commands and options
Options:
-V, --version output the version number
-s, --src <source> custom source directory
-d, --dest <destination> custom build directory
-n, --noserver do not start dev server
-p, --prod build the production version
-c --clean delete the previous build before building
-t --tsdir <ts-dir> set root dir for typescript watcher
-o --noopen server does not open new browser tab when starting
-h, --help display help for command
Commands:
build build the site once
watch watch the source folder for changes and keep the build folder updated correspondingly - also start a dev server
hack watch the typescript for changes, use this for hacking the generator
help [command] display help for command