@keenmate/web-components-devkit 1.0.0-rc06 → 1.0.0-rc08
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/CHANGELOG.md +93 -0
- package/README.md +64 -20
- package/package.json +1 -1
- package/src/cli/commands/check-pages.js +189 -0
- package/src/cli/commands/check-vars.js +20 -8
- package/src/cli/commands/doctor.js +146 -1
- package/src/cli/kmwc.js +9 -0
- package/src/cli/repo-checks.js +366 -0
- package/src/cli/sync-plan.js +1 -0
- package/src/examples/css/base.css +28 -0
- package/src/examples/css/content.css +5 -2
- package/src/examples/css/index-page.css +4 -0
- package/src/examples/css/tokens.css +5 -1
- package/src/vite/index.js +2 -6
- package/src/vite/page-composer.js +30 -1
- package/templates/Makefile.tmpl +4 -1
- package/templates/claude-block.md +8 -2
|
@@ -118,7 +118,7 @@
|
|
|
118
118
|
padding: 0.2rem 0.4rem;
|
|
119
119
|
border-radius: 3px;
|
|
120
120
|
font-size: 0.9em;
|
|
121
|
-
color: var(--kmwc-
|
|
121
|
+
color: var(--kmwc-inline-code-color);
|
|
122
122
|
font-family: var(--kmwc-mono-font-family);
|
|
123
123
|
/* A long identifier has no break opportunity — break it anywhere
|
|
124
124
|
rather than widen the page on a phone. */
|
|
@@ -157,8 +157,11 @@
|
|
|
157
157
|
background-color: var(--kmwc-accent-light-bg-hover);
|
|
158
158
|
color: var(--kmwc-accent-color);
|
|
159
159
|
font-weight: 600;
|
|
160
|
-
padding:
|
|
160
|
+
/* No padding: a match inside a word ("Town|send") must not split it. */
|
|
161
|
+
padding: 0;
|
|
161
162
|
border-radius: var(--kmwc-radius-sm);
|
|
163
|
+
box-decoration-break: clone;
|
|
164
|
+
-webkit-box-decoration-break: clone;
|
|
162
165
|
}
|
|
163
166
|
|
|
164
167
|
/* ==========================================================================
|
|
@@ -118,7 +118,11 @@
|
|
|
118
118
|
--kmwc-console-info-color: #7dd3fc;
|
|
119
119
|
--kmwc-console-warn-color: #fcd34d;
|
|
120
120
|
--kmwc-console-err-color: #fca5a5;
|
|
121
|
-
|
|
121
|
+
/* Dark: the chip is a step up from the main surface (slate on a slate page, not a
|
|
122
|
+
neutral grey), and the text keeps the accent hue but at least 0.8 lightness, so a
|
|
123
|
+
mid-dark accent (treeview's #059669) stays readable on it. */
|
|
124
|
+
--kmwc-inline-code-bg: light-dark(#edf2f7, oklch(from var(--kmwc-main-bg) calc(l + 0.07) c h));
|
|
125
|
+
--kmwc-inline-code-color: light-dark(var(--kmwc-accent-color), oklch(from var(--kmwc-accent-color) max(l, 0.8) c h));
|
|
122
126
|
|
|
123
127
|
/* ======================================================================
|
|
124
128
|
COLORS — SEMANTIC
|
package/src/vite/index.js
CHANGED
|
@@ -20,7 +20,7 @@ import { readdirSync, existsSync, cpSync } from 'node:fs';
|
|
|
20
20
|
import { join, resolve } from 'node:path';
|
|
21
21
|
import { getKmwcConfig, getDevkitPackageJson, generateBuildDefines, loadPeerModule, DEVKIT_ROOT, NON_PAGE_HTML_FILES } from '../config.js';
|
|
22
22
|
import { renderThemeBootstrapScript } from '../examples/theme-switch.js';
|
|
23
|
-
import { composePage } from './page-composer.js';
|
|
23
|
+
import { composePage, insertIntoHead, insertBeforeBodyEnd } from './page-composer.js';
|
|
24
24
|
import { generateChapterIndex } from './chapter-index.js';
|
|
25
25
|
|
|
26
26
|
const AUTO_ENTRY_PATH = join(DEVKIT_ROOT, 'src', 'examples', 'auto.js');
|
|
@@ -162,11 +162,7 @@ export function createExamplesPlugin(pluginConfig = {}) {
|
|
|
162
162
|
const kitImports = isBuild ? `import '${KIT_STYLESHEET_PATH}'; import '${VIRTUAL_AUTO_ID}';` : `import '${VIRTUAL_AUTO_ID}';`;
|
|
163
163
|
const bodyHtml = `<script type="module">${kitImports}</script>\n`;
|
|
164
164
|
|
|
165
|
-
|
|
166
|
-
? html.replace(/<head[^>]*>/i, (headTag) => `${headTag}\n${headHtml}`)
|
|
167
|
-
: headHtml + html;
|
|
168
|
-
html = /<\/body>/i.test(html) ? html.replace(/<\/body>/i, `${bodyHtml}</body>`) : html + bodyHtml;
|
|
169
|
-
return html;
|
|
165
|
+
return insertBeforeBodyEnd(insertIntoHead(html, headHtml), bodyHtml);
|
|
170
166
|
},
|
|
171
167
|
},
|
|
172
168
|
|
|
@@ -64,7 +64,36 @@ export function mapOutsideComments(html, mapper, skippedPattern = HTML_COMMENT_P
|
|
|
64
64
|
return mappedHtml + mapper(html.slice(lastIndex));
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
// The real tag only — `<head[^>]*>` also matches `<header>`.
|
|
68
|
+
const HEAD_TAG_PATTERN = /<head(?=[\s>])[^>]*>/i;
|
|
69
|
+
const BODY_END_TAG = '</body>';
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Insert `headHtml` right after the page's <head> tag (prepend when there is none).
|
|
73
|
+
* The first <head> outside comments is the real one: the text "<head>" in a tooltip
|
|
74
|
+
* or a script comment comes later, and a snippet landing there breaks the page
|
|
75
|
+
* (an HTML comment inside a module script throws).
|
|
76
|
+
*/
|
|
77
|
+
export function insertIntoHead(html, headHtml) {
|
|
78
|
+
let isInserted = false;
|
|
79
|
+
const insertedHtml = mapOutsideComments(html, (text) => {
|
|
80
|
+
if (isInserted || !HEAD_TAG_PATTERN.test(text)) return text;
|
|
81
|
+
isInserted = true;
|
|
82
|
+
return text.replace(HEAD_TAG_PATTERN, (headTag) => `${headTag}\n${headHtml}`);
|
|
83
|
+
});
|
|
84
|
+
return isInserted ? insertedHtml : headHtml + html;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Insert `bodyHtml` before the LAST </body> (append when there is none): an
|
|
89
|
+
* earlier one is text — e.g. a comment inside an inline script.
|
|
90
|
+
*/
|
|
91
|
+
export function insertBeforeBodyEnd(html, bodyHtml) {
|
|
92
|
+
const bodyEndIndex = html.toLowerCase().lastIndexOf(BODY_END_TAG);
|
|
93
|
+
return bodyEndIndex < 0 ? html + bodyHtml : html.slice(0, bodyEndIndex) + bodyHtml + html.slice(bodyEndIndex);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const mapToCamelCase =(kebabName) => kebabName.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
68
97
|
|
|
69
98
|
const HTML_ESCAPES = { '&': '&', '<': '<', '>': '>', '"': '"' };
|
|
70
99
|
const mapToEscapedHtml = (text) => String(text).replace(/[&<>"]/g, (character) => HTML_ESCAPES[character]);
|
package/templates/Makefile.tmpl
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# redefined there wins, with a make "overriding recipe" warning). Per-developer
|
|
5
5
|
# overrides (container runner, image name, port) go in .makefile.env.
|
|
6
6
|
|
|
7
|
-
.PHONY: help setup dev kill-port build build-examples preview-examples package publish-dry publish publish-rc clean check-version check-vars doctor sync test test-e2e test-e2e-ui test-e2e-headed test-e2e-install image-build image-run image-stop image-clean
|
|
7
|
+
.PHONY: help setup dev kill-port build build-examples preview-examples package publish-dry publish publish-rc clean check-version check-vars doctor check-pages sync test test-e2e test-e2e-ui test-e2e-headed test-e2e-install image-build image-run image-stop image-clean
|
|
8
8
|
|
|
9
9
|
-include .makefile.env
|
|
10
10
|
DOCKER_RUNNER ?= {{RUNNER}}
|
|
@@ -91,6 +91,9 @@ check-vars: ## Validate component-variables.manifest.json against the CSS
|
|
|
91
91
|
doctor: ## Check this repo against the Keenmate component standard
|
|
92
92
|
npx kmwc doctor
|
|
93
93
|
|
|
94
|
+
check-pages: ## Load every example page at 1440/390/320px: errors, undefined elements, overflow
|
|
95
|
+
npx kmwc check-pages
|
|
96
|
+
|
|
94
97
|
sync: ## Regenerate devkit-owned files (Dockerfile, nginx.conf, Makefile, …)
|
|
95
98
|
npx kmwc sync
|
|
96
99
|
|
|
@@ -28,7 +28,10 @@ locally — every local fork is how they drifted apart.
|
|
|
28
28
|
element out. Log lines take the kit tones (`.log-line--ok|info|warn|err|muted`,
|
|
29
29
|
`--action`, timeline cells `.log-line__time` …) — don't colour them per page.
|
|
30
30
|
`<kbd>`, `<mark>`, field widths (`.w-xs` … `.w-lg`) and `.push-end` are kit
|
|
31
|
-
too — no inline styles for them.
|
|
31
|
+
too — no inline styles for them. Page colours come from the kit's `--kmwc-*`
|
|
32
|
+
tokens or `light-dark()` — a literal doesn't follow dark mode (doctor warns);
|
|
33
|
+
a demo that shows fixed colours on purpose goes in `<style data-kmwc-fixed-colors>`
|
|
34
|
+
(one rule: a `/* kmwc-fixed-colors: why */` comment before it).
|
|
32
35
|
If a second component needs a pattern, it belongs in the devkit.
|
|
33
36
|
- **Example pages are fragments:** no `<html>`/`<head>`/`<header>` — start with
|
|
34
37
|
`<meta name="kmwc:title" content="…">`, the devkit layout adds the rest. Shared text
|
|
@@ -48,4 +51,7 @@ locally — every local fork is how they drifted apart.
|
|
|
48
51
|
otherwise published with it).
|
|
49
52
|
- Before finishing: `npx kmwc doctor` must pass — it runs the devkit checks,
|
|
50
53
|
checks the `npm pack` file list for dev-only files, and runs the rulebook's
|
|
51
|
-
`*.checks.sh` suites.
|
|
54
|
+
`*.checks.sh` suites. A rulebook failure that is a real architectural decision
|
|
55
|
+
goes into `VALIDATION-NOTES.md` under a `## C-XX-N — …` heading (deferrals
|
|
56
|
+
don't count). After changing a page, `npx kmwc check-pages` loads every page at
|
|
57
|
+
desktop and phone widths and reports errors and horizontal overflow.
|