@xingwangzhe/stalux 1.24.0 → 1.24.1

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
@@ -80,9 +80,10 @@ bun run dev
80
80
  - 🔤 **Unicode-range font slicing** — 25 MB font → ~22 woff2 chunks, browser downloads only what matches the page
81
81
  - 🔍 **Full-text search** via Pagefind (auto-indexed on build)
82
82
  - 📡 **RSS & Atom feeds**
83
+ - 🗺️ **Sitemap** (bundled; `.md` source endpoints auto-filtered)
83
84
  - 🖼️ **PhotoSwipe** image lightbox
84
85
  - 📊 **Mermaid** diagrams and flowcharts
85
- - 📐 **Math formula rendering** (KaTeX / MathML)
86
+ - 📐 **Math formula rendering** (Temml → MathML)
86
87
  - 💬 **Waline** comment system
87
88
  - 🤖 **LLM discovery files** (llms.txt / llms-full.txt)
88
89
  - 🤝 **WebMCP tools** for AI agents (W3C draft, pure front-end)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.24.0",
3
+ "version": "1.24.1",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -140,7 +140,14 @@ const mdSourceUrl = exportMd
140
140
  }
141
141
  }
142
142
 
143
- let lightbox = null;
143
+ // 状态放 window:View Transitions 软导航会重执行模块脚本,
144
+ // 用全局标记避免 document 级监听器重复注册导致灯箱重复初始化。
145
+ const state = (window.__staluxPhotoswipe ||= {
146
+ lightbox: null,
147
+ initPromise: null,
148
+ lightboxInitialized: false,
149
+ handlerInstalled: false,
150
+ });
144
151
 
145
152
  async function initLightbox() {
146
153
  const [{ default: PhotoSwipeLightbox }, { default: PhotoSwipe }, { default: photoSwipeCss }] = await Promise.all([
@@ -159,45 +166,72 @@ const mdSourceUrl = exportMd
159
166
  }
160
167
 
161
168
  // 销毁旧实例(View Transition 导航后,旧 DOM 已移除,需安全销毁)
162
- if (lightbox) {
169
+ if (state.lightbox) {
163
170
  try {
164
- lightbox.destroy();
171
+ state.lightbox.destroy();
165
172
  } catch {
166
173
  /* ignore */
167
174
  }
168
- lightbox = null;
175
+ state.lightbox = null;
169
176
  }
170
177
 
171
178
  // 不阻塞文章首屏;已加载图片会立即写入尺寸,其余图片在后台补齐。
172
179
  void enrichPhotoSwipeData();
173
180
 
174
- lightbox = new PhotoSwipeLightbox({
181
+ state.lightbox = new PhotoSwipeLightbox({
175
182
  gallery: "[data-pagefind-body]",
176
183
  children: GALLERY_SELECTOR,
177
184
  pswpModule: PhotoSwipe,
178
185
  initialZoomLevel: "fill",
179
186
  });
180
- lightbox.init();
187
+ state.lightbox.init();
181
188
  }
182
189
 
183
- let initPromise = null;
184
190
  const ensureLightbox = () => {
185
- if (!initPromise) initPromise = initLightbox();
186
- return initPromise;
191
+ if (!state.initPromise) state.initPromise = initLightbox();
192
+ return state.initPromise;
187
193
  };
188
194
 
189
- // 仅在用户第一次点击图片时加载 PhotoSwipe、其 CSS 和图片尺寸数据,
190
- // 文章首屏不再为未使用的灯箱支付 JS/CSS 成本。
191
- document.addEventListener("click", (event) => {
195
+ function handleGalleryClick(event) {
192
196
  const target = event.target;
193
- if (target instanceof Element && target.closest(GALLERY_SELECTOR)) {
194
- void ensureLightbox();
195
- }
196
- }, { capture: true });
197
+ if (!(target instanceof Element && target.closest(GALLERY_SELECTOR))) return;
198
+
199
+ // 灯箱就绪后,后续点击交给 PhotoSwipeLightbox 自身的
200
+ // bubble 阶段处理(它负责 preventDefault + loadAndOpen)。
201
+ if (state.lightboxInitialized) return;
202
+
203
+ // 首次点击:立即阻止浏览器跳转到原始图片(否则会离开文章页),
204
+ // 异步初始化完成后直接打开被点击的图片。
205
+ event.preventDefault();
206
+ const anchor = target.closest(GALLERY_SELECTOR);
207
+ const clickedIndex = [...document.querySelectorAll(GALLERY_SELECTOR)].indexOf(anchor);
208
+ const initialPoint = { x: event.clientX, y: event.clientY };
209
+
210
+ void ensureLightbox()
211
+ .then(() => {
212
+ state.lightboxInitialized = true;
213
+ if (state.lightbox) {
214
+ state.lightbox.loadAndOpen(clickedIndex, undefined, initialPoint);
215
+ }
216
+ })
217
+ .catch((error) => {
218
+ console.error("[stalux photoswipe] 初始化失败", error);
219
+ });
220
+ }
197
221
 
198
- document.addEventListener("astro:page-load", () => {
199
- initPromise = null;
200
- });
222
+ if (!state.handlerInstalled) {
223
+ state.handlerInstalled = true;
224
+
225
+ // 仅在用户第一次点击图片时加载 PhotoSwipe、其 CSS 和图片尺寸数据,
226
+ // 文章首屏不再为未使用的灯箱支付 JS/CSS 成本。
227
+ document.addEventListener("click", handleGalleryClick, { capture: true });
228
+
229
+ // 软导航后旧 DOM 已移除:下次点击重新初始化(initLightbox 会销毁旧实例)。
230
+ document.addEventListener("astro:page-load", () => {
231
+ state.initPromise = null;
232
+ state.lightboxInitialized = false;
233
+ });
234
+ }
201
235
  </script>
202
236
  )
203
237
  }