js.plated
Plated is a static site generator that uses a cascading chunk system to describe the output pages.
Since we are using node we are also able to dynamically build the pages in the browser, which is why we include json dumps of the chunk data. This provides enough data to reconstruct pages client side.
Included are a handful of plugins that do slightly more complicated things to enable extra functionality such as page redirects or generating blogs.
This module only exposes one function, which is used to create the actual module with bound state data.
plated=require("./plated.js").create(opts,plated)
opts is an object of options and plated is an optional input if provided it will be modified and returned otherwise a new object will be created and returned.
We also load and setup this and all the builtin plugins so after calling this we are good to go.
In the future when we talk about plated and its available functions we are referring to the return from this create function.
The opts is intended to be filled with command line options so take a look at these for a full description of what can be passed in here.
js.plated.blog
plated.blog()
Create a starting blogpost with todays date in the main blog directory.
Title is taken from opts._[1] onwards IE the command line.
js.plated.build
plated.build()
Build all the output files from the inputs.
js.plated.micro
plated.micro()
Create a starting microblogpost with todays date-time in the main blog directory.
Markdown text is taken from opts._[1] onwards IE the command line.
js.plated.plugin
plated.plugin(it)
Register a plugin, each plugin can provide the following function hooks.
dirs = it.process_dirs( dirs )
Adjust the registered dirs data and return it.
file = it.process_file( file )
Adjust or react to the file data and return it.
it.process_output( chunks )
Adjust a files chunks prior to writing it out, or, output extra data associated with these chunks.
js.plated.setup
plated.setup(opts)
Initialise plated and require the base plated modules: files, chunks and output.
js.plated.watch
plated.watch()
Continuously build the output files from the inputs whenever one of the input files changes
js.plated_chunks
Manage the chunks of text that are combined into a page.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_chunks = require("./plated_chunks.js").create(opts,plated)
This is called automatically when the plated module is created and the return value is made available in plated.chunks note that all of these modules are bound together and operate as a group with shared data.
In the future when we talk about this module and its available functions we are referring to the return value from this create function.
js.plated_chunks.deepmerge
too = plated_chunks.deepmerge(frm,too,_flags)
Merge the object, frm, into an object too. How values merge can be adjusted by _flags the same way _flags works in parsing chunks. same=merge is honoured here so some chunks can be appended rather than replace. We need to keep this separate as the act of merging will break how such things work.
This function is called recursively so as not to end up sharing values with any inputs.
js.plated_chunks.delimiter_close_str
s = plated_chunks.delimiter_close_str()
Return the last half of the opts.delimiter string.
js.plated_chunks.delimiter_open_str
s = plated_chunks.delimiter_open_str()
Return the first half of the opts.delimiter string.
js.plated_chunks.delimiter_wrap_str
s = plated_chunks.delimiter_wrap_str(s)
Return the given string wrapped in the opts.delimiter string.
js.plated_chunks.expand_tag
value = plated_chunks.expand_tag(v,dat,lastpass)
Do all the magical things that enables a tag to expand, normally we just lookup the value inside dat but a few operators can be applied.
if dat is null then we use data pushed into the namespaces otherwise we will only use data available in dat.
Operators are applied from left to right so we have no precedence besides this.
If we fail to lookup a valid value then we return input string wrapped in delimiters, essentially any values we do not understand will come out of the process unscathed exactly as they went in.
There must be no white space inside {} or we will not process it.
This combined is why we can safely use {} rather than {{}} and any accidental use will survive.
js.plated_chunks.fill_chunks
chunks = plated_chunks.fill_chunks(str,chunks)
break a string into chunks ( can merged with or replace other chunks ) so chunks can be a previously filled list of chunks that we will combine any chunks we find in the string with.
A chunk is defined by a line that begins with #^ this has been chosen so as not to be something that occurs by mistake in any language, but can be altered either inside the chunk file or via the command line opts. Note that any future reference is referring to this default and would work with any other string if this has been changed.
A line that begins with #^=## would redefine this from one to the other for the remainder of the file and can be changed globally by the option opt.hashchunk
The first word after this would be the name of the chunk and can then be followed by a number of optional flag arguments like flag=value we store these flags in the chunks table using chunks._flags[name]=value this includes trimming options and request for how chunks should be merged.
A comment begins with #^- and the rest of the line will be ignored.
The flag same=append will cause future chunks of the same name to be appended to this chunk rather than replace it. This is useful for CSS chunks where we wish to bubble down css values into sub directories.
js.plated_chunks.format_chunks
chunks = plated_chunks.format_chunks(chunks)
Process the chunks according to their flags, a chunk with trim=ends set will have white space removed from its beginning and end.
A chunk with form=json will be parsed as json rather than a string. It can then be referenced inside chunks using chunk.member style lookups.
A chunk with form=markdown will be processed as markdown and turned into a html string.
js.plated_chunks.lookup
chunks = plated_chunks.lookup(str,dat)
lookup the string inside dat, the string can use dot notation such as parent.member to lookup a value inside an object.
Numbers can also be used to reverence arrays such as array.0 or array.1 and negative indexes such as array.-1 can be used to fetch the last value from the array.
js.plated_chunks.lookup_in_namespace
chunks = plated_chunks.lookup_in_namespace(str)
lookup the string inside all namespaces using the same rules as plated_chunks.lookup
js.plated_chunks.markdown
html = plated_chunks.markdown(str)
Convert a markdown string to a html string. As a personal quirk We keep newlines a little more eagerly than standard markdown allowing some control over the spacing between your text.
Markdown is hardly a standard thing, after all.
js.plated_chunks.merge_namespace
chunks = plated_chunks.merge_namespace(dat)
Merge all of the namespaces together, along with the dat, then return this new set of chunks for easy lookup it should be safe to modify the output merged chunks without accidentally changing anything in the namespace.
This gives us a final chunks object that we can use to build the output page.
js.plated_chunks.pop_namespace
plated_chunks.pop_namespace(value)
Remove last namespace from top of the stack.
js.plated_chunks.prepare
array = plated_chunks.prepare(chunks)
break a string on {data} ready to find the lookup values and do all the templating actions. This just gets us an array of string parts we can easily parse.
js.plated_chunks.push_namespace
plated_chunks.push_namespace(value)
Add this value into the namespaces, we check this namespace as well as the current chunk data when filling in chunks.
js.plated_chunks.remove_underscorechunks
newchunks = plated_chunks.remove_underscorechunks(chunks)
Remove any chunks that begin with "_" these are all internal chunks used by plated code. The user should not be creating any chunks whose names begin with an underscore. Also none of these chunks should ever bubble down through the heirachy, they belong only to the page in which they are created..
A new object full of only chunks that do not begin with an underscore is returned.
js.plated_chunks.replace
value = plated_chunks.replace(str,dat)
Repeatedly call replace_once until all things that can expand, have expanded, or we ran out of sanity. Sanity is 100 levels of recursion, just to be on the safe side.
We then call a final replace_once with the lastpass flag set.
if dat is null then we use data pushed into the namespaces otherwise we will only use data available in dat.
js.plated_chunks.replace_once
chunks = plated_chunks.replace_once(str,dat,lastpass)
Parse the str and replace {} values once only using dat values. lastpass is a flag as on the lastpass we allow final expansion and removal.
We can use {[} {]} around areas of text to prevent further expansion inside. So we can talk about plated inside plated, this is necesary for our documentation.
js.plated_chunks.reset_namespace
plated_chunks.reset_namespace()
clear the namespace, a namespace is a list of chunks that will be merged together as we descend into directories. The lower or later chunks replacing or merging with the previous ones.
js.plated_chunks.set_namespace
plated_chunks.set_namespace(values)
Set the namespace to the given value.
js.plated_files
Manage the files that we read from and watch or write to.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_files = require("./plated_files.js").create(opts,plated)
This is called automatically when the plated module is created and the return value is made available in plated.chunks note that all of these modules are bound together and operate as a group with shared data.
In the future when we talk about this module and its available functions we are referring to the return value from this create function.
js.plated_files.base_files_to_chunks
chunks = await plated_files.base_files_to_chunks(fname)
Check this directory and all directories above for generic chunks build all of these into the current chunk namespace for this file.
js.plated_files.build
plated_files.build()
Build all files found in the source dir into the output dir.
js.plated_files.build_file
plated_files.build_file(fname)
Build the given source filename, using chunks or maybe just a raw copy from source into the output.
js.plated_files.empty_cache
plated_files.empty_cache()
Empty the current file cache, we fill it up as read files.
js.plated_files.empty_folder
plated_files.empty_folder(path)
Empty the (output) folder or make it if it does not exist. This is rather dangerous so please be careful.
js.plated_files.exists
await plated_files.exists(path)
Returns true if a file or dir at the given path exists.
js.plated_files.file_to_chunks
chunks = plated_files.file_to_chunks(root,fname,chunks)
Load root/fname or get it from the cache and then turn it into chunks using plated_chunks.fill_chunks(date,chunks) chunks is returned.
js.plated_files.filename_fixup
filename = plated_files.filename_fixup(filename)
Fix the filename, so it becomes an empty string rather than a "." or "/." or "/" this makes it easier to use in urls.
js.plated_files.filename_is_basechunk
bool = plated_files.filename_is_basechunk(filename)
Is this filename part of the basechunks for a dir?
A base chunk is something like ^.html or ^.css all of these files get merged into the base chunks for the directory they are found in. Their extension is ignored and just to help syntax highlighting when the file is viewed.
js.plated_files.filename_is_plated
bool = plated_files.filename_is_plated(filename)
Is this filename something we need to run through plated. Returns true if filename contains the ^ trigger string. This string can be changed by altering opts.hashfile from "^" to something else.
js.plated_files.filename_to_dirname
dirname = plated_files.filename_to_dirname(filename)
Get the dirname of this filename.
js.plated_files.filename_to_output
filename = plated_files.filename_to_output(filename)
Work out the output filename from an input filename, the trigger string "^." gets removed as we process a file.
js.plated_files.find_dirs
plated_files.find_dirs(root,name,func)
Call func(name) with every directory we find inside the root/name directory. We follow symlinks into other directories.
js.plated_files.find_files
plated_files.find_files(root,name)
REturn an array with every file we find inside the root/name directory. We follow symlinks into other directories.
js.plated_files.joinpath
await plated_files.joinpath(...)
join components into a full path.
js.plated_files.lstat
await plated_files.lstat(path)
Return the lstat of this path
js.plated_files.mkdir
plated_files.mkdir(dir)
Create the given dir and recursively create its parent dirs as well if necessary.
js.plated_files.prepare_namespace
plated_files.prepare_namespace(fname)
Check this directory and all directories above for generic chunks then build all of these into the current chunk namespace for this file.
js.plated_files.readdir
await plated_files.readdir(path)
Return the readdir of this path
js.plated_files.set_source
plated_files.set_source(dir)
Fill in _source and related chunks such as.
_sourcename the file that this set of chunks came from.
_filename the output filename.
_dirname the output dirname.
_root the root of the site, normally a relative path to the current directory, eg ../ since some things such as github pages need to exist in a directory rather than the root of a site. This should always be used in html paths, {_root} instead of / to make sure that you always get to the right place and can find your files.
_filename the url path of the filename, eg /dirname/filename
_dirname the url path of the dir this file exists in, eg /dirname
js.plated_files.source_to_output
filename = plated_files.source_to_output(filename)
Convert a source path into an output path.
js.plated_files.stat
await plated_files.stat(path)
Return the stat of this path
js.plated_files.trimpath
plated_files.trimpath(path)
Remove a trailing / from the path
js.plated_files.watch
plated_files.watch()
Build all files found in the source dir into the output dir and then sit watching for changes to these files that would trigger rebuilds.
This does not return, instead the user is expected to ctrl+c when finished.
js.plated_files.write
plated_files.write(filename,data)
Create parent dir if necessary and write the data into this file.
js.plated_output
Manage the chunks of text that are combined into a page.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_output = require("./plated_output.js").create(opts,plated)
This is called automatically when the plated module is created and the return value is made available in plated.chunks note that all of these modules are bound together and operate as a group with shared data.
In the future when we talk about this module and its available functions we are referring to the return value from this create function.
js.plated_output.remember
chunks = plated_output.remember(chunks)
Remember this page, the name is expected to be found in chunks._output_filename and this is used as the key to store these chunks.
js.plated_output.remember_and_write
chunks = await plated_output.remember_and_write(chunks)
The same as remember but also instantly write out the chunks using plated_output.write
js.plated_output.write
await plated_output.write(chunks)
Write out the chunks to to _output_filename as its final page like form. chunks._output_chunkname is the name of the chunk that we intend to render into this page, eg "html"
opts.output is the directory we are going to write the file into.
If the opts.dumpjson flag is set then we also output a .json file which contains the chunks used to construct this page.
js.plated_output.write_all
plated_output.write_all()
Go through all the remembered chunks and write each one out using plated_output.write
js.plated_output.write_map
plated_output.write_map()
Output plated.map.json which is a concise map of all chunks for all files and directories.
js.plated_plugin.blog
A blog plugin.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_plugin_blog = require("./plated_plugin_blog.js").create(opts,plated)
This is called automatically when the plated module is created and the returned plugin functions are added to the plugin call stack. Note that all of these modules are bound together and operate as a group with shared data.
js.plated_plugin.blog.process_dirs
dirs = plated_plugin_blog.process_dirs(dirs)
Tweak all the base chunks grouped by dir name and pre cascaded/merged
js.plated_plugin.blog.process_file
chunks = plated_plugin_blog.process_file(chunks)
Tweak a single file of chunks, only chunks found in this file will be available.
js.plated_plugin.copy
A blog plugin.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_plugin_copy = require("./plated_plugin_copy.js").create(opts,plated)
This is called automatically when the plated module is created and the returned plugin functions are added to the plugin call stack. Note that all of these modules are bound together and operate as a group with shared data.
This plugin is intended to duplicate part of a site into another directory with possibly tweaked chunks, this is primarily intended for text translations. We produce for instance pure text chunks containing just english text and replace these chunks with french versions inside a fra directory.
Note that we only copy chunkfiles not all data files, so this is only about duplicating files that are rendered from chunks.
js.plated_plugin.copy.process_dirs
dirs = plated_plugin_copy.process_dirs(dirs)
Remember all the _copy_json chunks we can find inside our plated_plugin_copy.chunks array. This will be used later to replicated output into other locations with slight chunk tweaks.
js.plated_plugin.copy.process_file
chunks = plated_plugin_copy.process_file(chunks)
Auto magically parse _copy_json chunks as json.
js.plated_plugin.copy.process_output
plated_plugin_copy.process_output(chunks)
Compare this output file with cached copy chunks and duplicate it into these directories with slightly tweaked chunks if it matches.
js.plated_plugin.docs
A docs plugin.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_plugin_docs = require("./plated_plugin_docs.js").create(opts,plated)
This is called automatically when the plated module is created and the returned plugin functions are added to the plugin call stack. Note that all of these modules are bound together and operate as a group with shared data.
js.plated_plugin.docs.process_dirs
dirs = plated_plugin_docs.process_dirs(dirs)
Tweak all the base chunks grouped by dir name and pre cascaded/merged
js.plated_plugin.docs.process_file
chunks = plated_plugin_docs.process_file(chunks)
Tweak a single file of chunks, only chunks found in this file will be available.
js.plated_plugin.import
A way of importing chunks from another page.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_plugin_import = require("./plated_plugin_import.js").create(opts,plated)
This is called automatically when the plated module is created and the returned plugin functions are added to the plugin call stack. Note that all of these modules are bound together and operate as a group with shared data.
js.plated_plugin.import.process_file
chunks = plated_plugin_import.process_file(chunks)
Tweak a single file of chunks, only chunks found in this file will be available.
js.plated_plugin.redirect
A blog plugin.
This module only exposes one function, which is used to create the actual module with bound state data.
plated_plugin_redirect = require("./plated_plugin_redirect.js").create(opts,plated)
This is called automatically when the plated module is created and the returned plugin functions are added to the plugin call stack. Note that all of these modules are bound together and operate as a group with shared data.
js.plated_plugin.redirect.process_dirs
dirs = plated_plugin_redirect.process_dirs(dirs)
Tweak all the base chunks grouped by dir name and pre cascaded/merged
js.plated_plugin.redirect.process_file
chunks = plated_plugin_redirect.process_file(chunks)
Tweak a single file of chunks, only chunks found in this file will be available.
#^_redirect_json
Is a special chunk name that we will parse as json and contain configuration data to setup redirects.