@allons-y/webc-patterns 0.1.0-beta.1 → 0.1.0-beta.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +97 -92
- package/llms.txt +709 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# @allons-y/webc-patterns
|
|
2
2
|
|
|
3
|
-
Part of [Norn](https://github.com/allonsy-studio/webc-resources#readme). Generic page
|
|
3
|
+
Part of [Norn](https://github.com/allonsy-studio/webc-resources#readme). Generic page & docs patterns for Eleventy sites that use WebC: the page frame & docs shell as Eleventy layouts, & the components they are built from, such as the header, footer, hero, cards, side nav, pager, skip link, icons, link buttons, & tags. One Eleventy plugin registers all of it. Content goes in slots: a component styles the markup it's given. Each component carries its own CSS in-file, so a page ships only the styles of the components it uses.
|
|
4
4
|
|
|
5
5
|
See it in the [component preview](https://allonsy-studio.github.io/webc-resources/).
|
|
6
6
|
|
|
7
|
+
Using an AI coding agent? Point it at [`llms.txt`](llms.txt): the rules for calling & styling the components, & a reference of every prop, slot, & token.
|
|
8
|
+
|
|
7
9
|
## Status
|
|
8
10
|
|
|
9
11
|
Beta. Versions are `0.1.0-beta.N` until 1.0.
|
|
@@ -15,7 +17,7 @@ npm install --save-dev @11ty/eleventy @11ty/eleventy-plugin-webc @allons-y/webc-
|
|
|
15
17
|
npm install --save-dev @allons-y/webc-code-sample # optional: highlighted code samples
|
|
16
18
|
```
|
|
17
19
|
|
|
18
|
-
`@11ty/eleventy`
|
|
20
|
+
`@11ty/eleventy` & `@11ty/eleventy-plugin-webc` are peer dependencies. `@allons-y/webc-code-sample` is an optional one: with it installed, the plugin registers `norn-code-block` & highlights Markdown fences, & the layouts show code with it; without it, the plugin registers a plain `norn-code-block` under the same tag, so a hand-written sample & the layouts' samples show as `<pre><code>`, with their `id` & caption. The project is an ES module (`"type": "module"`). Node 22 or later.
|
|
19
21
|
|
|
20
22
|
Evergreen browsers from about 2024. Features newer than that, such as `@scope`, degrade gracefully.
|
|
21
23
|
|
|
@@ -35,7 +37,7 @@ export default function (config) {
|
|
|
35
37
|
}
|
|
36
38
|
```
|
|
37
39
|
|
|
38
|
-
Then pick a layout per page in its front matter: `layout: norn-docs.webc`. The plugin owns the project's one `@11ty/eleventy-plugin-webc` registration: pass more component globs as `components`,
|
|
40
|
+
Then pick a layout per page in its front matter: `layout: norn-docs.webc`. The plugin owns the project's one `@11ty/eleventy-plugin-webc` registration: pass more component globs as `components`, & don't add the WebC plugin separately. For the OSS site theme, add `@allons-y/webc-oss-site`'s plugin in place of this one (see its [README](https://github.com/allonsy-studio/webc-resources/tree/main/packages/webc-oss-site#readme)).
|
|
39
41
|
|
|
40
42
|
| Option | Default | Does |
|
|
41
43
|
| --- | --- | --- |
|
|
@@ -43,17 +45,17 @@ Then pick a layout per page in its front matter: `layout: norn-docs.webc`. The p
|
|
|
43
45
|
| `layouts` | `true` | `false` ships no layout; a list of names, as `["norn-landing"]`, leaves those out so the project can supply its own |
|
|
44
46
|
| `components` | `[]` | More component globs: a theme's, the project's `_includes/*.webc` |
|
|
45
47
|
| `exclude` | `[]` | Packaged components to leave out, so the project can supply its own |
|
|
46
|
-
| `strings` | `{}` | The site's strings for every component
|
|
48
|
+
| `strings` | `{}` | The site's strings for every component & layout (see Translating) |
|
|
47
49
|
| `markdown` | `true` | Amend Markdown with the add-ons below |
|
|
48
50
|
| `defaults` | `{}` | Prop values a theme sets, under the mapping's |
|
|
49
51
|
| `icons` | none | Project icons for `norn-icon` (see Project icons) |
|
|
50
52
|
|
|
51
53
|
The plugin registers:
|
|
52
54
|
|
|
53
|
-
- `@11ty/eleventy-plugin-webc` once, with the patterns components, `norn-code-block` from the code sample when it is installed (else the plain one),
|
|
55
|
+
- `@11ty/eleventy-plugin-webc` once, with the patterns components, `norn-code-block` from the code sample when it is installed (else the plain one), & the `components` globs.
|
|
54
56
|
- The six layouts, under the project's configured layouts folder (or its includes folder), through `addTemplate`.
|
|
55
|
-
- The helpers the components
|
|
56
|
-
- With `markdown`, the Markdown add-ons through `amendLibrary`: `webcTags`, `highlightFences` from the code sample, `scrollTables`, `callouts`, `singleTitle`,
|
|
57
|
+
- The helpers the components & layouts call: `nornAdjacent`, `nornHeadings`, `nornComponentStrings`, `nornHook`, `nornIcons`, `nornCompiles`, & `nornTokenRanges` with the code sample.
|
|
58
|
+
- With `markdown`, the Markdown add-ons through `amendLibrary`: `webcTags`, `highlightFences` from the code sample, `scrollTables`, `callouts`, `singleTitle`, & `headingAnchors`.
|
|
57
59
|
- `dropEmptyBundleTags` as a transform, so a page with no CSS or JS keeps no empty `<link>` or `<script>`.
|
|
58
60
|
|
|
59
61
|
### Project icons
|
|
@@ -67,23 +69,23 @@ config.addPlugin(norn, {
|
|
|
67
69
|
});
|
|
68
70
|
```
|
|
69
71
|
|
|
70
|
-
Then `<norn-icon @name="logo"></norn-icon>`. Paths resolve against the working directory. A name is lowercase kebab case. A missing file, a bad name, or two files with one name fails the build,
|
|
72
|
+
Then `<norn-icon @name="logo"></norn-icon>`. Paths resolve against the working directory. A name is lowercase kebab case. A missing file, a bad name, or two files with one name fails the build, & so does a name no icon has: the error lists the built-in & project names.
|
|
71
73
|
|
|
72
74
|
- A project icon with a built-in's name replaces the built-in.
|
|
73
|
-
- The icon keeps its `viewBox`, or takes one from a numeric `width`
|
|
74
|
-
- The size, `<title>`, `<desc>`, scripts,
|
|
75
|
-
- Ids in the drawing,
|
|
75
|
+
- The icon keeps its `viewBox`, or takes one from a numeric `width` & `height`, or gets `0 0 24 24`, & its own paint. Draw it with `currentColor` so it follows the text color; a file with no paint is filled with `currentColor`. The built-in stroke styling applies to the built-in icons only, so a filled SVG renders filled.
|
|
76
|
+
- The size, `<title>`, `<desc>`, scripts, & event handler attributes are dropped, & the drawing is always hidden from assistive tech. Name an icon that carries meaning in the `label` slot, as for any icon.
|
|
77
|
+
- Ids in the drawing, & the references to them (`url(#id)`, `href`, & a `<style>`'s `#id` selectors), are prefixed with `norn-icon-` & the icon's name. Inlined icons share the page's one id space, so two icons that each define `id="a"` would otherwise clip & fill each other.
|
|
76
78
|
- `mirror: true` flips the icon in right-to-left text, as the built-in arrows do.
|
|
77
79
|
|
|
78
80
|
Without the plugin, `norn-icon` draws the built-in set only.
|
|
79
81
|
|
|
80
|
-
Without the plugin, register the components as `patterns()` (or `npm:@allons-y/webc-patterns/components/*.webc`) in the project's own WebC `components` list. The layouts, helpers,
|
|
82
|
+
Without the plugin, register the components as `patterns()` (or `npm:@allons-y/webc-patterns/components/*.webc`) in the project's own WebC `components` list. The layouts, helpers, & Markdown add-ons are then the project's to wire up.
|
|
81
83
|
|
|
82
84
|
### Layout props
|
|
83
85
|
|
|
84
|
-
The layouts read their props as `$data.norn`. Without `props`, each prop is read off the page data of the same name. Every list defaults to `[]`,
|
|
86
|
+
The layouts read their props as `$data.norn`. Without `props`, each prop is read off the page data of the same name. Every list defaults to `[]`, & a value that is not a list counts as empty. Eleventy also runs the mapping against placeholder data to learn what it reads, so it must not throw on missing data: write `data.collections?.docs ?? []`, not `data.collections.docs`. `norn` is a reserved data key: a page, or a data file, that sets it fails the build with the page's path.
|
|
85
87
|
|
|
86
|
-
One mapping serves every layout, because each layout reads only its own props
|
|
88
|
+
One mapping serves every layout, because each layout reads only its own props & ignores the rest:
|
|
87
89
|
|
|
88
90
|
```js
|
|
89
91
|
config.addPlugin(norn, {
|
|
@@ -101,21 +103,21 @@ config.addPlugin(norn, {
|
|
|
101
103
|
});
|
|
102
104
|
```
|
|
103
105
|
|
|
104
|
-
Every list item that links somewhere or describes something has one shape: `href` (the address), `title` (the label),
|
|
106
|
+
Every list item that links somewhere or describes something has one shape: `href` (the address), `title` (the label), & `description` (the short text), plus `icon` where a layout draws one. That holds for `nav`, the footer's links, `docs`, `prev` & `next`, `features`, `packages`, & `workspaces`, & for the `items` of `norn-side-nav` & `norn-breadcrumbs`. A mapping turns an Eleventy page into an item with `href: page.url`. The props that are not list items keep their names: `name` is the project's own name, `url` the page's canonical address, & `footer.license` is `{ name, url }`.
|
|
105
107
|
|
|
106
108
|
`norn-base` is the frame of every layout, so its props apply to all of them:
|
|
107
109
|
|
|
108
110
|
| Prop | Shape | Default | Rendered as |
|
|
109
111
|
| --- | --- | --- | --- |
|
|
110
112
|
| `lang` | string | `page.lang`, then `en` | `<html lang>` |
|
|
111
|
-
| `dir` | `"ltr"`, `"rtl"`, or `"auto"` | `rtl` for a right-to-left `lang`, else `ltr` | `<html dir>`. Right-to-left languages are `ar`, `fa`, `he`, `ur`, `ps`, `yi`, `dv`, `ckb`, `sd`,
|
|
113
|
+
| `dir` | `"ltr"`, `"rtl"`, or `"auto"` | `rtl` for a right-to-left `lang`, else `ltr` | `<html dir>`. Right-to-left languages are `ar`, `fa`, `he`, `ur`, `ps`, `yi`, `dv`, `ckb`, `sd`, & `ug`, matched on the primary subtag of `lang` |
|
|
112
114
|
| `title` | string | none | `<title>`, as "title: name"; the `<h1>` of the docs layouts |
|
|
113
|
-
| `name` | string | none | The brand link, the footer's lead, `og:site_name`,
|
|
114
|
-
| `tagline` | string | none | After the name in the title
|
|
115
|
-
| `description` | string | none | `<meta name="description">`
|
|
116
|
-
| `url` | string | none | `<link rel="canonical">`
|
|
115
|
+
| `name` | string | none | The brand link, the footer's lead, `og:site_name`, & the hero `<h1>`. Each is left out without one (the brand link also shows for a logo) |
|
|
116
|
+
| `tagline` | string | none | After the name in the title & the hero `<h1>`; the footer's text |
|
|
117
|
+
| `description` | string | none | `<meta name="description">` & `og:description`; the hero paragraph |
|
|
118
|
+
| `url` | string | none | `<link rel="canonical">` & `og:url`. Absolute, for a relative `ogImage` |
|
|
117
119
|
| `ogTitle` | string | the document title | `og:title` |
|
|
118
|
-
| `ogImage` | `{ src, alt? }` or a URL | none | `og:image`, `og:image:alt`,
|
|
120
|
+
| `ogImage` | `{ src, alt? }` or a URL | none | `og:image`, `og:image:alt`, & `twitter:card` as `summary_large_image` |
|
|
119
121
|
| `locale` | string | none | `og:locale`, such as `en_US` |
|
|
120
122
|
| `themeColor` | string | the page surface in each scheme | `<meta name="theme-color">` |
|
|
121
123
|
| `themeToggle` | boolean | `false` | An inline script that applies the scheme a `norn-theme-toggle` saved, before the first paint |
|
|
@@ -124,54 +126,54 @@ Every list item that links somewhere or describes something has one shape: `href
|
|
|
124
126
|
| `logo` | `{ src, alt? }` or a URL | none | An image in the header in place of the name. `alt` falls back to the name |
|
|
125
127
|
| `nav` | `{ href, title, icon? }[]` | `[]` | The links of `norn-header`. `icon` names a `norn-icon` |
|
|
126
128
|
| `footer` | object | `{ badges: [], groups: [] }` | `norn-footer`, from the fields below |
|
|
127
|
-
| `footer.name`, `footer.text` | string | the name, the tagline | The lead column's title
|
|
129
|
+
| `footer.name`, `footer.text` | string | the name, the tagline | The lead column's title & line |
|
|
128
130
|
| `footer.license` | `{ name, url }` | none | "Licensed under {license}", linked |
|
|
129
131
|
| `footer.badges` | `{ href, src, alt, width?, height? }[]` | `[]` | Linked images under the lead |
|
|
130
132
|
| `footer.groups` | `{ heading, links: { href, title }[] }[]` | `[]` | The footer navigation, one list per group |
|
|
131
133
|
| `footer.colophon` | string | none | A closing line |
|
|
132
134
|
|
|
133
|
-
A relative `ogImage.src` resolves against `url`. When `url` is not absolute, the build logs a `norn-head:` warning, leaves out `og:image`
|
|
135
|
+
A relative `ogImage.src` resolves against `url`. When `url` is not absolute, the build logs a `norn-head:` warning, leaves out `og:image` & `og:image:alt`, & sets the card to `summary`. A path with a leading slash (`/img/share.png`) resolves against the origin of `url`, one without (`share.png`) against the page. Without an image, no image tag renders & the card is `summary`.
|
|
134
136
|
|
|
135
137
|
Each of the other layouts adds its own props, below. The base props a layout reads are named under its heading.
|
|
136
138
|
|
|
137
139
|
#### `norn-base.webc`
|
|
138
140
|
|
|
139
|
-
The page frame: head, skip link, header, `main` around the content,
|
|
141
|
+
The page frame: head, skip link, header, `main` around the content, & footer. It takes the props above. It compiles Markdown content once, so a Markdown page's callouts, code fences, & tables render as components, also through a Nunjucks or Liquid layout of the project's or a layout alias. Content that WebC already compiled goes in as it is: a WebC page, a `templateEngineOverride` with `webc`, a `{% renderTemplate "webc" %}` block, & a page on any shipped layout or on a WebC layout of the project's own. A Nunjucks, Liquid, or HTML page renders its components through `{% renderTemplate "webc" %}`. The `nornCompiles` helper decides, from `page.templateSyntax`. Every other shipped layout sets `nornCompiled: true` in its front matter, so the frame leaves the content it compiled; a WebC layout of the project's own that compiles the content & sits deeper in the chain than the page's own layout sets it too.
|
|
140
142
|
|
|
141
|
-
A `<section>` directly in `main` is a centered column at `--norn-layout-width`, with block padding, a gap,
|
|
143
|
+
A `<section>` directly in `main` is a centered column at `--norn-layout-width`, with block padding, a gap, & a second-level heading style. Its `id` is the anchor. The rule is in the `norn.layout` layer under `:where(main)`, so a project rule overrides it, & a section anywhere else is left alone.
|
|
142
144
|
|
|
143
145
|
#### `norn-docs.webc`
|
|
144
146
|
|
|
145
|
-
A docs page: the sidebar with site search, the title, the contents, the body in `norn-rich-text`,
|
|
147
|
+
A docs page: the sidebar with site search, the title, the contents, the body in `norn-rich-text`, & the pager. Reads `title`.
|
|
146
148
|
|
|
147
149
|
| Prop | Shape | Default | Rendered as |
|
|
148
150
|
| --- | --- | --- | --- |
|
|
149
151
|
| `docs` | `{ href, title, icon? }[]` | `[]` | The sidebar's `norn-side-nav`, in order, with the current page marked |
|
|
150
152
|
| `prev`, `next` | `{ href, title }` | the neighbors in `docs` | The `norn-pager` |
|
|
151
|
-
| `search` | `{ bundle?, site? }` or `false` | the Pagefind script at `/pagefind/pagefind.js`,
|
|
153
|
+
| `search` | `{ bundle?, site? }` or `false` | the Pagefind script at `/pagefind/pagefind.js`, & the host of `url` | `norn-search` above the sidebar list. `false` leaves it out |
|
|
152
154
|
|
|
153
|
-
The contents come from `nornHeadings` over the body, so they list the headings the Markdown add-on anchors
|
|
155
|
+
The contents come from `nornHeadings` over the body, so they list the headings the Markdown add-on anchors & any `norn-heading-anchor` written by hand. The layout shows the title as the page's h1, so a Markdown body keeps no h1 of its own: a leading `# Title` that repeats the title is dropped, & any other `#` heading renders as an h2 (`singleTitle`). A page 60rem wide or more has them as a sticky column beside the body; narrower, they fold under their title, & the sidebar folds into a closed `<details>` named "Documentation".
|
|
154
156
|
|
|
155
157
|
#### `norn-docs-home.webc`
|
|
156
158
|
|
|
157
|
-
The hero with the install sample, then the docs pages as a contents list, then the page body. Reads `name`, `tagline`,
|
|
159
|
+
The hero with the install sample, then the docs pages as a contents list, then the page body. Reads `name`, `tagline`, & `description`.
|
|
158
160
|
|
|
159
161
|
| Prop | Shape | Default | Rendered as |
|
|
160
162
|
| --- | --- | --- | --- |
|
|
161
163
|
| `lede` | string | `description` | The hero paragraph |
|
|
162
164
|
| `install` | string | none | The install sample in the hero |
|
|
163
165
|
| `repo` | string | none | The "View on GitHub" button |
|
|
164
|
-
| `docs` | `{ href, title, description? }[]` | `[]` | The contents list,
|
|
166
|
+
| `docs` | `{ href, title, description? }[]` | `[]` | The contents list, & the "Read the docs" button to the first page |
|
|
165
167
|
|
|
166
168
|
#### `norn-landing.webc`
|
|
167
169
|
|
|
168
|
-
The hero with a sample, then install, features,
|
|
170
|
+
The hero with a sample, then install, features, & packages sections, then the page body. Reads `name`, `tagline`, & `description`.
|
|
169
171
|
|
|
170
172
|
| Prop | Shape | Default | Rendered as |
|
|
171
173
|
| --- | --- | --- | --- |
|
|
172
174
|
| `lede` | string | `description` | The hero paragraph |
|
|
173
175
|
| `repo` | string | none | The "View on GitHub" button |
|
|
174
|
-
| `license`, `node` | string | none | Facts under the hero, such as "License: MIT"
|
|
176
|
+
| `license`, `node` | string | none | Facts under the hero, such as "License: MIT" & "Node 24+" |
|
|
175
177
|
| `install` | string | none | The install sample; with `usage`, its own section |
|
|
176
178
|
| `usage` | `{ language, code, caption? }` | none | The hero's sample |
|
|
177
179
|
| `features` | `{ title, description, href? }[]` | `[]` | Cards in the features section |
|
|
@@ -179,7 +181,7 @@ The hero with a sample, then install, features, and packages sections, then the
|
|
|
179
181
|
|
|
180
182
|
#### `norn-workspaces-home.webc`
|
|
181
183
|
|
|
182
|
-
A monorepo's home page: the hero with the install sample, then an index of the workspaces, then the page body. Reads `name`, `tagline`,
|
|
184
|
+
A monorepo's home page: the hero with the install sample, then an index of the workspaces, then the page body. Reads `name`, `tagline`, & `description`.
|
|
183
185
|
|
|
184
186
|
| Prop | Shape | Default | Rendered as |
|
|
185
187
|
| --- | --- | --- | --- |
|
|
@@ -195,21 +197,21 @@ One workspace's page in the docs frame. Reads `title`.
|
|
|
195
197
|
| Prop | Shape | Default | Rendered as |
|
|
196
198
|
| --- | --- | --- | --- |
|
|
197
199
|
| `workspaces` | `{ href, title, icon? }[]` | `[]` | The sidebar |
|
|
198
|
-
| `workspace` | `{ name, description?, html? }` | none | The `<h1>`, the description,
|
|
200
|
+
| `workspace` | `{ name, description?, html? }` | none | The `<h1>`, the description, & `html`, compiled as WebC. The page's own content follows |
|
|
199
201
|
|
|
200
|
-
On the three home layouts, the page body follows the shipped sections in a `<section>` of its own, in `norn-rich-text`,
|
|
202
|
+
On the three home layouts, the page body follows the shipped sections in a `<section>` of its own, in `norn-rich-text`, & a page with no body renders none. Markdown there is compiled once, as on `norn-docs`.
|
|
201
203
|
|
|
202
204
|
The layouts' texts ("Get started", "Read the docs", "Packages") come from `componentStrings` under the layout's name, then English (see Translating).
|
|
203
205
|
|
|
204
206
|
### Copy a layout
|
|
205
207
|
|
|
206
|
-
The layouts ship as files in the package's `layouts/` folder. To change one, copy it into the project
|
|
208
|
+
The layouts ship as files in the package's `layouts/` folder. To change one, copy it into the project & turn the shipped one off:
|
|
207
209
|
|
|
208
210
|
1. Leave the layout out: `config.addPlugin(norn, { layouts: ["norn-docs"], props })`. The other five stay.
|
|
209
211
|
2. Copy `node_modules/@allons-y/webc-patterns/layouts/norn-docs.webc` into the project's layouts folder (`_includes/` unless `dir.layouts` says otherwise).
|
|
210
|
-
3. Edit the copy. It still extends `norn-base.webc`
|
|
212
|
+
3. Edit the copy. It still extends `norn-base.webc` & reads `$data.norn`, so the mapping needs no change.
|
|
211
213
|
|
|
212
|
-
A file in the layouts folder with the name of a shipped layout,
|
|
214
|
+
A file in the layouts folder with the name of a shipped layout, & no matching entry in `layouts`, fails the build: it would replace the shipped one without a word. A copy of `norn-base.webc` also needs the text of `css/base.css` & `css/print.css` pasted over its two style placeholders, which the plugin fills only in the shipped file.
|
|
213
215
|
|
|
214
216
|
### Hooks
|
|
215
217
|
|
|
@@ -228,11 +230,11 @@ import { fillHooks } from "@allons-y/webc-patterns/plugin";
|
|
|
228
230
|
fillHooks(config, { head: '<link rel="stylesheet" href="/assets/tokens.css" webc:keep />', credit: "<my-credit></my-credit>" });
|
|
229
231
|
```
|
|
230
232
|
|
|
231
|
-
A fill is WebC markup, compiled with the page, so it may call components; give a `<link>` or `<script src>` `webc:keep`. Fills are appended in the order they are added, before or after the plugin. An unknown hook name throws,
|
|
233
|
+
A fill is WebC markup, compiled with the page, so it may call components; give a `<link>` or `<script src>` `webc:keep`. Fills are appended in the order they are added, before or after the plugin. An unknown hook name throws, & no page data can change a hook: `norn-base` reads them through the `nornHook` helper. Fills are trusted markup, written in the config.
|
|
232
234
|
|
|
233
235
|
### Theming
|
|
234
236
|
|
|
235
|
-
A shared token is a custom property named for its path in `tokens.json`: `ui.border.color` is `--norn-ui-border-color`. Every component reads its tokens with the default compiled in as the fallback, so nothing has to define them
|
|
237
|
+
A shared token is a custom property named for its path in `tokens.json`: `ui.border.color` is `--norn-ui-border-color`. Every component reads its tokens with the default compiled in as the fallback, so nothing has to define them & a component renders the same with none set. Set any of them in the project's own `tokens.css`, unlayered, & every component follows. Link it from the `head` hook, & copy the file to the output:
|
|
236
238
|
|
|
237
239
|
```css
|
|
238
240
|
/* assets/tokens.css */
|
|
@@ -248,7 +250,7 @@ fillHooks(config, { head: '<link rel="stylesheet" href="/assets/tokens.css" webc
|
|
|
248
250
|
config.addPassthroughCopy("assets");
|
|
249
251
|
```
|
|
250
252
|
|
|
251
|
-
The accent drives the link color (`--norn-text-accent`)
|
|
253
|
+
The accent drives the link color (`--norn-text-accent`) & the text on an accent surface (`--norn-text-on-accent`) too, since their defaults are derived from it. The heading face (`--norn-font-heading`) follows the body face until it is set. The properties sit in no layer, so the order of the stylesheets does not matter. To read a token in the project's own CSS, give it the default as the fallback, as the components do: `var(--norn-space-m, 1.25rem)`. The component preview lists every token with its default.
|
|
252
254
|
|
|
253
255
|
| Group | Tokens |
|
|
254
256
|
| --- | --- |
|
|
@@ -261,7 +263,7 @@ The accent drives the link color (`--norn-text-accent`) and the text on an accen
|
|
|
261
263
|
| `layout` | `--norn-layout-width` |
|
|
262
264
|
| `status` | `--norn-status-info`, `--norn-status-success`, `--norn-status-warning`, `--norn-status-danger` |
|
|
263
265
|
|
|
264
|
-
A theme is a file like that, plus the components
|
|
266
|
+
A theme is a file like that, plus the components & hook fills it adds through the plugin's `components` option & `fillHooks`. A theme styles a component with CSS against its tag, in its own layer; no component exposes a custom property of its own. [`@allons-y/webc-oss-site`](https://github.com/allonsy-studio/webc-resources/tree/main/packages/webc-oss-site#readme) is a theme. Its `css/tokens.css` sets the mono face, its `css/brand.css` draws the header strip & styles the footer name by the component tags, both in the `norn.oss` layer, & its plugin fills all four hooks:
|
|
265
267
|
|
|
266
268
|
```css
|
|
267
269
|
@layer norn.oss {
|
|
@@ -281,7 +283,7 @@ A theme is a file like that, plus the components and hook fills it adds through
|
|
|
281
283
|
|
|
282
284
|
### Collisions
|
|
283
285
|
|
|
284
|
-
Tag names are the file names of the components: `norn-*` for the patterns,
|
|
286
|
+
Tag names are the file names of the components: `norn-*` for the patterns, & `oss-*` for the OSS site theme. A project component with the tag of a packaged one, a `norn-link-button.webc` of its own, fails the build with "Global component name collision". Give the project's components another prefix, or replace a packaged one on purpose by leaving it out:
|
|
285
287
|
|
|
286
288
|
```js
|
|
287
289
|
config.addPlugin(norn, { props, exclude: ["norn-card"], components: ["_includes/*.webc"] });
|
|
@@ -295,7 +297,7 @@ config.addPlugin(norn, { props, exclude: ["norn-card"], components: ["_includes/
|
|
|
295
297
|
|
|
296
298
|
### The reset
|
|
297
299
|
|
|
298
|
-
`css/reset.css` is optional, in the `norn.reset` layer: the components
|
|
300
|
+
`css/reset.css` is optional, in the `norn.reset` layer: the components & layouts look the same without it. The plugin exports its path as `reset`. Copy it to the site & link it from the head hook, or embed its text:
|
|
299
301
|
|
|
300
302
|
```js
|
|
301
303
|
import fs from "node:fs";
|
|
@@ -306,7 +308,7 @@ fillHooks(config, { head: `<style>${fs.readFileSync(reset, "utf8")}</style>` });
|
|
|
306
308
|
|
|
307
309
|
### A layout of the project's own
|
|
308
310
|
|
|
309
|
-
A layout that does not extend `norn-base` calls `norn-head` in its head, which declares the layer order
|
|
311
|
+
A layout that does not extend `norn-base` calls `norn-head` in its head, which declares the layer order & links the bundles, & adds the base & print styles, `css/base.css` & `css/print.css` (the plugin exports their paths as `base` & `print`):
|
|
310
312
|
|
|
311
313
|
```html
|
|
312
314
|
<!doctype html>
|
|
@@ -323,15 +325,15 @@ A layout that does not extend `norn-base` calls `norn-head` in its head, which d
|
|
|
323
325
|
</html>
|
|
324
326
|
```
|
|
325
327
|
|
|
326
|
-
- **Render a Markdown page's `content` with `@html`.** WebC then compiles the `norn-callout`
|
|
327
|
-
- **Call head components with `<meta webc:is>`.** A custom tag in `<head>` makes the parser close the head early, so a head component is called as a `<meta>` with `webc:is`
|
|
328
|
+
- **Render a Markdown page's `content` with `@html`.** WebC then compiles the `norn-callout` & `norn-code-block` tags the add-ons write.
|
|
329
|
+
- **Call head components with `<meta webc:is>`.** A custom tag in `<head>` makes the parser close the head early, so a head component is called as a `<meta>` with `webc:is` & `webc:nokeep`. A void tag has no children, so `norn-head` has no slot: write extra head tags after it.
|
|
328
330
|
- **The layer order comes first.** `norn-head` declares it in an inline style ahead of the bundle links, so it holds whatever order the page's styles bundle in.
|
|
329
|
-
- **Link bundles with `webc:keep`.** WebC removes `<link>`
|
|
330
|
-
- **Every packaged layer sits inside one `norn` layer:** `norn.reset`, `norn.base`, `norn.layout`, `norn.components`, `norn.oss`, `norn.print`. A project that uses its own layers, or a framework such as Tailwind, orders the whole package with one name, as in `@layer norn, base, components, utilities;`,
|
|
331
|
+
- **Link bundles with `webc:keep`.** WebC removes `<link>` & `<script src>` without it. `norn-head` does this for the bundles.
|
|
332
|
+
- **Every packaged layer sits inside one `norn` layer:** `norn.reset`, `norn.base`, `norn.layout`, `norn.components`, `norn.oss`, `norn.print`. A project that uses its own layers, or a framework such as Tailwind, orders the whole package with one name, as in `@layer norn, base, components, utilities;`, & no layer names collide.
|
|
331
333
|
- **Project CSS stays unlayered.** It beats every layer without `!important`.
|
|
332
334
|
- **`.visually-hidden` hides text but keeps it read.** `css/base.css` defines it. It shows again while it or a child has focus.
|
|
333
335
|
|
|
334
|
-
Copy the two stylesheets to the output with `addPassthroughCopy`, or embed their text as `norn-base` does. See the [neutral fixture](https://github.com/allonsy-studio/webc-resources/tree/main/fixtures/neutral) for a working site on the plugin
|
|
336
|
+
Copy the two stylesheets to the output with `addPassthroughCopy`, or embed their text as `norn-base` does. See the [neutral fixture](https://github.com/allonsy-studio/webc-resources/tree/main/fixtures/neutral) for a working site on the plugin & the layouts, with no theme.
|
|
335
337
|
|
|
336
338
|
### Markdown
|
|
337
339
|
|
|
@@ -348,15 +350,15 @@ config.amendLibrary("md", headingAnchors);
|
|
|
348
350
|
config.addJavaScriptFunction("nornHeadings", headings);
|
|
349
351
|
```
|
|
350
352
|
|
|
351
|
-
- `webcTags` keeps a component tag with WebC attributes (`@variant`, `:@level`, `webc:if`) as HTML. Without it, markdown-it escapes the tag to text: CommonMark's attribute names have no `@`. It acts only on custom elements, names with a hyphen,
|
|
353
|
+
- `webcTags` keeps a component tag with WebC attributes (`@variant`, `:@level`, `webc:if`) as HTML. Without it, markdown-it escapes the tag to text: CommonMark's attribute names have no `@`. It acts only on custom elements, names with a hyphen, & only when the library's `html` option is on, as it is in Eleventy. It also gives a `<script>` or a `<link>` in Markdown `webc:keep`, so an embed (`<script async src="https://…">`, `<script src="/local.js">`) reaches the browser as written: without it, WebC fails the build on a full URL or a site path, & moves an inline script into the page bundle. Where a layout inserts the HTML without compiling it, the attribute stays in the output, where browsers ignore it.
|
|
352
354
|
- `scrollTables` wraps each table in `norn-simple-table`.
|
|
353
355
|
- `callouts` turns a `> [!NOTE]` blockquote into a `norn-callout` of that kind.
|
|
354
|
-
- `singleTitle` keeps a page on `norn-docs` or `norn-workspace`, which show the title as their h1, to one h1: a leading `# Title` that repeats the title goes,
|
|
355
|
-
- `headingAnchors` renders each h2
|
|
356
|
+
- `singleTitle` keeps a page on `norn-docs` or `norn-workspace`, which show the title as their h1, to one h1: a leading `# Title` that repeats the title goes, & any other h1 becomes an h2. `{ layouts }` names a project layout that shows the title too.
|
|
357
|
+
- `headingAnchors` renders each h2 & h3 as `norn-heading-anchor`, with an id from `slugify`, as an author writes it: `## Install` becomes `<norn-heading-anchor @slug="install">Install</norn-heading-anchor>`. A heading whose text holds a link keeps that link & gets the id only, since a link can't hold another. Like the callouts, the tag needs WebC to compile it: on a layout that doesn't, such as a Nunjucks one of the project's own, or in a feed built from `templateContent`, it stays an uncompiled tag.
|
|
356
358
|
- `headings(html)` lists the anchored headings for `norn-toc`, from compiled HTML or from Markdown output that WebC has not compiled yet, `norn-heading-anchor` tags included. Register it as `nornHeadings`.
|
|
357
|
-
- `slugify(text)` is the id function `headingAnchors` uses. It keeps the letters
|
|
359
|
+
- `slugify(text)` is the id function `headingAnchors` uses. It keeps the letters & digits of any script (`## 日本語の見出し` gets `id="日本語の見出し"`), lowercases them, takes the accents off Latin letters, & joins the rest with hyphens. A repeated heading gets `-2`, `-3`, & so on, counted across the page, so two Markdown blocks on one page never share an id.
|
|
358
360
|
|
|
359
|
-
The add-on writes only what an author would write by hand,
|
|
361
|
+
The add-on writes only what an author would write by hand, & no text of its own. A callout title, a code block's labels, & every other string come from the component's slots, which fall back to `componentStrings` & then English (see Translating).
|
|
360
362
|
|
|
361
363
|
### Components in Markdown
|
|
362
364
|
|
|
@@ -379,18 +381,18 @@ Write a component in Markdown as its tag, with its props, as in a WebC file. Two
|
|
|
379
381
|
</norn-callout>
|
|
380
382
|
```
|
|
381
383
|
|
|
382
|
-
plugin-webc renders each block with the site's Markdown library, so the add-ons apply,
|
|
384
|
+
plugin-webc renders each block with the site's Markdown library, so the add-ons apply, & the page then compiles the output. Keep the Markdown in a block flush left: an indented `## Heading` renders as a paragraph. `11ty:type="liquid,md"` runs Liquid first, for page data.
|
|
383
385
|
|
|
384
386
|
In both routes:
|
|
385
387
|
|
|
386
|
-
- A block component takes its open tag alone on a line, a blank line, the Markdown body, a blank line,
|
|
388
|
+
- A block component takes its open tag alone on a line, a blank line, the Markdown body, a blank line, & its close tag alone on a line. Without the blank lines, CommonMark keeps the body as raw HTML, so `**bold**` stays literal. On one line with text, the component lands inside a `<p>`.
|
|
387
389
|
- An inline component, such as `norn-icon` or `norn-link-button`, may sit in a sentence.
|
|
388
390
|
- A tag fits on one line. CommonMark reads no HTML tag whose attributes span lines.
|
|
389
|
-
- Code spans
|
|
390
|
-
- A `<script>` or `<link>` stays where it is written, for the browser,
|
|
391
|
+
- Code spans & fences stay literal: `` `<norn-icon @name="info">` `` shows the tag.
|
|
392
|
+
- A `<script>` or `<link>` stays where it is written, for the browser, & WebC's bundler leaves it alone.
|
|
391
393
|
- The content is compiled as WebC, so it is as trusted as a `.webc` file: a dynamic attribute (`:data-x="…"`) runs at build time. Render content from outside the repository with `markdown: false` or through `@raw`.
|
|
392
394
|
|
|
393
|
-
Avoid `markdownTemplateEngine: "webc"`. WebC then runs before Markdown,
|
|
395
|
+
Avoid `markdownTemplateEngine: "webc"`. WebC then runs before Markdown, & Markdown parses WebC's output again: a blank line in a component's output turns into a paragraph, `> [!TIP]` loses its `>`, a tag in a fence is compiled, so a code sample shows rendered HTML, & any dynamic attribute in the page text runs at build time. Keep `markdownTemplateEngine: false`, as in Setup, & use one of the two routes above.
|
|
394
396
|
|
|
395
397
|
### Project data
|
|
396
398
|
|
|
@@ -398,8 +400,8 @@ Avoid `markdownTemplateEngine: "webc"`. WebC then runs before Markdown, and Mark
|
|
|
398
400
|
|
|
399
401
|
| Export | Purpose |
|
|
400
402
|
| --- | --- |
|
|
401
|
-
| `buildSite({ packagePath, projectPath, host })` | Site facts from `package.json`
|
|
402
|
-
| `buildWorkspaces({ root })` | One entry per workspace, an item for `workspaces`: `href`, `title`,
|
|
403
|
+
| `buildSite({ packagePath, projectPath, host })` | Site facts from `package.json` & `project.json`: name, tagline, description, license, repository links, the Node version, & the URL (the project's, or `host` plus the repository name) |
|
|
404
|
+
| `buildWorkspaces({ root })` | One entry per workspace, an item for `workspaces`: `href`, `title`, & `description`, with the package `name` & `slug`, & its SKILL.md or README.md as `html`, rendered with the site's Markdown add-ons, so headings get the same ids & anchors as a docs page. The README's raw HTML renders as HTML, as on GitHub. Nothing is sanitized: the README is the project's own, & `norn-workspace` compiles it as WebC, as trusted as any page |
|
|
403
405
|
| `npmRelease(packageName)` | Whether the package has a `latest` release on npm, for badges. Cached an hour; offline is no release |
|
|
404
406
|
| `accentHex(cssPath)` | The `--norn-ui-accent` hex digits a stylesheet sets, for a badge color |
|
|
405
407
|
|
|
@@ -407,40 +409,40 @@ The `project.json` schema is `@allons-y/webc-patterns/schema/project.schema.json
|
|
|
407
409
|
|
|
408
410
|
## Components
|
|
409
411
|
|
|
410
|
-
| Component | Props
|
|
412
|
+
| Component | Props & slots | Purpose |
|
|
411
413
|
| --- | --- | --- |
|
|
412
|
-
| `norn-head` | `@title`, `@description`, `@url`, `@theme-color`, `@og-title`, `@og-image`, `@og-image-alt`, `:@theme-toggle` | Head metadata, Open Graph
|
|
414
|
+
| `norn-head` | `@title`, `@description`, `@url`, `@theme-color`, `@og-title`, `@og-image`, `@og-image-alt`, `:@theme-toggle` | Head metadata, Open Graph & Twitter card tags, the layer order, & the bundle links. `norn-base` calls it |
|
|
413
415
|
| `norn-skip-link` | `@href`, slot `label` (the text) | Link past the page chrome to the main content |
|
|
414
|
-
| `norn-header` | slot `brand` (the home link), default slot (the links), slots `label`
|
|
415
|
-
| `norn-footer` | default slot (the columns), slot `colophon`, `@width`
|
|
416
|
+
| `norn-header` | slot `brand` (the home link), default slot (the links), slots `label` & `summary`, `@logo-height` (a CSS length, 2rem by default) | Brand link & primary navigation. Below 40rem the links fold into a closed `<details>` |
|
|
417
|
+
| `norn-footer` | default slot (the columns), slot `colophon`, `@width` & `@lead-width` (CSS lengths) | Footer lock-up: a lead column up to 25rem, then columns sized to their content |
|
|
416
418
|
| `norn-hero` | `@width` (`layout` or `measure`), default slot (h1, lede, actions, `norn-fact-list` with `@gap="l"`, extras) | Page intro |
|
|
417
|
-
| `norn-card` | `@accent` (`accent`, `info`, `success`, `warning`, `danger`, or `none`), `@title-face` (`mono`), default slot (a heading, then the body) | Card on a raised surface. A heading link covers the whole card,
|
|
419
|
+
| `norn-card` | `@accent` (`accent`, `info`, `success`, `warning`, `danger`, or `none`), `@title-face` (`mono`), default slot (a heading, then the body) | Card on a raised surface. A heading link covers the whole card, & an accent draws a 2px line along the top |
|
|
418
420
|
| `norn-card-grid` | `@gap` (`s`, `m`, or `l`), `@min` (a length), default slot (`<li>` cards) | Responsive grid of cards |
|
|
419
|
-
| `norn-side-nav` | `:@items` (`{ href, title, icon?, children? }[]`), slots `label`
|
|
420
|
-
| `norn-sidebar-layout` | slots `nav`
|
|
421
|
+
| `norn-side-nav` | `:@items` (`{ href, title, icon?, children? }[]`), slots `label` & `search` | Page links, with `aria-current` on the current page & its parent |
|
|
422
|
+
| `norn-sidebar-layout` | slots `nav` & `summary`, default slot (the body, from its h1), `@nav-width` (a CSS length), `@gap` (`s`, `m`, `l`, `xl`), `@columns` (the body's grid columns) | Navigation column beside a page body. The navigation stays in view; below 37.5rem the columns stack & the navigation folds into a closed `<details>` |
|
|
421
423
|
| `norn-rich-text` | `@measure` (`text` or `none`), default slot | Prose styles for long-form content |
|
|
422
424
|
| `norn-pager` | `:@prev`, `:@next` (`{ href, title }`), slot `label` | Links to the neighboring pages |
|
|
423
425
|
| `norn-link-button` | `@href`, `@variant` (`primary`, `secondary`, or `quiet`), `@tone` (`accent` or `current`), default slot | A link styled as a button, for a call to action |
|
|
424
426
|
| `norn-fact-list` | `@gap` (`xs`, `s`, `m`, or `l`, the space between rows), default slot (`<li>` facts) | A row of short facts, each with an optional icon |
|
|
425
|
-
| `norn-segmented-control` | `:@icon-only`, slot `legend` (required), default slot of `<label>` + radio, or `@name`
|
|
427
|
+
| `norn-segmented-control` | `:@icon-only`, slot `legend` (required), default slot of `<label>` + radio, or `@name` & `:@options` | One choice from a few, from native radios. The checked option is tinted in the accent. A missing legend fails the build |
|
|
426
428
|
| `norn-theme-toggle` | slots `label`, `light`, `system`, `dark` | Light, system, or dark, saved in this browser. Hidden without a script. Pair with `norn-head`'s `:@theme-toggle="true"` |
|
|
427
|
-
| `norn-copy-button` | `@value` or `@source` (an id), `:@compact`, `@surface` (`base`, `raised`, or `code`), slots `copy`, `copied`, `failed`, `label` | Copies text
|
|
428
|
-
| `norn-simple-table` | default slot (a `<table>`), slot `label` | A wide table scrolls in its own box, with a shadow at the edge that has more,
|
|
429
|
-
| `norn-notice` | `@severity` (`info`, `success`, `warning`, `danger`), `:@live`, default slot, slots `prefix`
|
|
429
|
+
| `norn-copy-button` | `@value` or `@source` (an id), `:@compact`, `@surface` (`base`, `raised`, or `code`), slots `copy`, `copied`, `failed`, `label` | Copies text & says so. Hidden where the Clipboard API is missing |
|
|
430
|
+
| `norn-simple-table` | default slot (a `<table>`), slot `label` | A wide table scrolls in its own box, with a shadow at the edge that has more, & a tab stop named by the caption while it scrolls |
|
|
431
|
+
| `norn-notice` | `@severity` (`info`, `success`, `warning`, `danger`), `:@live`, default slot, slots `prefix` & `action` | A message about the page, with an icon & a severity word read first |
|
|
430
432
|
| `norn-callout` | `@variant` (`note`, `tip`, `important`, `warning`, `caution`), slot `heading`, default slot | An aside in long-form text, set like a pull quote on a raised panel with an eyebrow label, as `role="note"`. For a status message, use `norn-notice` |
|
|
431
433
|
| `norn-accordion` | default slot (`<details>` sections) | Disclosures from native `details`. Give them one `name` to open one at a time |
|
|
432
434
|
| `norn-heading-anchor` | `@slug`, `:@level`, default slot | A heading whose text links to its own section |
|
|
433
435
|
| `norn-toc` | `:@items` (`{ id, text, level }[]`, from `nornHeadings`), `@fold` (`always`, or `narrow` below 60rem), slot `label` | The page's contents, marking the section in view. Folds under its title as `@fold` says |
|
|
434
436
|
| `norn-breadcrumbs` | `:@items` (`{ href, title }[]`), slot `label` | The trail to the current page, with chevrons that mirror in right-to-left text |
|
|
435
|
-
| `norn-code-tabs` | `@group`, default slot (`norn-code-block`s), slots `label`
|
|
437
|
+
| `norn-code-tabs` | `@group`, default slot (`norn-code-block`s), slots `label` & `sample` | Tabs over code samples, kept in step by group; stacked without a script |
|
|
436
438
|
| `norn-search` | `@bundle`, `@action`, `@site`, slots `label`, `none`, `results-one`, `results-other` (and `-zero`, `-two`, `-few`, `-many`) | Live results from a Pagefind index; a plain web search form without one |
|
|
437
439
|
| `norn-icon` | `@name`, `@size` (`s` or `m`), slot `label` | An inline icon from a built-in set or the plugin's `icons` option, at 1em, or the title size for `m`. Decorative unless it has a label; directional icons mirror in right-to-left text |
|
|
438
440
|
|
|
439
|
-
A component is styled through the shared tokens in `tokens.json` (`--norn-ui-accent`, `--norn-ui-border-color`, `--norn-space-m`,
|
|
441
|
+
A component is styled through the shared tokens in `tokens.json` (`--norn-ui-accent`, `--norn-ui-border-color`, `--norn-space-m`, & so on). The component preview lists the tokens each one reads, from its source. Each token falls back to its default, compiled into the component, so a component renders the same with no tokens set, & no stylesheet defines them. A custom property of a component's own is not part of its documented API.
|
|
440
442
|
|
|
441
443
|
### Pager
|
|
442
444
|
|
|
443
|
-
`norn-docs` links the neighbors itself. In a page of the project's own, `adjacent` returns the pages around the current one: map them to `{ href, title }` at the call site,
|
|
445
|
+
`norn-docs` links the neighbors itself. In a page of the project's own, `adjacent` returns the pages around the current one: map them to `{ href, title }` at the call site, & keep the lookup in the expression: a `webc:setup` block in a layout runs once per template, so a value computed there is shared by every page.
|
|
444
446
|
|
|
445
447
|
```html
|
|
446
448
|
<norn-pager
|
|
@@ -453,7 +455,7 @@ Here `link` is a pure helper in the layout's `webc:setup` block: `(page) => (pag
|
|
|
453
455
|
|
|
454
456
|
### Translating
|
|
455
457
|
|
|
456
|
-
Every string a visitor sees or hears, accessible names
|
|
458
|
+
Every string a visitor sees or hears, accessible names & text a script shows included, is content in the page: a named slot on the component. Fill the slot on the tag for one instance, as `<span slot="label">Rechercher</span>`. An empty slot falls back to the site's strings from `componentStrings`, then to the English default:
|
|
457
459
|
|
|
458
460
|
```html
|
|
459
461
|
<norn-search @bundle="/pagefind/pagefind.js">
|
|
@@ -463,7 +465,7 @@ Every string a visitor sees or hears, accessible names and text a script shows i
|
|
|
463
465
|
</norn-search>
|
|
464
466
|
```
|
|
465
467
|
|
|
466
|
-
A line break inside the tag leaves every named slot's fallback in place, so `<norn-skip-link>`
|
|
468
|
+
A line break inside the tag leaves every named slot's fallback in place, so `<norn-skip-link>` & `</norn-skip-link>` can sit on their own lines. Set the strings once for the whole site with the plugin's `strings` option, keyed by component & slot name. The plugin registers them through `componentStrings`:
|
|
467
469
|
|
|
468
470
|
```js
|
|
469
471
|
config.addPlugin(norn, {
|
|
@@ -478,25 +480,25 @@ config.addPlugin(norn, {
|
|
|
478
480
|
});
|
|
479
481
|
```
|
|
480
482
|
|
|
481
|
-
A layout has no caller to fill a slot, so its texts are keys of their own under the layout's name: `norn-landing`'s `start` ("Get started")
|
|
483
|
+
A layout has no caller to fill a slot, so its texts are keys of their own under the layout's name: `norn-landing`'s `start` ("Get started") & `license` ("License: {license}"), `norn-base`'s `license` ("Licensed under {license}"), & so on. `defaultStrings` lists every component, layout, & key with its English default. A key is the slot it fills; `norn-callout`'s `heading` & `norn-notice`'s `prefix` take one key per variant or severity, & `norn-code-block` reads its button texts from the `norn-copy-button` keys. An unknown component or key fails the build with the list of valid ones. For a site in several languages, key the tables by language tag, as `{ fr: { … }, de: { … } }`: each page picks its table by `page.lang`, which [Eleventy's i18n plugin](https://www.11ty.dev/docs/plugins/i18n/) sets from the URL (`/fr/…`), & `fr-CA` falls back to `fr`. `norn-base` sets `<html lang>` from the `lang` prop, which falls back to `page.lang`. Then:
|
|
482
484
|
|
|
483
|
-
- A landmark names itself with `aria-labelledby`, pointing at its own text: the title of `norn-toc`, or visually hidden text in `norn-header`, `norn-side-nav`, `norn-pager`,
|
|
484
|
-
- Text only a script shows sits in the page as hidden elements that the script reads: `norn-copy-button`'s texts, `norn-search`'s statuses, `norn-theme-toggle`'s names,
|
|
485
|
-
- `norn-search` picks `results-one`, `results-other`, or another plural form with `Intl.PluralRules` for the nearest `lang`,
|
|
485
|
+
- A landmark names itself with `aria-labelledby`, pointing at its own text: the title of `norn-toc`, or visually hidden text in `norn-header`, `norn-side-nav`, `norn-pager`, & `norn-breadcrumbs`.
|
|
486
|
+
- Text only a script shows sits in the page as hidden elements that the script reads: `norn-copy-button`'s texts, `norn-search`'s statuses, `norn-theme-toggle`'s names, & `norn-code-tabs`'s fallback tab name.
|
|
487
|
+
- `norn-search` picks `results-one`, `results-other`, or another plural form with `Intl.PluralRules` for the nearest `lang`, & formats the count for it. `{count}` stands in for the number. An empty form falls back to `results-other`.
|
|
486
488
|
- `norn-notice`'s `prefix` carries its own punctuation, as in `"Remarque : "`.
|
|
487
489
|
- `norn-simple-table` without a caption or a `label` slot names its scroll box from the column headings, so it needs no string of its own.
|
|
488
490
|
- Markdown callouts take their titles from `componentStrings`, like any callout: the Markdown add-on writes no `heading` slot.
|
|
489
|
-
- `norn-pager`'s arrows are drawn in CSS
|
|
491
|
+
- `norn-pager`'s arrows are drawn in CSS & point the other way in right-to-left text.
|
|
490
492
|
|
|
491
493
|
## Exports
|
|
492
494
|
|
|
493
495
|
| Export | Purpose |
|
|
494
496
|
| --- | --- |
|
|
495
497
|
| `patterns({ exclude })` | Absolute glob for the package's components, minus any names in `exclude` |
|
|
496
|
-
| `adjacent(pages, page)` | Previous
|
|
498
|
+
| `adjacent(pages, page)` | Previous & next page in a collection, for `norn-pager` |
|
|
497
499
|
| `dropEmptyBundleTags` | Eleventy transform that drops the empty bundle tags a page without bundles is left with |
|
|
498
|
-
| `componentStrings(table)` | Site-wide fallbacks for the strings, by component or layout
|
|
499
|
-
| `defaultStrings` | Every component
|
|
500
|
+
| `componentStrings(table)` | Site-wide fallbacks for the strings, by component or layout & key, or by language tag, as the `nornComponentStrings` helper |
|
|
501
|
+
| `defaultStrings` | Every component & layout string & its English default, by name & key |
|
|
500
502
|
|
|
501
503
|
`@allons-y/webc-patterns/plugin` exports the plugin:
|
|
502
504
|
|
|
@@ -504,8 +506,8 @@ A layout has no caller to fill a slot, so its texts are keys of their own under
|
|
|
504
506
|
| --- | --- |
|
|
505
507
|
| `default` | The Norn plugin, `config.addPlugin(norn, options)` |
|
|
506
508
|
| `fillHooks(config, { head, banner, cta, credit })` | Adds markup to `norn-base`'s hooks |
|
|
507
|
-
| `reset`, `base`, `print` | Absolute paths to `css/reset.css`, `css/base.css`,
|
|
508
|
-
| `HOOKS`, `LAYOUTS` | The hook names
|
|
509
|
+
| `reset`, `base`, `print` | Absolute paths to `css/reset.css`, `css/base.css`, & `css/print.css` |
|
|
510
|
+
| `HOOKS`, `LAYOUTS` | The hook names & the layout names |
|
|
509
511
|
| `compiles(data, layout, aliases)` | Whether a shipped layout compiles the page content: the rule behind `nornCompiles` |
|
|
510
512
|
|
|
511
513
|
`@allons-y/webc-patterns/markdown` exports the Markdown add-on:
|
|
@@ -515,16 +517,19 @@ A layout has no caller to fill a slot, so its texts are keys of their own under
|
|
|
515
517
|
| `webcTags(md)` | markdown-it amend that keeps component tags with WebC attributes, such as `@variant`, as HTML |
|
|
516
518
|
| `scrollTables(md)` | markdown-it amend that wraps each table in `norn-simple-table` |
|
|
517
519
|
| `callouts(md)` | markdown-it amend that renders `> [!NOTE]` blockquotes as `norn-callout` |
|
|
518
|
-
| `singleTitle(md, { layouts })` | markdown-it amend that drops a leading h1 that repeats the title,
|
|
519
|
-
| `headingAnchors(md, { levels })` | markdown-it amend that renders headings as `norn-heading-anchor` with an id; levels 2
|
|
520
|
+
| `singleTitle(md, { layouts })` | markdown-it amend that drops a leading h1 that repeats the title, & turns any other h1 into an h2, on `norn-docs` & `norn-workspace` by default |
|
|
521
|
+
| `headingAnchors(md, { levels })` | markdown-it amend that renders headings as `norn-heading-anchor` with an id; levels 2 & 3 by default |
|
|
520
522
|
| `headings(html, { levels })` | The anchored headings of rendered HTML or Markdown output as `{ id, text, level }[]`, for `norn-toc`; register it as `nornHeadings` |
|
|
521
523
|
| `slugify(text)` | The URL fragment `headingAnchors` makes from heading text, in any script |
|
|
522
524
|
|
|
523
|
-
`@allons-y/webc-patterns/project` exports the project data builders above. The stylesheets are exported as `@allons-y/webc-patterns/css/reset.css`, `/css/base.css`,
|
|
525
|
+
`@allons-y/webc-patterns/project` exports the project data builders above. The stylesheets are exported as `@allons-y/webc-patterns/css/reset.css`, `/css/base.css`, & `/css/print.css`, & the schema as `@allons-y/webc-patterns/schema/project.schema.json`.
|
|
524
526
|
|
|
525
527
|
## License
|
|
526
528
|
|
|
527
|
-
[MPL-2.0](LICENSE): use freely, modify as needed; changes to MPL-licensed files
|
|
529
|
+
> [MPL-2.0](LICENSE): use freely, modify as needed; changes to MPL-licensed files
|
|
530
|
+
> should be shared back under the same license.
|
|
531
|
+
|
|
532
|
+
---
|
|
528
533
|
|
|
529
534
|
<p align="center">
|
|
530
535
|
<a href="https://allons-y.studio">
|