- siteNav
The homepage's section nav: pinned to the top by its classes, and made smarter here.
- Hides while the visitor scrolls down and comes back when they scroll up (or tab into it), so it doesn't cover the page while reading.
- On phones it collapses behind the Menu button (the list's
data-closedattribute; frommdup the classes keep it a row whatever the attribute says). - Marks the link of the section being read with
data-currentandaria-current.
Without this script the nav is still a plain, pinned list of links: the Menu button stays
hiddenand the list stays open.- roleTitles
The typing effect on the homepage's role line, run by title-switcher (https://www.npmjs.com/package/title-switcher).
The page's real text stays put: the role line's static "Full-Stack Engineer" is what screen readers, applicant tracking systems and visitors without JavaScript get. The lines to type live in a
<template>, which browsers don't render and readers don't read. This module copies them into anaria-hiddenspan, tucks the static text away visually (data-animatedon the line switches itsgroup-data-animated:sr-onlyclass on), and starts the typing. When the visitor's system asks for reduced motion, nothing changes at all.- titleSwitcherSandbox
The title-switcher sandbox on /projects/: visitors type their own lines, set the speed and order, and watch title-switcher (https://www.npmjs.com/package/title-switcher) type them out.
title-switcher has no "stop": pause() only stops it from moving to the next line. So each (re)start builds a fresh container on the stage and lets the old instance finish in the background, detached and unseen. The lines become text nodes (never HTML), so whatever a visitor types is shown, not run.
- siFuncionaSandbox
The si-funciona sandbox: pick a function, edit its inputs, and see the call and its result update as you type. Runs the real library (https://www.npmjs.com/package/si-funciona), loaded as window.siFunciona.
Inputs are read as text, numbers or JSON (JSON.parse, never eval), and results are shown with textContent, so nothing a visitor types is run as code. Rendered into each
<div data-sandbox='si-funciona'>, so /projects/ and the si-funciona page share one sandbox.- pseudoDomSandbox
The pseudo-dom sandbox, "same question, two DOMs": pseudo-dom imitates the browser's DOM for tests in Node, so the page asks it and the real browser DOM the same questions (CSS selectors, then a few predefined changes) and shows both answers side by side. Runs the real library (pseudo-dom), loaded as window.pseudoDom.
The real side parses visitor HTML in a separate, inert document (document.implementation.createHTMLDocument), where scripts and handlers like onerror never run; pseudo-dom never runs anything either. Rendered into each
<div data-sandbox='pseudo-dom'>, so /projects/ and the pseudo-dom page share one sandbox.- matrixDomSandbox
The matrix-dom sandbox: a 10 by 10 board to try the grid geometry Battleship is built on. Draw a line between two cells, see a cell's neighbours, or place a fleet the way Battleship does. Runs the real library (matrix-dom), loaded as window.matrixDom: on /projects/ the site's own bundle already defines it, and the matrix-dom page loads it from browser/vendor.
Rendered into each
<div data-sandbox='matrix-dom'>, so /projects/ and the matrix-dom page share one sandbox.- jsonFsQuerySandbox
The json-fs-query sandbox: a small library database (authors, books, members, loans) kept as JSON files on this site, queried in the browser by the real library (json-fs-query, window.jsonFsQuery) over fetch(). Pick a question to load its query, edit it, or write your own read. Writes only work in Node, and json-fs-query says so.
Results are drawn with textContent, so whatever a query returns is shown, not run. Rendered into each
<div data-sandbox='json-fs-query'>, so /projects/ and the json-fs-query page share one sandbox. The database is built by scripts/build-library-database.mjs (with json-fs-query itself).- jsonDomSandbox
The json-dom sandbox: describe a piece of page as JSON (json-dom's own item format) and watch json-dom render it, next to the HTML it produced. Runs the real library (json-dom), loaded as window.jsonDom: on /projects/ the site's own bundle defines it, and the json-dom page loads it from browser/vendor.
Visitor JSON goes through an allowlist first: only plain content tags and a few safe attributes render, so nothing like onclick, <script> or a javascript: link can run. Whatever was dropped is listed. Rendered into each
<div data-sandbox='json-dom'>, so /projects/ and the json-dom page share one sandbox.- collectYourStuffSandbox
The collect-your-stuff sandbox: try a Queue, a Stack and a (doubly) linked list one call at a time, and see the collection redrawn after each call from the library's own state. Runs the real library (https://www.npmjs.com/package/collect-your-stuff), loaded as window.collectYourStuff.
Values are shown with textContent, so whatever a visitor types is displayed, not run. Rendered into each
<div data-sandbox='collect-your-stuff'>, so /projects/ and the collect-your-stuff page share one sandbox.
- tileContent(project) ⇒
DomItem A single tile's content: an icon badge plus title/description, all wrapped in one clickable link.
- projectGrid(projects) ⇒
DomItem Builds a matrix-dom grid of project tiles, one per entry in
projects, in display order (row-major: left to right, then top to bottom). Any trailing columns left over whenprojects.lengthdoesn't divide evenly intocolumnsare left empty (marked 'tile-empty', andinvisible).
- ProjectTile :
object The real projects shown in the homepage's project grid, in display order.
The homepage's section nav: pinned to the top by its classes, and made smarter here.
- Hides while the visitor scrolls down and comes back when they scroll up (or tab into it), so it doesn't cover the page while reading.
- On phones it collapses behind the Menu button (the list's
data-closedattribute; frommdup the classes keep it a row whatever the attribute says). - Marks the link of the section being read with
data-currentandaria-current.
Without this script the nav is still a plain, pinned list of links: the Menu button stays hidden and the list
stays open.
- siteNav
- .scrollTolerance
- .nextHidden ⇒
boolean - .currentSection ⇒
string|null - .initSiteNav ⇒
Object|null
Scroll movements smaller than this (in px) don't change whether the nav is shown, so tiny jitters don't flicker it.
Kind: static constant of siteNav
siteNav.nextHidden ⇒ boolean
Decide whether the nav should be hidden after a scroll.
Kind: static constant of siteNav
| Param | Type | Description |
|---|---|---|
| state | Object |
|
| state.hidden | boolean |
Whether the nav is hidden now. |
| state.lastY | number |
The scroll position at the previous decision. |
| state.y | number |
The scroll position now. |
| state.pinnedFrom | number |
The scroll position where the nav starts to stick to the top; above it the nav is in its natural place under the header, so it always shows. |
| state.menuOpen | boolean |
The phone menu is open: keep the nav showing. |
| state.holding | boolean |
A nav link was just followed: keep the nav showing until that scroll ends. |
Pick the section being read: the last one whose top has passed the reading line (a third of the way down the viewport), or none above the first section.
Kind: static constant of siteNav
| Param | Type | Description |
|---|---|---|
| sections | Array.<{id: string, top: number}> |
Each section's id and its top relative to the viewport, in page order. |
| readingLine | number |
Distance from the top of the viewport, in px. |
Wire up the nav.
Kind: static constant of siteNav
Returns: Object | null - null when the page has no nav.
| Param | Type |
|---|---|
| document | Document |
| window | Window |
The typing effect on the homepage's role line, run by title-switcher (https://www.npmjs.com/package/title-switcher).
The page's real text stays put: the role line's static "Full-Stack Engineer" is what screen readers, applicant
tracking systems and visitors without JavaScript get. The lines to type live in a <template>, which browsers
don't render and readers don't read. This module copies them into an aria-hidden span, tucks the static text
away visually (data-animated on the line switches its group-data-animated:sr-only class on), and starts the
typing. When the visitor's system asks for reduced motion, nothing changes at all.
- roleTitles
- .timing
- .startRoleTitles ⇒
Object|null
Typing speed (ms per character) and the cursor's blink interval (ms), passed to title-switcher.
Kind: static constant of roleTitles
Start the typing effect, unless something it needs is missing or the visitor prefers reduced motion.
Kind: static constant of roleTitles
Returns: Object | null - The running TitleSwitcher, or null when it didn't start.
| Param | Type | Default | Description |
|---|---|---|---|
| document | Document |
||
| window | Window |
||
| [TitleSwitcher] | function |
window.TitleSwitcher |
The title-switcher class (swappable in tests). |
The title-switcher sandbox on /projects/: visitors type their own lines, set the speed and order, and watch title-switcher (https://www.npmjs.com/package/title-switcher) type them out.
title-switcher has no "stop": pause() only stops it from moving to the next line. So each (re)start builds a fresh container on the stage and lets the old instance finish in the background, detached and unseen. The lines become text nodes (never HTML), so whatever a visitor types is shown, not run.
- titleSwitcherSandbox
- .markup
- .parseLines ⇒
Array.<string> - .buildTitles ⇒
HTMLElement - .initTitleSwitcherSandbox ⇒
Object|null
The sandbox's controls and stage. Static markup (no visitor data goes in here), styled with Tailwind classes;
assets/tailwind/site.css scans this folder for them. Rendered into each <div data-sandbox='title-switcher'>,
so /projects/ and the title-switcher page share one sandbox.
Kind: static constant of titleSwitcherSandbox
The visitor's lines: one per row, trimmed, blank rows dropped.
Kind: static constant of titleSwitcherSandbox
| Param | Type |
|---|---|
| text | string |
Build a fresh title container (one span per line) for title-switcher to animate.
Kind: static constant of titleSwitcherSandbox
| Param | Type |
|---|---|
| document | Document |
| lines | Array.<string> |
Render the sandbox into the page's <div data-sandbox='title-switcher'> and wire it up. One sandbox per page (its
ids are fixed). Starts on its own unless the visitor prefers reduced motion; then it waits for Start.
Kind: static constant of titleSwitcherSandbox
Returns: Object | null - null when the sandbox isn't on the page.
| Param | Type | Default |
|---|---|---|
| document | Document |
|
| window | Window |
|
| [TitleSwitcher] | function |
window.TitleSwitcher |
The si-funciona sandbox: pick a function, edit its inputs, and see the call and its result update as you type. Runs the real library (https://www.npmjs.com/package/si-funciona), loaded as window.siFunciona.
Inputs are read as text, numbers or JSON (JSON.parse, never eval), and results are shown with textContent, so
nothing a visitor types is run as code. Rendered into each <div data-sandbox='si-funciona'>, so /projects/ and
the si-funciona page share one sandbox.
- siFuncionaSandbox
- .functions :
Array.<{group: string, name: string, label: (string|undefined), chip: (string|undefined), about: string, inputs: Array.<{label: string, kind: string, value: string}>, run: (function()|undefined)}> - .parseInput ⇒
* - .formatValue ⇒
string - .runFunction ⇒
Object - .markup
- .queueMarkup
- .queueSteps
- .expectedOrder ⇒
Object - .initQueueDemo ⇒
Object - .initSiFuncionaSandbox ⇒
Object|null
- .functions :
siFuncionaSandbox.functions : Array.<{group: string, name: string, label: (string|undefined), chip: (string|undefined), about: string, inputs: Array.<{label: string, kind: string, value: string}>, run: (function()|undefined)}>
The functions on offer, grouped as in the picker. Each input has a kind: 'text', 'number', 'numbers' or 'json'. An entry can
show several functions at once with its own run, a label for the call line and a short chip for its button.
Kind: static constant of siFuncionaSandbox
Turn one input's text into its argument.
Kind: static constant of siFuncionaSandbox
Throws:
ErrorFor JSON that doesn't parse, or text that isn't a number.
| Param | Type | Description |
|---|---|---|
| kind | string |
'text', 'number', 'numbers' (a comma-separated list of whole numbers) or 'json' |
| text | string |
Show a value the way it would read in code: strings quoted, everything else as indented JSON.
Kind: static constant of siFuncionaSandbox
| Param | Type |
|---|---|
| value | * |
Run a function from the list with the given input texts.
Kind: static constant of siFuncionaSandbox
| Param | Type | Description |
|---|---|---|
| library | Object |
The si-funciona exports. |
| fn | Object |
|
| texts | Array.<string> |
One per input. |
The sandbox's static markup (no visitor data), styled with Tailwind classes; assets/tailwind/site.css scans this folder for them.
Kind: static constant of siFuncionaSandbox
The queueTimeout demo's markup (static), shown below the function explorer.
Kind: static constant of siFuncionaSandbox
The queue demo's starting steps: a long delay first, so the two orders differ.
Kind: static constant of siFuncionaSandbox
When each step fires: all at once from the start (setTimeout), or each after the one before (queueTimeout).
Kind: static constant of siFuncionaSandbox
Returns: Object - Each in firing order.
| Param | Type |
|---|---|
| steps | Array.<{label: string, delay: number}> |
Wire up the queueTimeout demo inside an already rendered sandbox.
Kind: static constant of siFuncionaSandbox
| Param | Type | Description |
|---|---|---|
| document | Document |
|
| window | Window |
|
| library | Object |
The si-funciona exports (for queueTimeout). |
Render the sandbox into the page's <div data-sandbox='si-funciona'> and wire it up. One per page (fixed ids).
Kind: static constant of siFuncionaSandbox
Returns: Object | null - null when the sandbox isn't on the page.
| Param | Type | Default |
|---|---|---|
| document | Document |
|
| window | Window |
|
| [library] | Object |
window.siFunciona |
The pseudo-dom sandbox, "same question, two DOMs": pseudo-dom imitates the browser's DOM for tests in Node, so the page asks it and the real browser DOM the same questions (CSS selectors, then a few predefined changes) and shows both answers side by side. Runs the real library (pseudo-dom), loaded as window.pseudoDom.
The real side parses visitor HTML in a separate, inert document (document.implementation.createHTMLDocument), where
scripts and handlers like onerror never run; pseudo-dom never runs anything either. Rendered into each
<div data-sandbox='pseudo-dom'>, so /projects/ and the pseudo-dom page share one sandbox.
- pseudoDomSandbox
- .exampleHtml
- .suggestedSelectors
- .changes :
Object.<string, {label: string, code: string, run: function(Element, Document, Array.<string>): void}> - .matchTexts ⇒
Array.<string> - .normalizeHtml ⇒
string - .prettyHtml ⇒
string - .buildRoots ⇒
Object - .compareQuery ⇒
Object - .compareChange ⇒
Object - .markup
- .initPseudoDomSandbox ⇒
Object|null
Starting HTML to try.
Kind: static constant of pseudoDomSandbox
Selectors to try with one tap.
Kind: static constant of pseudoDomSandbox
pseudoDomSandbox.changes : Object.<string, {label: string, code: string, run: function(Element, Document, Array.<string>): void}>
The predefined changes: each runs the same code on a root element of either DOM, and may log what it saw.
Kind: static constant of pseudoDomSandbox
The text of each match, for comparing and showing.
Kind: static constant of pseudoDomSandbox
| Param | Type |
|---|---|
| root | Element |
| selector | string |
HTML with formatting whitespace between tags removed, so both DOMs' output compares fairly.
Kind: static constant of pseudoDomSandbox
| Param | Type |
|---|---|
| html | string |
Indent HTML one tag per line, for reading the two results side by side.
Kind: static constant of pseudoDomSandbox
| Param | Type |
|---|---|
| html | string |
Two fresh roots holding the same HTML: one in pseudo-dom, one in an inert real document.
Kind: static constant of pseudoDomSandbox
| Param | Type | Description |
|---|---|---|
| library | Object |
The pseudo-dom exports. |
| document | Document |
The page's document (for createHTMLDocument). |
| html | string |
Ask both DOMs the same selector.
Kind: static constant of pseudoDomSandbox
| Param | Type |
|---|---|
| library | Object |
| document | Document |
| html | string |
| selector | string |
Run a predefined change on both DOMs.
Kind: static constant of pseudoDomSandbox
| Param | Type | Description |
|---|---|---|
| library | Object |
|
| document | Document |
|
| html | string |
|
| name | string |
A key of changes. |
The sandbox's static markup (no visitor data), styled with Tailwind classes; assets/tailwind/site.css scans this folder for them.
Kind: static constant of pseudoDomSandbox
Render the sandbox into the page's <div data-sandbox='pseudo-dom'> and wire it up. One per page.
Kind: static constant of pseudoDomSandbox
| Param | Type | Default |
|---|---|---|
| document | Document |
|
| window | Window |
|
| [library] | Object |
window.pseudoDom |
The matrix-dom sandbox: a 10 by 10 board to try the grid geometry Battleship is built on. Draw a line between two cells, see a cell's neighbours, or place a fleet the way Battleship does. Runs the real library (matrix-dom), loaded as window.matrixDom: on /projects/ the site's own bundle already defines it, and the matrix-dom page loads it from browser/vendor.
Rendered into each <div data-sandbox='matrix-dom'>, so /projects/ and the matrix-dom page share one sandbox.
- matrixDomSandbox
- .size
- .modes
- .key ⇒
string - .formatPoint ⇒
string - .validPlacements ⇒
Array.<Array.<{x: number, y: number}>> - .markup
- .initMatrixDomSandbox ⇒
Object|null
The board's size, and the fleet Battleship places (ship lengths, longest first).
Kind: static constant of matrixDomSandbox
The modes, with one line on what each shows.
Kind: static constant of matrixDomSandbox
A point's key, for sets and lookups.
Kind: static constant of matrixDomSandbox
| Param | Type |
|---|---|
| point | Object |
A point as it reads in code.
Kind: static constant of matrixDomSandbox
| Param | Type |
|---|---|
| point | Object |
Every place a ship of this length could go without crossing an occupied cell: Battleship's validPlacements.
Kind: static constant of matrixDomSandbox
Returns: Array.<Array.<{x: number, y: number}>> - Each placement as its cells.
| Param | Type | Description |
|---|---|---|
| library | Object |
The matrix-dom exports. |
| matrix | Object |
|
| length | number |
|
| occupied | Set.<string> |
Keys of cells already taken. |
The sandbox's static markup (no visitor data), styled with Tailwind classes; assets/tailwind/site.css scans this folder for them.
Kind: static constant of matrixDomSandbox
Render the sandbox into the page's <div data-sandbox='matrix-dom'> and wire it up. One per page.
Kind: static constant of matrixDomSandbox
| Param | Type | Default |
|---|---|---|
| document | Document |
|
| window | Window |
|
| [library] | Object |
window.matrixDom |
The json-fs-query sandbox: a small library database (authors, books, members, loans) kept as JSON files on this site, queried in the browser by the real library (json-fs-query, window.jsonFsQuery) over fetch(). Pick a question to load its query, edit it, or write your own read. Writes only work in Node, and json-fs-query says so.
Results are drawn with textContent, so whatever a query returns is shown, not run. Rendered into each
<div data-sandbox='json-fs-query'>, so /projects/ and the json-fs-query page share one sandbox.
The database is built by scripts/build-library-database.mjs (with json-fs-query itself).
- jsonFsQuerySandbox
- .databasePath
- .libraryDate
- .records
- .questions
- .cellText ⇒
string - .columnsOf ⇒
Array.<string> - .isGrouped ⇒
boolean - .buildTable ⇒
HTMLElement - .markup
- .initJsonFsQuerySandbox ⇒
Object|null
Where the database lives on this site.
Kind: static constant of jsonFsQuerySandbox
The library's "today", so overdue loans stay overdue.
Kind: static constant of jsonFsQuerySandbox
The records, with their sizes, for the browse buttons.
Kind: static constant of jsonFsQuerySandbox
Questions to load with one tap: each shows off a part of the query language.
Kind: static constant of jsonFsQuerySandbox
A cell's text: arrays of rows become a compact list (each row's values joined), other values as they read.
Kind: static constant of jsonFsQuerySandbox
| Param | Type |
|---|---|
| value | * |
The columns for some rows: every key, in the order first seen.
Kind: static constant of jsonFsQuerySandbox
| Param | Type |
|---|---|
| rows | Array.<Object> |
Whether a result is grouped (group by returns groups with field, value and rows or groups).
Kind: static constant of jsonFsQuerySandbox
| Param | Type |
|---|---|
| result | Array |
Build a table element for rows (text only).
Kind: static constant of jsonFsQuerySandbox
| Param | Type |
|---|---|
| document | Document |
| rows | Array.<Object> |
The sandbox's static markup (no visitor data), styled with Tailwind classes; assets/tailwind/site.css scans this folder for them.
Kind: static constant of jsonFsQuerySandbox
Render the sandbox into the page's <div data-sandbox='json-fs-query'> and wire it up. One per page.
Kind: static constant of jsonFsQuerySandbox
| Param | Type | Default |
|---|---|---|
| document | Document |
|
| window | Window |
|
| [library] | Object |
window.jsonFsQuery |
The json-dom sandbox: describe a piece of page as JSON (json-dom's own item format) and watch json-dom render it, next to the HTML it produced. Runs the real library (json-dom), loaded as window.jsonDom: on /projects/ the site's own bundle defines it, and the json-dom page loads it from browser/vendor.
Visitor JSON goes through an allowlist first: only plain content tags and a few safe attributes render, so nothing
like onclick, <script> or a javascript: link can run. Whatever was dropped is listed. Rendered into each
<div data-sandbox='json-dom'>, so /projects/ and the json-dom page share one sandbox.
- jsonDomSandbox
- .allowedTags
- .allowedAttributes
- .examples
- .isSafeHref ⇒
boolean - .sanitize ⇒
Object|null - .prettyHtml ⇒
string - .markup
- .initJsonDomSandbox ⇒
Object|null
The tags a visitor's structure may use. '#text' is a text node (its text goes in nodeValue).
Kind: static constant of jsonDomSandbox
The attributes a visitor's structure may set.
Kind: static constant of jsonDomSandbox
Starting structures to load with one tap.
Kind: static constant of jsonDomSandbox
Whether a link is safe to keep: http(s), mailto, a page path or an anchor (never javascript: or data:).
Kind: static constant of jsonDomSandbox
| Param | Type |
|---|---|
| href | string |
Keep only allowed tags, attributes and links, recording what was dropped.
Kind: static constant of jsonDomSandbox
Returns: Object | null - A clean item, or null when the whole item was dropped.
| Param | Type | Default | Description |
|---|---|---|---|
| item | * |
A visitor's item (parsed JSON). | |
| dropped | Array.<string> |
Collects a note for each thing removed. | |
| [where] | string |
"'root'" |
Where in the structure this item is, for the notes. |
Indent HTML one tag per line, for reading (whitespace inside text is left alone).
Kind: static constant of jsonDomSandbox
| Param | Type |
|---|---|
| html | string |
The sandbox's static markup (no visitor data), styled with Tailwind classes; assets/tailwind/site.css scans this folder for them.
Kind: static constant of jsonDomSandbox
Render the sandbox into the page's <div data-sandbox='json-dom'> and wire it up. One per page.
Kind: static constant of jsonDomSandbox
| Param | Type | Default |
|---|---|---|
| document | Document |
|
| window | Window |
|
| [library] | Object |
window.jsonDom |
The collect-your-stuff sandbox: try a Queue, a Stack and a (doubly) linked list one call at a time, and see the collection redrawn after each call from the library's own state. Runs the real library (https://www.npmjs.com/package/collect-your-stuff), loaded as window.collectYourStuff.
Values are shown with textContent, so whatever a visitor types is displayed, not run. Rendered into each
<div data-sandbox='collect-your-stuff'>, so /projects/ and the collect-your-stuff page share one sandbox.
- collectYourStuffSandbox
- .modes
- .nextLabel ⇒
string - .readList ⇒
Array.<*> - .formatValue ⇒
string - .createState ⇒
Object - .runOperation ⇒
Object - .contents ⇒
Array.<*> - .markup
- .initCollectYourStuffSandbox ⇒
Object|null
The modes, their operations, and one line on how each collection behaves.
Kind: static constant of collectYourStuffSandbox
The next label to suggest: A, B, … Z, then AA, AB, …
Kind: static constant of collectYourStuffSandbox
| Param | Type | Description |
|---|---|---|
| count | number |
How many have been suggested so far. |
Read a linked list's values in order.
Kind: static constant of collectYourStuffSandbox
| Param | Type | Description |
|---|---|---|
| list | Object |
Anything with forEach(node => …) over nodes with .data. |
Show a value the way it reads in code.
Kind: static constant of collectYourStuffSandbox
| Param | Type |
|---|---|
| value | * |
A fresh state: an empty Queue, Stack and list, built with the library's own classes.
Kind: static constant of collectYourStuffSandbox
| Param | Type | Default | Description |
|---|---|---|---|
| library | Object |
The collect-your-stuff exports. | |
| [doubly] | boolean |
false |
A DoublyLinkedList instead of a LinkedList. |
Run one operation on the state, through the library.
Kind: static constant of collectYourStuffSandbox
Returns: Object - The call as it reads in code, what it returned, and a
message when it can't run (no list item selected).
| Param | Type | Description |
|---|---|---|
| state | Object |
|
| mode | string |
'queue', 'stack' or 'list' |
| operation | string |
One of that mode's operations. |
| value | string |
The value to add (for adding operations). |
| selected | number | null |
The selected list position (for insertAfter and remove). |
The values to draw for a mode: queue front first, stack top first, list first to last.
Kind: static constant of collectYourStuffSandbox
| Param | Type |
|---|---|
| state | Object |
| mode | string |
The sandbox's static markup (no visitor data), styled with Tailwind classes; assets/tailwind/site.css scans this folder for them.
Kind: static constant of collectYourStuffSandbox
Render the sandbox into the page's <div data-sandbox='collect-your-stuff'> and wire it up. One per page.
Kind: static constant of collectYourStuffSandbox
| Param | Type | Default |
|---|---|---|
| document | Document |
|
| window | Window |
|
| [library] | Object |
window.collectYourStuff |
projects : Array.<ProjectTile>
A single tile's content: an icon badge plus title/description, all wrapped in one clickable link.
Kind: global function
| Param | Type |
|---|---|
| project | Object |
Builds a matrix-dom grid of project tiles, one per entry in projects, in display order
(row-major: left to right, then top to bottom). Any trailing columns left over when projects.length
doesn't divide evenly into columns are left empty (marked 'tile-empty', and invisible).
Kind: global function
| Param | Type |
|---|---|
| projects | Array.<{title: string, href: string, description: string}> |
The real projects shown in the homepage's project grid, in display order.
Kind: global typedef
Properties
| Name | Type | Description |
|---|---|---|
| title | string |
the display name |
| href | string |
where the tile's single link goes (a project's own page, or GitHub when it has no page) |
| description | string |
a brief description shown on the tile |