# luasmith Tutorial
In this tutorial, we'll start with a trivial pipeline and build it up into a simple blog theme. See [../README.md](../README.md) for an overview of luasmith.
For an example of input content, look at the `sample/content/` directory.
### Trivial/Identity Pipeline
Here's a pipeline that essentially just copies from `content/` to `out/`:
```lua
-- Pipeline that copies from content/ to out/
return {
readFromSource("content"),
writeToDestination("out"),
}
```
Note that no Markdown processing is done whatsoever. You can try this trivial example out by compiling luasmith, going into the `sample` directory, and running `../luasmith tutorial1.lua`.
### Process Markdown
To actually convert Markdown to HTML, just add the `processMarkdown()` node (as in `sample/tutorial2.lua`):
```lua
return {
readFromSource("content"),
-- Convert Markdown files to HTML fragments
processMarkdown(),
writeToDestination("out"),
}
```
### Templates
Markdown produces an HTML fragment, so you can apply a template to build the rest of the document:
```lua
-- Put generated HTML fragment into a complete document
-- The template is internally passed to etlua.compile()
-- See etlua docs for an explanation of <%= %>, etc.
-- The item schema is roughly:
-- {
-- path = "relative path of the item",
-- pathToRoot = "path TO the root FROM the item",
-- content = "contents of the item/file",
-- ... -- Any additional properties added by the pipeline
-- }
local template = [[
<%= title %>
<%- content %>
]]
return {
readFromSource("content"),
processMarkdown(),
applyTemplates({
-- The first item in each pair is a pattern to match item paths
-- The second item in each pair is the etlua template string itself
-- If an item's path matches multiple entries, the last match wins
-- The Lua pattern below means "ends with '.html'"
{ "%.html$", template },
}),
writeToDestination("out"),
}
```
What does `%.html$` mean? Lua does not use POSIX regular expressions (regexp) for reasons outlined [here](https://www.lua.org/pil/20.1.html). In this case, `%.` means the literal `.` character; in other words, `%` is the escape character. The `$` (**only** at the end of a pattern) anchors the match to the end of the string in question. The manual outlines this in greater detail [here](https://www.lua.org/manual/5.4/manual.html#6.4.1). A tutorial [here](http://lua-users.org/wiki/PatternsTutorial) explains some of the limitations of Lua's pattern matching.
### Adding CSS
Injecting a CSS file is trivial, but remember to reference it using the correct relative path (see `pathToRoot` in the contained HTML template):
```lua
-- Add and reference CSS
local css = [[
body { max-width: 40em; margin: auto; }
]]
-- Note CSS is referenced using `pathToRoot`
local template = [[
<%= title %>
<%- content %>
]]
return {
readFromSource("content"),
-- Inject arbitrary files: key is the path and value is the content
injectFiles({ ["style.css"] = css }),
processMarkdown(),
applyTemplates({ { "%.html$", template } }),
writeToDestination("out"),
}
```
### Root/Index Page
Using `aggregate()`, you can create a root/index/home page that displays information about all posts, in reverse chronological order. Note that you can add multiple `applyTemplates()` steps, e.g. to format the content in the first pass and then insert the content into a document in a second pass.
```lua
-- Add a root/index/home page, listing blog posts
local index = [[
<% for i, item in ipairs(table.sortBy(items, "date", true)) do -%>
]]
local outer = [[
<%= title %>
<%- content %>
]]
local css = [[
body { max-width: 40em; margin: auto; }
]]
return {
readFromSource("content"),
injectFiles({ ["style.css"] = css }),
processMarkdown(),
-- Aggregate into an item of path, including a new property
-- named `items` of all items matching the pattern
aggregate("index.html", "%.html$"),
-- Apply a template to list the blog posts
applyTemplates({ { "^index%.html$", index } }),
-- Finally, wrap each HTML fragment in a document
applyTemplates({ { "%.html$", outer } }),
writeToDestination("out"),
}
```
There you go! Now you've got a barebones blog.
### Bonus: syntax highlighting and link checking
* Add `highlightSyntax()` after `processMarkdown()` to apply CSS classes to code blocks
* Add `checkLinks()` to check that relative links are not broken
```lua
return {
...
processMarkdown(),
highlightSyntax(), -- Add ".hl-*" CSS classes to code blocks
...
checkLinks(), -- Check for broken links
writeToDestination("out"),
}
```
### Beyond the Tutorial
Poke around the included themes in `themes/` for further inspiration.