c3b-lint 0.0.12 → 0.0.13

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 CHANGED
@@ -20,7 +20,7 @@ markdown that a tool can check, with one command and one config to install. It r
20
20
  stylesheets (webfonts are self-hosted), stylesheet order (`reset`, `tokens`, `main`, …, page file last),
21
21
  the skip-link rule (`<a id="skip-link" href="#main">` first in `<body>` when there is a header or nav, absent
22
22
  otherwise, `<main id="main">`), one `<h1>`, `alt` on every image, no inline handlers, no `<style>` or `style=""`
23
- (except a JS-driven custom property), relative paths only, kebab-case ids and classes, no duplicate ids,
23
+ (except a JS-driven custom property), relative paths only (a Barba site's links outside its container — header, menu — stay root-relative), kebab-case ids and classes, no duplicate ids,
24
24
  `integrity` on CDN scripts.
25
25
  5. **Project structure**: singular directory names, lowercase kebab-case asset names (and no camera exports), and,
26
26
  when `src/` holds pages, CSS only in `src/style/` + `style/page/` + `style/animation/`, JS only in `src/script/`
package/check/html.js CHANGED
@@ -26,6 +26,19 @@ const toPosix = (p) => p.split(sep).join('/');
26
26
  const attr = (el, name) => el.attrs?.find((a) => a.name === name)?.value;
27
27
  const line = (el) => el.sourceCodeLocation?.startLine ?? 0;
28
28
  const isElement = (node) => Boolean(node.tagName);
29
+ const isBarbaContainer = (node) => isElement(node) && attr(node, 'data-barba') === 'container';
30
+
31
+ // Inside Barba's page container: replaced on every navigation, so its links resolve against the URL
32
+ // of the page they came with
33
+ function inBarbaContainer(el) {
34
+ for (let node = el.parentNode; node; node = node.parentNode) {
35
+ if (isBarbaContainer(node)) {
36
+ return true;
37
+ }
38
+ }
39
+
40
+ return false;
41
+ }
29
42
 
30
43
  // Every element in document order
31
44
  function* elements(node) {
@@ -154,6 +167,10 @@ function checkPage(report, file, source) {
154
167
  report.error(h1s[1] ? at(h1s[1]) : file, `one <h1> per page (found ${ h1s.length })`);
155
168
  }
156
169
  const ids = new Map();
170
+ // A Barba site keeps everything outside its container (header, menu) for the whole visit while the URL
171
+ // changes under it, so a relative link there would resolve against whichever page is showing: those
172
+ // links stay root-relative
173
+ const barba = all.some((el) => attr(el, 'data-barba') === 'wrapper');
157
174
  for (const el of all) {
158
175
  for (const { name, value } of el.attrs ?? []) {
159
176
  if (/^on[a-z]+$/.test(name)) {
@@ -162,7 +179,8 @@ function checkPage(report, file, source) {
162
179
  if (name === 'style' && !/^\s*(--[a-z0-9-]+\s*:[^;]+;?\s*)+$/.test(value)) {
163
180
  report.error(at(el), 'no style="" attributes, except to set a JS-driven custom property');
164
181
  }
165
- if ((name === 'href' || name === 'src') && /^\/(?!\/)/.test(value)) {
182
+ const persistentLink = barba && el.name === 'a' && name === 'href' && !inBarbaContainer(el);
183
+ if ((name === 'href' || name === 'src') && /^\/(?!\/)/.test(value) && !persistentLink) {
166
184
  report.error(at(el), `root-relative path ${ value } — use a relative path`);
167
185
  }
168
186
  if (name === 'id') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "c3b-lint",
3
- "version": "0.0.12",
3
+ "version": "0.0.13",
4
4
  "description": "Lints a co:lab project against the rules a tool can check: ESLint, Stylelint, the 500-line limit and the shared .editorconfig; --init writes the config files.",
5
5
  "license": "GPL-3.0",
6
6
  "type": "module",