npm.io
7.1.1 • Published 3 weeks ago

als-layout

Licence
MIT
Version
7.1.1
Deps
1
Size
47 kB
Vulns
0
Weekly
0

als-layout

als-layout is a small, dependency‑light library for building and manipulating an HTML document in memory — title, meta tags, Open Graph / Twitter cards, styles, scripts, links, favicon and viewport — with a fluent, chainable API. It works the same in Node (SSR / static generation) and in the browser.

It is built on top of als-document and is a pure document builder: it has no global state and no site‑level concerns (collections, sitemaps, robots). For multi‑page sites built on top of it, see als-site.


What's new in 7.1

  • toDocument() — render a layout into the live DOM on the client (no‑op in Node).
  • urlObjurl() now exposes the parsed URL.
  • Packaging — ESM resolves to the named Layout export, CommonJS to the class (exports map).
  • Fixtwitter:description uses name= (was property=), per the Twitter Cards spec.
  • Fixclone preserves the document URL/host.
  • Changeurl() keeps the canonical trailing slash (URL.href) and stores urlObj.

See the full Changelog below.


Installation

npm i als-layout
ESM (named export)
import { Layout } from 'als-layout'
Node (CommonJS)
const Layout = require('als-layout')
Browser bundle (global Layout, als-document inlined)
<script src="layout.js"></script>
<script>const layout = new Layout()</script>

Quick start

import { Layout } from 'als-layout'

const layout = new Layout(undefined, 'https://example.com')
   .lang('en')
   .noindex()                                    // adds <meta name="robots" content="noindex">
   .viewport()                                   // width=device-width, initial-scale=1.0
   .title('Home')                                // <title> + og:title
   .description('A cool site')                   // description + og/twitter description
   .keywords(['stats', 'sheets'])
   .favicon('/favicon.png')
   .image('/cover.png')                          // og:image, twitter:image, twitter:card
   .link('/styles.css')                          // <link rel=stylesheet> (deduped)
   .style('body{margin:0}')                      // appends to <style>
   .script({ src: '/app.js' })                   // <script> in <head>
   .script({}, 'console.log("hi")', false)       // inline <script> in <body>
   .url('/')                                      // canonical + og:url, resolved vs host

layout.body.innerHTML = '<h1>Home</h1>'
console.log(layout.rawHtml)                       // full HTML string

A Layout is an offline DOM

This is the core idea: a Layout extends an als-document document, so the instance is a real, in‑memory DOM tree you can query and mutate almost exactly like the browser DOM — no jsdom, no browser, works in plain Node. The chainable title()/meta()/link()/… helpers are just convenience on top of it; for anything else you manipulate nodes directly.

const layout = new Layout(/*html*/`<html><head></head><body><main></main></body></html>`)

// Query like the DOM ($ / $ are aliases for querySelector / querySelectorAll)
const main = layout.$('main')              // === layout.querySelector('main')
const items = layout.$('.item')           // === querySelectorAll, returns an array

// Build and insert nodes
main.innerHTML = '<h1>Hello</h1>'
main.insert(2, '<p class="lead">Intro</p>')          // append parsed HTML
main.insertAdjacentHTML('beforeend', '<hr>')

// Mutate elements with the familiar API
const h1 = layout.$('h1')
h1.setAttribute('id', 'top')
h1.classList.add('title')
h1.dataset.role = 'heading'
h1.textContent = 'Welcome'
console.log(h1.outerHTML)                   // <h1 id="top" class="title" data-role="heading">Welcome</h1>

// Traverse
h1.parent          // parent node
h1.nextElementSibling
layout.body.children

// Remove
layout.$('hr').remove()

Supported on nodes: querySelector/$, querySelectorAll/$, getElementById, getAttribute/setAttribute/removeAttribute, classList, dataset, style, innerHTML/outerHTML/textContent, append/insert/insertAdjacentHTML/remove, plus traversal (parent, children, prev/next, …). See als-document for the full node API.

On the client, toDocument() flushes this offline DOM into the live document.


Cloning

layout.clone returns a deep, independent copy — ideal as a template for many pages. Changes to a clone never affect the original.

const base = new Layout(template, 'https://example.com').link('/styles.css')
const about = base.clone.title('About').url('/about')

API

Constructor
new Layout(html?: string, host?: string)
  • html — optional HTML string to start from.
  • host — base URL used to resolve relative URLs in url().
Properties
  • rawHtml — current document as an HTML string.
  • clone — a deep, independent copy.
  • urlObj — the parsed URL of the last url() call (set after url()).
  • head / body / html — element accessors (from als-document).
Methods (all chainable, return this)
  • lang(lang) — sets <html lang>.
  • title(title) — sets <title> and og:title.
  • description(text) — sets description, og:description, twitter:description.
  • keywords(list) — sets/merges meta[name=keywords].
  • meta(props) — sets/updates a <meta> tag (keyed by its first attribute).
  • image(src) — sets og:image, twitter:image, twitter:card.
  • favicon(href) — sets/updates the favicon link.
  • viewport(content?) — sets the viewport meta.
  • link(href, attributes?) — adds a stylesheet <link> (skipped if already present).
  • style(css) — appends CSS to a <style> element.
  • script(attrs?, innerHTML?, head = true) — adds a <script> (head or body; src deduped).
  • url(url, host = this.URL) — sets canonical + og:url, stores urlObj.
  • toDocument() — in the browser, renders this layout into the live document (no‑op in Node); returns this.

Changelog

7.1.0
  • Added toDocument() — render a layout into the live DOM on the client.
  • Added urlObjurl() now exposes the parsed URL.
  • Added exports map — ESM resolves to the named Layout export, CommonJS to the class.
  • Fixed twitter:description now uses name= (was property=), per the Twitter Cards spec.
  • Fixed clone preserves the document URL/host.
  • Changed url() keeps the canonical trailing slash (URL.href), and stores urlObj.
7.0.0 (breaking)
  • Merged into a single source file; added ESM build (index.mjs) and browser bundle (layout.js).
  • Removed status, end, minified, propsToClone, and JS/CSS uglification.

Notes

  • Pure document builder — no global state, no file I/O.
  • index.mjs and the browser layout.js are generated from src/layout.js by node build.js.
  • Use clone to derive page variants from a base template.