Skip to content
LexerLangv0.1.0

Document and layout

html_document, shared layouts, ${children}, $page and static files.

LexerLang
use html_document

$doc = new html_document
$doc = new html_document({title: 'Title', lang: 'en'})
CallProduces
$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.partsthe array of added parts

add and prepend accept several parts and return the section.

The rendered skeleton#

HTML
<!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#

LexerLang
$app.layout(path.pwd + "/layout.lx")
$app.layout({file: path.pwd + "/layout.lx"})
LexerLang
# 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>
`)
MarkerReplaced by
${children}the page's body — required
Document and layout · LexerLangthe page's title
enthe 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:

LexerLang
if not $page.indexable then
    $doc.body.add(`<small>This page is not indexed.</small>`)
end if
FieldContents
$page.title · $page.langthe page's title and language
$page.indexablewhether the page may be indexed
$page.body · $page.headthe 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#

LexerLang
# home.lx
package home
use html_document

$doc = new html_document
$doc.body.add(`<form>...</form>`)
LexerLang
$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 only html_document is used; with more than one it is an error.
  • When a document is given, only the body is added; the head is not quietly merged.
  • Circular includes are caught.

Static files#

LexerLang
$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#

LexerLang
$doc.indexable = false         # adds a "noindex, nofollow" meta tag

The default is true.

LexerLang
$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.

Next#

Request and response.