weifuwu 0.27.23 β†’ 0.27.25

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
@@ -69,7 +69,7 @@ Server-rendered HTML with zero frontend build tools. Uses `html()` tagged templa
69
69
  for safe HTML rendering, and `weifuwu-ui.js` for client-side interactions.
70
70
 
71
71
  ```ts
72
- import { Router, serve, html, raw, layout, view, wfuwAssets, theme, i18n, flash } from 'weifuwu'
72
+ import { Router, serve, html, raw, layout, view, wfuwAssets, wfuwVersion, theme, i18n, flash } from 'weifuwu'
73
73
 
74
74
  const app = new Router()
75
75
 
@@ -125,7 +125,7 @@ html`<div>${html`<span>nested</span>`}</div>`
125
125
  Wraps page HTML in a layout template. Multiple layouts nest naturally.
126
126
 
127
127
  ```ts
128
- import { html, raw } from 'weifuwu'
128
+ import { html, raw, wfuwVersion } from 'weifuwu'
129
129
 
130
130
  // ui/app/layout.ts
131
131
  export default function (body: string, ctx: any) {
@@ -133,8 +133,8 @@ export default function (body: string, ctx: any) {
133
133
  <html data-theme="${ctx.theme?.value || 'light'}">
134
134
  <head>
135
135
  <meta charset="utf-8" />
136
- <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css" />
137
- <script src="/__wfw/js/weifuwu-ui.js"></script>
136
+ <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
137
+ <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
138
138
  <script id="__wfw-i18n" type="application/json">
139
139
  ${raw(JSON.stringify(ctx.i18n?.messages || {}))}
140
140
  </script>
@@ -172,11 +172,15 @@ import { wfuwAssets } from 'weifuwu'
172
172
  app.use(wfuwAssets()) // serve /__wfw/js/weifuwu-ui.js + /__wfw/css/weifuwu-ui.css
173
173
  ```
174
174
 
175
- In your layout:
175
+ In your layout (with cache-busting via `wfuwVersion`):
176
+
177
+ ```ts
178
+ import { wfuwVersion } from 'weifuwu'
179
+ ```
176
180
 
177
181
  ```html
178
- <script src="/__wfw/js/weifuwu-ui.js"></script>
179
- <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css" />
182
+ <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
183
+ <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
180
184
  ```
181
185
 
182
186
  ---
@@ -565,9 +569,13 @@ import { wfuwAssets } from 'weifuwu'
565
569
  app.use(wfuwAssets())
566
570
  ```
567
571
 
572
+ ```ts
573
+ import { wfuwVersion } from 'weifuwu'
574
+ ```
575
+
568
576
  ```html
569
- <script src="/__wfw/js/weifuwu-ui.js"></script>
570
- <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css" />
577
+ <script src="/__wfw/js/weifuwu-ui.js?v=${wfuwVersion}"></script>
578
+ <link rel="stylesheet" href="/__wfw/css/weifuwu-ui.css?v=${wfuwVersion}" />
571
579
  ```
572
580
 
573
581
  ### Standalone utilities
@@ -4,12 +4,10 @@
4
4
 
5
5
  This project uses weifuwu-ui.js β€” a zero-dependency frontend runtime (~5KB).
6
6
 
7
- Read the full reference at `node_modules/weifuwu/dist/docs/ssr/ui.md` or online:
7
+ **Must read**: `node_modules/weifuwu/README.md` for the full framework reference.
8
8
 
9
- - **weifuwu-ui.js**: AJAX loading, state binding (`wu-data`, `wu-text`, `wu-show`),
10
- event handling (`wu-on`), SSE streaming, WebSocket, theme/i18n/flash, UI components
11
- - **weifuwu-ui.css**: Button, form, card, modal, collapse, tabs, dropdown, toast styles
12
- with CSS variable theming (light/dark mode via `data-theme` on `<html>`)
9
+ For weifuwu-ui.js attribute reference and component docs, see:
10
+ `node_modules/weifuwu/dist/docs/ssr/ui.md`
13
11
 
14
12
  ### Key attributes
15
13
 
@@ -1,5 +1,4 @@
1
1
  {
2
- "theme": "πŸŒ™",
3
2
  "lang": "δΈ­ζ–‡",
4
3
  "title": "Build APIs & UI, Zero Build Step",
5
4
  "cta": "Try Me",
@@ -1,5 +1,4 @@
1
1
  {
2
- "theme": "πŸŒ™",
3
2
  "lang": "EN",
4
3
  "title": "ι›ΆηΌ–θ―‘ζž„ε»Ί API ε’Œ UI",
5
4
  "cta": "体ιͺŒδΈ€δΈ‹",
@@ -3,13 +3,20 @@ import { html, raw } from 'weifuwu'
3
3
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
4
4
  export default function (ctx: any) {
5
5
  const t = ctx.i18n?.t || ((k: string) => k)
6
+ // Theme/language buttons: show opposite (click to switch)
7
+ const themeVal = ctx.theme?.value || 'system'
8
+ const btnTheme = themeVal === 'dark' ? 'light' : 'dark'
9
+ const btnIcon = btnTheme === 'dark' ? 'πŸŒ™' : 'β˜€οΈ'
10
+ const locale = ctx.i18n?.locale || 'en'
11
+ const btnLang = locale === 'zh-CN' ? 'en' : 'zh-CN'
12
+ const langLabel = btnLang === 'zh-CN' ? 'δΈ­ζ–‡' : 'EN'
6
13
 
7
14
  return html`<div wu-data='${raw(JSON.stringify({ open: false }))}'>
8
15
  <nav class="wu-flex wu-items-center wu-justify-between wu-p-4 wu-border-bottom">
9
16
  <strong class="wu-text-lg">weifuwu</strong>
10
17
  <div class="wu-flex wu-gap-sm wu-items-center">
11
- <button wu-theme="dark" class="wu-btn wu-btn-sm" wu-text-key="theme">πŸŒ™</button>
12
- <button wu-lang="zh-CN" class="wu-btn wu-btn-sm" wu-text-key="lang">δΈ­ζ–‡</button>
18
+ <button wu-theme="${btnTheme}" class="wu-btn wu-btn-sm">${raw(btnIcon)}</button>
19
+ <button wu-lang="${btnLang}" class="wu-btn wu-btn-sm" wu-text-key="lang">${raw(langLabel)}</button>
13
20
  </div>
14
21
  </nav>
15
22
 
@@ -723,15 +723,19 @@ const WFU_VERSION = '0.27.20';
723
723
  // ═══════════════════════════════════════════════════════════════════
724
724
 
725
725
  function initTheme() {
726
- // Set initial theme from cookie
726
+ // Set initial theme from cookie, sync button state
727
727
  const cookie = document.cookie.match(/theme=([^;]+)/)?.[1] || 'system'
728
- applyTheme(cookie)
728
+ const resolved = applyTheme(cookie)
729
+ syncThemeButtons(resolved)
729
730
 
730
731
  // Listen for system preference changes
731
732
  if (window.matchMedia) {
732
733
  window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => {
733
734
  const current = document.cookie.match(/theme=([^;]+)/)?.[1] || 'system'
734
- if (current === 'system') applyTheme('system')
735
+ if (current === 'system') {
736
+ const r = applyTheme('system')
737
+ syncThemeButtons(r)
738
+ }
735
739
  })
736
740
  }
737
741
  }
@@ -744,6 +748,15 @@ const WFU_VERSION = '0.27.20';
744
748
  : 'light'
745
749
  : value
746
750
  document.documentElement.setAttribute('data-theme', theme)
751
+ return theme
752
+ }
753
+
754
+ function syncThemeButtons(resolved) {
755
+ const target = resolved === 'dark' ? 'light' : 'dark'
756
+ document.querySelectorAll('[wu-theme]').forEach((b) => {
757
+ b.setAttribute('wu-theme', target)
758
+ b.textContent = target === 'dark' ? 'πŸŒ™' : 'β˜€οΈ'
759
+ })
747
760
  }
748
761
 
749
762
  // Theme switching (delegated click)
@@ -756,16 +769,7 @@ const WFU_VERSION = '0.27.20';
756
769
  // Sync with server (no redirect, JSON request)
757
770
  fetch('/__theme/' + value, { headers: { Accept: 'application/json' } }).catch(() => {})
758
771
  // Toggle all [wu-theme] buttons: dark ↔ light
759
- document.querySelectorAll('[wu-theme]').forEach((b) => {
760
- const v = b.getAttribute('wu-theme')
761
- if (v === 'dark') {
762
- b.setAttribute('wu-theme', 'light')
763
- b.textContent = 'β˜€οΈ'
764
- } else if (v === 'light') {
765
- b.setAttribute('wu-theme', 'dark')
766
- b.textContent = 'πŸŒ™'
767
- }
768
- })
772
+ syncThemeButtons(value)
769
773
  })
770
774
 
771
775
  // ═══════════════════════════════════════════════════════════════════
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "weifuwu",
3
3
  "type": "module",
4
- "version": "0.27.23",
4
+ "version": "0.27.25",
5
5
  "description": "Web-standard HTTP microframework for Node.js β€” (req, ctx) => Response",
6
6
  "exports": {
7
7
  ".": "./dist/index.js"