Installion of STExtended is very simple:
npm init @jlpenny/stextended dirname
cd dirname
to enter the directory and get building!
If you are wanting to build a blog, we also offer a blogging template:
npm init @jlpenny/stextended dirname blog
To build your site, simply use:
npm run build
Now that you have a basic website, the first thing you should learn about STExtended is the object.yml file.
Configuration of a website is stored in an objects.yml
file. Here you can find various global configuration variables that are used by the processor for building your site. For basic sites, you just need to specify a base
, which is your build folder. You should also specify source
which specifies your source directory, otherwise it will assume the working directory! Then you have urlBase
to specify the URL of the website when routing, and titleBase
which is used to generate titles.
Macros are used to generate pages programatically. They will iterate through a specified configuration attribute and will pass a list of pages for each attribute valie to a specified layout. This is useful, for instance, if you wanted to generate a list of HTMLs that contained a list of articles in each category.
Perhaps the best way to illustrate this is using an example:
Let's say you had a blog with 3 categories, "stuff," "things," and "tidbits." You also want a page generated for each category which lists the blog posts.
First of all, simply specify the "category" attribute in your pages. Then, you'll want to create a layout page for the macro:
parent: /includes/layout.html
build: false
---
{{#each page.local}}
<div>
<h3>{{this.config.title}}</h3>
<p class='text-right'>
<a href='{{route this.name}}'>
<button>View Post</button>
</a>
</p>
</div>
{{/each}}
The pages are stored in page.local
, and you can access all page configuration and contents there.
Finally, you specify the macro in the configuration file:
macros:
- attribute: 'category'
href: '/{{value}}/index.html'
layout: '/includes/category.html'
Attribute specifies which configuration attribute to group by, href is the route to the page, and layout is the layout you wish to use.
Macros can be paginated simply by adding a "paginate" directive to the macro configuration. This specifies the number of pages per page, you will also need to update your href directive:
macros:
- attribute: 'category'
paginate: 10
href: '/{{value}}/index.html'
layout: '/includes/category.html'
Macros can also be sorted
macros:
- attribute: 'category'
paginate: 10
href: '/{{value}}/index{{pagenum}}.html'
layout: '/includes/category.html'
sortby: date
sortorder: desc
The static site generator will go through all HTML and MD (markdown) files to look for data to render. These files have two sections: a 'configuration' section at the top which uses YAML, and a content section below. A basic html file might look like:
---
layout: /includes/layout.html
title: Test title
---
<p>Hello world!</p>
Within the 3 dashes, you add configuration values. These can include title, the layout it should be using, and anything you like! These can be used to influence things like macros to generate content automatically, or you can even put variables in here that you can use in the page.
The template language is very simple, using Handlebars.js
, and mostly consists of putting inline javascript or in-built "helper statements" between {{}}
.
Apart from being able to embed plain ol' javascript, we've made some shortcuts to make it simpler for you:
route
{{route '/index.html'}}
Configuration values can be accessed inline as such:
{{page.variablename}}
For example, for the title:
{{page.title}}
If you are trying to do something like create a blog, you are able to query through your pages using the 'where' command. This goes through all rendered pages in the engine, and filters them. There is also a sort command to sort them how you like too! For example, if you wanted to grab all pages that have the config variable "blog: 1" by their date, simply use the example below:
Generation (building) of a website is handled with a script called generate.js (or at least, it is when using the stextended init
tool.) The one for this website looks like this:
const stextended = require('@jlpenny/stextended');
const { Builder, HTML, CSS } = stextended();
CSS.ProcessFile('./style.css');
Builder.all();
The Builder, HTML, and CSS objects contain classes related to the generation process. CSS is the CSS processor, HTML is the HTML parser, and Builder is the builder itself. You can find more information about these objects under the parser section.
STExtended allows you to write classless code, which basically means adding attributes which automatically get converted into CSS to your HTML tags. These are styled after bootstrap's tags. For example, if you want a margin, you can use m-x where x is the size in em which you want the margin.
<div m="2">This has a margin</div>
Apart from some built in attributes, you can also define any CSS property by putting a dollar symbol in front of the tag:
<div $background-color="#ccc">I have a grey background!</div>
The CSS file will automatically be processed and the attributes will be replaced with a class name. This way CSS is generated only for what you used.
You can add your own CSS to the processing system using the following: CSS.ProcessFile(filename);
This is to be put in your generation script, which is generate.js if you used the stextended init
command. You can see this in action on the source code of this very website:
const { Builder, HTML, CSS } = STextended();
CSS.ProcessFile('./src/style.css');
Generate.all();
You can create your own HTML tag components into the parser using HTML.define
as follows:
HTML.define('CustomClass', (name, attribs, content) => {
return `<span class="${attribs.addClass('customClass').extract('class')}" ${attribs.toString(true)} $position="relative">${content}</span>`;
});
This will replace any instance of <CustomClass>text here</CustomClass>
with the returned value, which would be <span class="customClass generated-position-relative-class">text here</span>
in this case.