Document and layout
html_document, shared layouts, ${children}, $page and static files.
use html_document
$doc = new html_document
$doc = new html_document({title: 'Title', lang: 'en'})| Call | Produces |
|---|---|
$doc.title = '...' | <title> |
$doc.lang = 'en' | <html lang> |
$doc.head.add(...) | appends to <head> |
$doc.head.prepend(...) | prepends to <head> |
$doc.body.add(...) | appends to <body> |
$doc.body.prepend(...) | prepends to <body> |
$doc.from_file(<path>) | runs another .lx file and returns its document |
$doc.body.parts | the array of added parts |
add and prepend accept several parts and return the section.
The rendered skeleton#
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>...</title>
... head parts ...
</head>
<body>
... body parts ...
</body>
</html><html>, <head>, <meta charset>, <meta viewport> and <title> are already written by the document; you only write what you add.
A shared layout#
$app.layout(path.pwd + "/layout.lx")
$app.layout({file: path.pwd + "/layout.lx"})# layout.lx
$doc = new html_document
$doc.type = html_document.types.LAYOUT
$doc.head.add(`<link rel="stylesheet" href="/public/style.css">`)
$doc.body.add(`
<header>Document and layout · LexerLang</header>
<main>${children}</main>
`)| Marker | Replaced by |
|---|---|
${children} | the page's body — required |
Document and layout · LexerLang | the page's title |
en | the page's language |
A layout file must declare its type (html_document.types.LAYOUT); without it the file counts as a page and raises an error. A missing ${children} is an error too — where the content should go would be undefined.
$page#
The layout can also read the page's data through $page:
if not $page.indexable then
$doc.body.add(`<small>This page is not indexed.</small>`)
end if| Field | Contents |
|---|---|
$page.title · $page.lang | the page's title and language |
$page.indexable | whether the page may be indexed |
$page.body · $page.head | the page's raw parts |
The markers are a shorthand; $page is for writing conditions. $page is a copy of the page: a layout cannot modify the page, otherwise where the output came from would stop being traceable.
Partials — from_file#
# home.lx
package home
use html_document
$doc = new html_document
$doc.body.add(`<form>...</form>`)$index = new html_document
$index = $index.from_file(path.pwd + "/home.lx")
$doc.body.add($index.body) # place only its body
$doc.body.add($index) # the same: given a document, its body is added- The included file runs in its own scope; it does not see the caller's variables and cannot change them. This is a deliberate difference from PHP's
include. - The returned document is the file's
$doc. Without$doc, the file's onlyhtml_documentis used; with more than one it is an error. - When a document is given, only the body is added; the
headis not quietly merged. - Circular includes are caught.
Static files#
$app.static({url_path: "/public", directory: path.pwd + "/public"})Requests with that prefix are served from the directory, and it is checked before the route table. Paths escaping the directory (/public/../secret) are rejected. The content type comes from the extension.
Robots and sitemap#
$doc.indexable = false # adds a "noindex, nofollow" meta tagThe default is true.
$app.routes.create_sitemap({
output_file: path.pwd + "/public/sitemap.xml",
base_url: "https://example.com",
skip: ["/secret"]
})The sitemap is written at startup and contains parameterless paths: which addresses /product/:id corresponds to cannot be known.
indexable = false puts a meta tag on the page but does not affect the sitemap: the sitemap is written at startup, before handlers run, and whether a page closes itself off cannot be known at that moment. Use skip to leave a path out.