uniweb 0.14.1 → 0.14.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uniweb",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "description": "Create structured Vite + React sites with content/code separation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -42,8 +42,8 @@
42
42
  "prompts": "^2.4.2",
43
43
  "tar": "^7.0.0",
44
44
  "@uniweb/core": "0.8.0",
45
- "@uniweb/kit": "0.10.1",
46
- "@uniweb/runtime": "0.9.0"
45
+ "@uniweb/runtime": "0.9.0",
46
+ "@uniweb/kit": "0.10.2"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@uniweb/build": "0.16.0",
@@ -869,14 +869,13 @@ Names only — for signatures and props, read the package: it's on disk at `node
869
869
  **Header/layout:** `useScrolled(threshold)`, `useMobileMenu()`, `useAppearance()`
870
870
  **Overlays:** `Overlay` (modals, palettes, drawers, toasts — portals out of the layout, contains focus; read the note below before hand-rolling one)
871
871
  **Keyboard:** `useShortcut('mod+k', fn)`, `useShortcuts({…})`, `useShortcutLabel('mod+k')` — `mod` is Cmd on Apple platforms and Ctrl elsewhere, and the label renders per-platform so a hint never shows the wrong key
872
- **Long-form prose:** `<Prose>` and the container you put `<Render>` output in both use Tailwind Typography's `prose` classes, which come from a plugin your *foundation* installs — kit ships no stylesheet. Without it the markup is right and completely unstyled. Add `@tailwindcss/typography` to the foundation's deps, then:
872
+ **Long-form prose:** `<Prose>` and the container you put `<Render>` output in both use Tailwind Typography's `prose` classes. One line in the foundation's `styles.css` supplies them and points them at the site's theme:
873
873
 
874
874
  ```css
875
- @plugin "@tailwindcss/typography";
876
- @import "@uniweb/kit/prose-tokens.css"; /* makes prose answer to theme.yml */
875
+ @import "@uniweb/kit/prose-tokens.css"; /* the plugin, wired to theme.yml */
877
876
  ```
878
877
 
879
- Use **one** `prose` container per subtree — the `--tw-prose-*` variables are inherited, so a nested one silently resets them and the outer container goes on looking correct. The section that renders the document is usually the better owner; a layout should supply column width and padding.
878
+ Nothing to install — the import brings the plugin with it. **Skip the import and prose is completely unstyled**, silently: the class is there and no rules are behind it. `uniweb doctor` flags that. Use **one** `prose` container per subtree — the `--tw-prose-*` variables are inherited, so a nested one silently resets them and the outer container goes on looking correct. The section that renders the document is usually the better owner; a layout should supply column width and padding.
880
879
 
881
880
  **Documentation shells:** `useHeadings()` (the page's headings + the one being read, derived from content so it prerenders), `website.getBranchHierarchy({ route, for })` (the page tree for one branch). Kit ships no ready-made layout — a layout is your foundation's design; write it in `src/layouts/` and use these for the behaviour.
882
881
  **Layout helpers:** `useGridLayout(columns, { gap })`, `useAccordion({ multiple, defaultOpen })`
@@ -169,6 +169,41 @@ function loadSiteYml(dir) {
169
169
  * committed, and then looks like something you may edit. That is how
170
170
  * hand-authored files ended up there in the first place.
171
171
  */
172
+ /**
173
+ * Whether any component source under `dir` matches `pattern`.
174
+ *
175
+ * Only the directories a foundation puts components in, and never
176
+ * `node_modules` — this answers "did the developer write this", so a match
177
+ * inside a dependency is the wrong answer.
178
+ */
179
+ function sourceMatches(dir, pattern) {
180
+ const roots = ['sections', 'layouts', 'components']
181
+ const walk = (d, depth = 0) => {
182
+ if (depth > 6) return false
183
+ let entries
184
+ try {
185
+ entries = readdirSync(d, { withFileTypes: true })
186
+ } catch {
187
+ return false
188
+ }
189
+ for (const entry of entries) {
190
+ if (entry.name === 'node_modules' || entry.name.startsWith('.')) continue
191
+ const p = join(d, entry.name)
192
+ if (entry.isDirectory()) {
193
+ if (walk(p, depth + 1)) return true
194
+ } else if (/\.(jsx?|tsx?)$/.test(entry.name)) {
195
+ try {
196
+ if (pattern.test(readFileSync(p, 'utf8'))) return true
197
+ } catch {
198
+ // unreadable file — not this check's problem to report
199
+ }
200
+ }
201
+ }
202
+ return false
203
+ }
204
+ return roots.some((r) => walk(join(dir, r)))
205
+ }
206
+
172
207
  function checkGeneratedDataDir({ sitePath, siteName, siteYml, issues, shouldFix, fixed }) {
173
208
  const dataDir = join(sitePath, 'public', DATA_DIR)
174
209
  const declared = new Set(Object.keys(siteYml.collections || {}))
@@ -380,6 +415,52 @@ export async function doctor(args = []) {
380
415
  }
381
416
  }
382
417
 
418
+ // Prose without the tokens — a silent, total loss of styling.
419
+ //
420
+ // `@uniweb/kit/prose-tokens.css` brings Tailwind Typography with it and then
421
+ // points it at the site's theme.yml. A foundation that writes `prose` (or
422
+ // renders <Prose>/<Article>, which emit it) and does NOT import that file
423
+ // gets the class and no rules behind it: correct markup, zero styling, and
424
+ // nothing reported anywhere. Measured 2026-07-30 on a foundation missing only
425
+ // the plugin — every paragraph `margin-top: 0px`, no warning from Vite,
426
+ // Tailwind or the browser.
427
+ //
428
+ // kit closes this for anyone who imports the file; this closes it for anyone
429
+ // who does not, which is the case kit cannot reach.
430
+ for (const f of foundations) {
431
+ // `f.path` is already absolute (built above with join(workspaceDir, …)).
432
+ const stylesPath = join(f.path, 'styles.css')
433
+ if (!existsSync(stylesPath)) continue
434
+
435
+ const styles = readFileSync(stylesPath, 'utf8')
436
+ if (styles.includes('@uniweb/kit/prose-tokens.css')) continue
437
+
438
+ // Does anything here actually ask for prose? Either the class in the
439
+ // stylesheet, or kit's components, which render it.
440
+ const usesProseClass = /(^|[\s"'`])prose(\s|["'`]|$)/m.test(styles)
441
+ const usesProseComponent = sourceMatches(f.path, /<(Prose|Article)\b/)
442
+
443
+ if (!usesProseClass && !usesProseComponent) continue
444
+
445
+ const id = 'prose-without-tokens'
446
+ const reason = usesProseComponent
447
+ ? 'renders <Prose> or <Article>'
448
+ : 'uses the `prose` class'
449
+ issues.push({
450
+ id,
451
+ type: 'warning',
452
+ foundation: f.name,
453
+ message: `${f.name} ${reason} but does not import prose-tokens.css`
454
+ })
455
+ warn(`[${id}] ${f.name} ${reason}, with no prose styling behind it`)
456
+ log(
457
+ ` Tailwind Typography supplies the rules and it is not loaded, so the ` +
458
+ `markup is correct and completely unstyled — silently.`
459
+ )
460
+ log(` Add to ${f.folderName}/styles.css:`)
461
+ log(` ${colors.dim}@import "@uniweb/kit/prose-tokens.css";${colors.reset}`)
462
+ }
463
+
383
464
  if (extensions.length > 0) {
384
465
  log('')
385
466
  success(`Found ${extensions.length} extension(s):`)
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-07-30T19:35:25.684Z",
3
+ "generatedAt": "2026-07-30T22:09:40.317Z",
4
4
  "packages": {
5
5
  "@uniweb/build": {
6
6
  "version": "0.16.0",
@@ -45,7 +45,7 @@
45
45
  "deps": []
46
46
  },
47
47
  "@uniweb/kit": {
48
- "version": "0.10.1",
48
+ "version": "0.10.2",
49
49
  "path": "framework/kit",
50
50
  "deps": [
51
51
  "@uniweb/core",