daily-soup-widget 0.2.0 → 0.2.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/dist/embed.cjs.js CHANGED
@@ -155,9 +155,9 @@ var WIDGET_STYLES = `
155
155
  align-items: center;
156
156
  gap: 0.25rem;
157
157
  }
158
- .ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
158
+ .ds-btn:hover { color: var(--ds-accent); border-color: var(--ds-accent); }
159
159
  .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }
160
- .ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
160
+ .ds-btn.ds-toast { color: var(--ds-accent); border-color: var(--ds-accent); }
161
161
  .ds-powered { font-size: 0.75em; color: var(--ds-muted); }
162
162
  .ds-powered a { color: var(--ds-muted); text-decoration: none; }
163
163
  .ds-powered a:hover { text-decoration: underline; }
@@ -327,7 +327,11 @@ function mount(host, options = {}) {
327
327
  root,
328
328
  cardEl: card,
329
329
  unwatchTheme: () => {
330
- }
330
+ },
331
+ unwatchVisibility: () => {
332
+ },
333
+ schedule: null,
334
+ displayedDate: ""
331
335
  };
332
336
  if (themeConfig === "auto") {
333
337
  state.unwatchTheme = watchSystemTheme((t2) => {
@@ -350,18 +354,35 @@ function mount(host, options = {}) {
350
354
  renderError(state.cardEl, lang, resolvedTheme);
351
355
  return;
352
356
  }
357
+ state.schedule = schedule;
353
358
  const quote = pickQuote(schedule);
354
359
  if (!quote) {
355
360
  renderError(state.cardEl, lang, resolvedTheme);
356
361
  return;
357
362
  }
363
+ state.displayedDate = todayUtc8();
358
364
  renderQuote(state.cardEl, quote, lang, resolvedTheme);
359
365
  };
360
366
  load();
367
+ if (typeof document !== "undefined") {
368
+ const onVisibility = () => {
369
+ if (document.visibilityState !== "visible") return;
370
+ if (!state.schedule) return;
371
+ const today = todayUtc8();
372
+ if (today === state.displayedDate) return;
373
+ const quote = pickQuote(state.schedule);
374
+ if (!quote) return;
375
+ state.displayedDate = today;
376
+ renderQuote(state.cardEl, quote, lang, resolvedTheme);
377
+ };
378
+ document.addEventListener("visibilitychange", onVisibility);
379
+ state.unwatchVisibility = () => document.removeEventListener("visibilitychange", onVisibility);
380
+ }
361
381
  return {
362
382
  destroy() {
363
383
  cancelled = true;
364
384
  state.unwatchTheme();
385
+ state.unwatchVisibility();
365
386
  if (root === host) {
366
387
  host.textContent = "";
367
388
  } else if (host.shadowRoot) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/i18n.ts", "../src/theme.ts", "../src/share.ts", "../src/styles.ts", "../src/date.ts", "../src/widget.ts", "../src/component.tsx"],
4
- "sourcesContent": ["export { mount, mountAll } from './widget';\nexport { DailySoup } from './component';\nexport type {\n Lang,\n ThemeConfig,\n ResolvedTheme,\n Quote,\n Schedule,\n MountOptions,\n DailySoupProps,\n} from './types';\n", "import type { Lang } from './types';\n\ninterface UiStrings {\n copy: string;\n copied: string;\n share: string;\n source: string;\n poweredBy: string;\n attributedPopular: string;\n shareX: string;\n shareLine: string;\n loadFailed: string;\n}\n\nconst STRINGS: Record<Lang, UiStrings> = {\n zh: {\n copy: '\u8907\u88FD',\n copied: '\u5DF2\u8907\u88FD',\n share: '\u5206\u4EAB',\n source: '\u51FA\u8655',\n poweredBy: '\u7531 mshmwr \u63D0\u4F9B',\n attributedPopular: '\u50B3\u7D71\u6B78\u5C6C',\n shareX: '\u5206\u4EAB\u5230 X',\n shareLine: '\u5206\u4EAB\u5230 LINE',\n loadFailed: '\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557',\n },\n};\n\nexport function t(lang: Lang): UiStrings {\n return STRINGS[lang] ?? STRINGS.zh;\n}\n\nexport type { UiStrings };\n", "import type { ThemeConfig, ResolvedTheme, ThemeColors } from './types';\n\nfunction isThemeColors(config: ThemeConfig): config is ThemeColors {\n return typeof config === 'object' && config !== null;\n}\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\n if (isThemeColors(config)) return config.base ?? 'light';\n if (config === 'light' || config === 'dark') return config;\n if (typeof window === 'undefined' || !window.matchMedia) return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nexport function getThemeColors(config: ThemeConfig): ThemeColors | null {\n return isThemeColors(config) ? config : null;\n}\n\nexport function watchSystemTheme(cb: (theme: ResolvedTheme) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light');\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n}\n", "const SHARE_URL = 'https://daily-soup-widget.vercel.app';\n\nexport interface ShareContent {\n text: string;\n author: string;\n}\n\nexport async function copyToClipboard(content: ShareContent): Promise<boolean> {\n const payload = `${content.text} \u2014 ${content.author}`;\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(payload);\n return true;\n } catch {\n return false;\n }\n }\n return false;\n}\n\nexport function buildXShareUrl(content: ShareContent): string {\n const text = encodeURIComponent(`${content.text} \u2014 ${content.author}`);\n const url = encodeURIComponent(SHARE_URL);\n return `https://twitter.com/intent/tweet?text=${text}&url=${url}`;\n}\n\nexport function buildLineShareUrl(content: ShareContent): string {\n const url = encodeURIComponent(`${SHARE_URL} \u2014 ${content.text}`);\n return `https://social-plugins.line.me/lineit/share?url=${url}`;\n}\n", "export const WIDGET_STYLES = `\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n`;\n", "export function todayUtc8(now: Date = new Date()): string {\n const utc8 = new Date(now.getTime() + 8 * 60 * 60 * 1000);\n const yy = utc8.getUTCFullYear();\n const mm = String(utc8.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(utc8.getUTCDate()).padStart(2, '0');\n return `${yy}-${mm}-${dd}`;\n}\n", "import type { Lang, MountOptions, Quote, ResolvedTheme, Schedule, ThemeConfig } from './types';\nimport { t } from './i18n';\nimport { resolveTheme, watchSystemTheme, getThemeColors } from './theme';\nimport { buildLineShareUrl, buildXShareUrl, copyToClipboard } from './share';\nimport { WIDGET_STYLES } from './styles';\nimport { todayUtc8 } from './date';\n\nconst DEFAULT_SCHEDULE_BASE = 'https://daily-soup-widget.vercel.app';\n\nexport interface MountHandle {\n destroy(): void;\n}\n\ninterface WidgetState {\n lang: Lang;\n themeConfig: ThemeConfig;\n scheduleUrl: string;\n host: HTMLElement;\n root: ShadowRoot | HTMLElement;\n cardEl: HTMLElement;\n unwatchTheme: () => void;\n}\n\nfunction escape(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nfunction attachRoot(host: HTMLElement): ShadowRoot | HTMLElement {\n if (typeof host.attachShadow === 'function') {\n if (host.shadowRoot) return host.shadowRoot;\n return host.attachShadow({ mode: 'open' });\n }\n console.warn('[daily-soup] attachShadow unsupported, falling back to light DOM');\n return host;\n}\n\nfunction injectStyles(root: ShadowRoot | HTMLElement) {\n const style = document.createElement('style');\n style.textContent = WIDGET_STYLES;\n root.appendChild(style);\n}\n\nfunction buildSkeleton(theme: ResolvedTheme): HTMLElement {\n const card = document.createElement('div');\n card.className = `ds-card ds-${theme} ds-skeleton`;\n card.innerHTML = `\n <div class=\"ds-quote\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>\n <div class=\"ds-meta\"><span class=\"ds-author\">&nbsp;</span><span class=\"ds-source\">&nbsp;</span></div>\n `;\n return card;\n}\n\nfunction renderQuote(card: HTMLElement, quote: Quote, lang: Lang, theme: ResolvedTheme) {\n const s = t(lang);\n card.className = `ds-card ds-${theme}`;\n const sourceLabel = quote.sourceUrl\n ? `<a href=\"${escape(quote.sourceUrl)}\" target=\"_blank\" rel=\"noopener noreferrer\">${escape(quote.source)}</a>`\n : escape(quote.source);\n const flag = quote.attribution === 'popular-attribution'\n ? `<span class=\"ds-flag\">${escape(s.attributedPopular)}</span>`\n : '';\n card.innerHTML = `\n <p class=\"ds-quote\">${escape(quote.text)}</p>\n <div class=\"ds-meta\">\n <span class=\"ds-author\">\u2014 ${escape(quote.author)}${flag}</span>\n ${quote.source ? `<span class=\"ds-source\">${s.source}\uFF1A${sourceLabel}</span>` : ''}\n </div>\n <div class=\"ds-actions\">\n <div class=\"ds-share\">\n <button class=\"ds-btn\" data-action=\"copy\" type=\"button\" aria-label=\"${escape(s.copy)}\">\n <span aria-hidden=\"true\">\u29C9</span><span class=\"ds-share-label\">${escape(s.copy)}</span>\n </button>\n <a class=\"ds-btn\" data-action=\"x\" href=\"${escape(buildXShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareX)}\">\n <span aria-hidden=\"true\">\uD835\uDD4F</span><span class=\"ds-share-label\">X</span>\n </a>\n <a class=\"ds-btn\" data-action=\"line\" href=\"${escape(buildLineShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareLine)}\">\n <span aria-hidden=\"true\">L</span><span class=\"ds-share-label\">LINE</span>\n </a>\n </div>\n <span class=\"ds-powered\"><a href=\"https://personal-site-mocha-chi.vercel.app\" target=\"_blank\" rel=\"noopener noreferrer\">${s.poweredBy}</a></span>\n </div>\n `;\n\n const copyBtn = card.querySelector<HTMLButtonElement>('[data-action=\"copy\"]');\n if (copyBtn) {\n copyBtn.addEventListener('click', async () => {\n const ok = await copyToClipboard({ text: quote.text, author: quote.author });\n if (ok) {\n const label = copyBtn.querySelector('.ds-share-label');\n const originalLabel = label?.textContent ?? '';\n if (label) label.textContent = s.copied;\n copyBtn.classList.add('ds-toast');\n setTimeout(() => {\n if (label) label.textContent = originalLabel;\n copyBtn.classList.remove('ds-toast');\n }, 2000);\n }\n });\n }\n}\n\nfunction renderError(card: HTMLElement, lang: Lang, theme: ResolvedTheme) {\n card.className = `ds-card ds-${theme}`;\n const s = t(lang);\n card.innerHTML = `<p class=\"ds-error\">${escape(s.loadFailed)}</p>`;\n}\n\nasync function fetchSchedule(scheduleUrl: string, lang: Lang): Promise<Schedule | null> {\n const base = scheduleUrl.replace(/\\/$/, '');\n const url = `${base}/schedule-${lang}.json`;\n try {\n const init: RequestInit = base === '' ? { credentials: 'omit' } : { credentials: 'omit', mode: 'cors' };\n const res = await fetch(url, init);\n if (!res.ok) return null;\n return (await res.json()) as Schedule;\n } catch {\n return null;\n }\n}\n\nfunction pickQuote(schedule: Schedule): Quote | null {\n const today = todayUtc8();\n const id = schedule.entries[today];\n if (id && schedule.quotes[id]) return schedule.quotes[id];\n const fallbackId = Object.keys(schedule.quotes).sort()[0];\n if (fallbackId && schedule.quotes[fallbackId]) {\n console.warn('[daily-soup] today entry missing or stale, falling back to first quote');\n return schedule.quotes[fallbackId];\n }\n return null;\n}\n\nfunction applyThemeOverrides(card: HTMLElement, config: ThemeConfig, maxWidth?: string) {\n const colors = getThemeColors(config);\n if (colors) {\n if (colors.bg) card.style.setProperty('--ds-bg', colors.bg);\n if (colors.ink) card.style.setProperty('--ds-fg', colors.ink);\n if (colors.muted) card.style.setProperty('--ds-muted', colors.muted);\n if (colors.border) card.style.setProperty('--ds-border', colors.border);\n if (colors.accent) card.style.setProperty('--ds-accent', colors.accent);\n }\n if (maxWidth) card.style.setProperty('--ds-max-width', maxWidth);\n}\n\nexport function mount(host: HTMLElement, options: MountOptions = {}): MountHandle {\n const lang: Lang = options.lang ?? 'zh';\n const themeConfig: ThemeConfig = options.theme ?? 'auto';\n const scheduleUrl = options.scheduleUrl === undefined ? DEFAULT_SCHEDULE_BASE : options.scheduleUrl;\n const maxWidth = options.maxWidth;\n\n let resolvedTheme = resolveTheme(themeConfig);\n const root = attachRoot(host);\n if (root === host) {\n // light DOM fallback \u2014 clear any prior content\n host.textContent = '';\n } else {\n while ((root as ShadowRoot).firstChild) (root as ShadowRoot).removeChild((root as ShadowRoot).firstChild!);\n }\n injectStyles(root);\n\n const card = buildSkeleton(resolvedTheme);\n applyThemeOverrides(card, themeConfig, maxWidth);\n root.appendChild(card);\n\n const state: WidgetState = {\n lang,\n themeConfig,\n scheduleUrl,\n host,\n root,\n cardEl: card,\n unwatchTheme: () => {},\n };\n\n if (themeConfig === 'auto') {\n state.unwatchTheme = watchSystemTheme((t) => {\n resolvedTheme = t;\n state.cardEl.classList.remove('ds-light', 'ds-dark');\n state.cardEl.classList.add(`ds-${t}`);\n });\n }\n\n let cancelled = false;\n let retried = false;\n\n const load = async () => {\n const schedule = await fetchSchedule(scheduleUrl, lang);\n if (cancelled) return;\n if (!schedule) {\n if (!retried) {\n retried = true;\n setTimeout(load, 2000);\n return;\n }\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n const quote = pickQuote(schedule);\n if (!quote) {\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n load();\n\n return {\n destroy() {\n cancelled = true;\n state.unwatchTheme();\n if (root === host) {\n host.textContent = '';\n } else if (host.shadowRoot) {\n while (host.shadowRoot.firstChild) host.shadowRoot.removeChild(host.shadowRoot.firstChild);\n }\n },\n };\n}\n\nexport function mountAll(selector = '[data-daily-soup], #daily-soup'): MountHandle[] {\n if (typeof document === 'undefined') return [];\n const nodes = document.querySelectorAll<HTMLElement>(selector);\n const handles: MountHandle[] = [];\n nodes.forEach((node) => {\n const lang = (node.dataset.lang as Lang | undefined) ?? 'zh';\n const theme = (node.dataset.theme as 'auto' | 'light' | 'dark' | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n const maxWidth = node.dataset.maxWidth;\n handles.push(mount(node, { lang, theme, scheduleUrl, maxWidth }));\n });\n return handles;\n}\n", "import { useEffect, useRef } from 'react';\nimport { mount } from './widget';\nimport type { DailySoupProps } from './types';\n\nexport function DailySoup({ lang = 'zh', theme = 'auto', scheduleUrl, className, maxWidth }: DailySoupProps) {\n const hostRef = useRef<HTMLDivElement | null>(null);\n\n const themeKey = typeof theme === 'string' ? theme : JSON.stringify(theme);\n useEffect(() => {\n if (!hostRef.current) return;\n const handle = mount(hostRef.current, { lang, theme, scheduleUrl, maxWidth });\n return () => handle.destroy();\n }, [lang, themeKey, scheduleUrl, maxWidth]);\n\n return <div ref={hostRef} className={className} data-daily-soup-host=\"\" />;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export { mount, mountAll } from './widget';\nexport { DailySoup } from './component';\nexport type {\n Lang,\n ThemeConfig,\n ResolvedTheme,\n Quote,\n Schedule,\n MountOptions,\n DailySoupProps,\n} from './types';\n", "import type { Lang } from './types';\n\ninterface UiStrings {\n copy: string;\n copied: string;\n share: string;\n source: string;\n poweredBy: string;\n attributedPopular: string;\n shareX: string;\n shareLine: string;\n loadFailed: string;\n}\n\nconst STRINGS: Record<Lang, UiStrings> = {\n zh: {\n copy: '\u8907\u88FD',\n copied: '\u5DF2\u8907\u88FD',\n share: '\u5206\u4EAB',\n source: '\u51FA\u8655',\n poweredBy: '\u7531 mshmwr \u63D0\u4F9B',\n attributedPopular: '\u50B3\u7D71\u6B78\u5C6C',\n shareX: '\u5206\u4EAB\u5230 X',\n shareLine: '\u5206\u4EAB\u5230 LINE',\n loadFailed: '\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557',\n },\n};\n\nexport function t(lang: Lang): UiStrings {\n return STRINGS[lang] ?? STRINGS.zh;\n}\n\nexport type { UiStrings };\n", "import type { ThemeConfig, ResolvedTheme, ThemeColors } from './types';\n\nfunction isThemeColors(config: ThemeConfig): config is ThemeColors {\n return typeof config === 'object' && config !== null;\n}\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\n if (isThemeColors(config)) return config.base ?? 'light';\n if (config === 'light' || config === 'dark') return config;\n if (typeof window === 'undefined' || !window.matchMedia) return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nexport function getThemeColors(config: ThemeConfig): ThemeColors | null {\n return isThemeColors(config) ? config : null;\n}\n\nexport function watchSystemTheme(cb: (theme: ResolvedTheme) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light');\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n}\n", "const SHARE_URL = 'https://daily-soup-widget.vercel.app';\n\nexport interface ShareContent {\n text: string;\n author: string;\n}\n\nexport async function copyToClipboard(content: ShareContent): Promise<boolean> {\n const payload = `${content.text} \u2014 ${content.author}`;\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(payload);\n return true;\n } catch {\n return false;\n }\n }\n return false;\n}\n\nexport function buildXShareUrl(content: ShareContent): string {\n const text = encodeURIComponent(`${content.text} \u2014 ${content.author}`);\n const url = encodeURIComponent(SHARE_URL);\n return `https://twitter.com/intent/tweet?text=${text}&url=${url}`;\n}\n\nexport function buildLineShareUrl(content: ShareContent): string {\n const url = encodeURIComponent(`${SHARE_URL} \u2014 ${content.text}`);\n return `https://social-plugins.line.me/lineit/share?url=${url}`;\n}\n", "export const WIDGET_STYLES = `\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n`;\n", "export function todayUtc8(now: Date = new Date()): string {\n const utc8 = new Date(now.getTime() + 8 * 60 * 60 * 1000);\n const yy = utc8.getUTCFullYear();\n const mm = String(utc8.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(utc8.getUTCDate()).padStart(2, '0');\n return `${yy}-${mm}-${dd}`;\n}\n", "import type { Lang, MountOptions, Quote, ResolvedTheme, Schedule, ThemeConfig } from './types';\nimport { t } from './i18n';\nimport { resolveTheme, watchSystemTheme, getThemeColors } from './theme';\nimport { buildLineShareUrl, buildXShareUrl, copyToClipboard } from './share';\nimport { WIDGET_STYLES } from './styles';\nimport { todayUtc8 } from './date';\n\nconst DEFAULT_SCHEDULE_BASE = 'https://daily-soup-widget.vercel.app';\n\nexport interface MountHandle {\n destroy(): void;\n}\n\ninterface WidgetState {\n lang: Lang;\n themeConfig: ThemeConfig;\n scheduleUrl: string;\n host: HTMLElement;\n root: ShadowRoot | HTMLElement;\n cardEl: HTMLElement;\n unwatchTheme: () => void;\n unwatchVisibility: () => void;\n schedule: Schedule | null;\n displayedDate: string;\n}\n\nfunction escape(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nfunction attachRoot(host: HTMLElement): ShadowRoot | HTMLElement {\n if (typeof host.attachShadow === 'function') {\n if (host.shadowRoot) return host.shadowRoot;\n return host.attachShadow({ mode: 'open' });\n }\n console.warn('[daily-soup] attachShadow unsupported, falling back to light DOM');\n return host;\n}\n\nfunction injectStyles(root: ShadowRoot | HTMLElement) {\n const style = document.createElement('style');\n style.textContent = WIDGET_STYLES;\n root.appendChild(style);\n}\n\nfunction buildSkeleton(theme: ResolvedTheme): HTMLElement {\n const card = document.createElement('div');\n card.className = `ds-card ds-${theme} ds-skeleton`;\n card.innerHTML = `\n <div class=\"ds-quote\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>\n <div class=\"ds-meta\"><span class=\"ds-author\">&nbsp;</span><span class=\"ds-source\">&nbsp;</span></div>\n `;\n return card;\n}\n\nfunction renderQuote(card: HTMLElement, quote: Quote, lang: Lang, theme: ResolvedTheme) {\n const s = t(lang);\n card.className = `ds-card ds-${theme}`;\n const sourceLabel = quote.sourceUrl\n ? `<a href=\"${escape(quote.sourceUrl)}\" target=\"_blank\" rel=\"noopener noreferrer\">${escape(quote.source)}</a>`\n : escape(quote.source);\n const flag = quote.attribution === 'popular-attribution'\n ? `<span class=\"ds-flag\">${escape(s.attributedPopular)}</span>`\n : '';\n card.innerHTML = `\n <p class=\"ds-quote\">${escape(quote.text)}</p>\n <div class=\"ds-meta\">\n <span class=\"ds-author\">\u2014 ${escape(quote.author)}${flag}</span>\n ${quote.source ? `<span class=\"ds-source\">${s.source}\uFF1A${sourceLabel}</span>` : ''}\n </div>\n <div class=\"ds-actions\">\n <div class=\"ds-share\">\n <button class=\"ds-btn\" data-action=\"copy\" type=\"button\" aria-label=\"${escape(s.copy)}\">\n <span aria-hidden=\"true\">\u29C9</span><span class=\"ds-share-label\">${escape(s.copy)}</span>\n </button>\n <a class=\"ds-btn\" data-action=\"x\" href=\"${escape(buildXShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareX)}\">\n <span aria-hidden=\"true\">\uD835\uDD4F</span><span class=\"ds-share-label\">X</span>\n </a>\n <a class=\"ds-btn\" data-action=\"line\" href=\"${escape(buildLineShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareLine)}\">\n <span aria-hidden=\"true\">L</span><span class=\"ds-share-label\">LINE</span>\n </a>\n </div>\n <span class=\"ds-powered\"><a href=\"https://personal-site-mocha-chi.vercel.app\" target=\"_blank\" rel=\"noopener noreferrer\">${s.poweredBy}</a></span>\n </div>\n `;\n\n const copyBtn = card.querySelector<HTMLButtonElement>('[data-action=\"copy\"]');\n if (copyBtn) {\n copyBtn.addEventListener('click', async () => {\n const ok = await copyToClipboard({ text: quote.text, author: quote.author });\n if (ok) {\n const label = copyBtn.querySelector('.ds-share-label');\n const originalLabel = label?.textContent ?? '';\n if (label) label.textContent = s.copied;\n copyBtn.classList.add('ds-toast');\n setTimeout(() => {\n if (label) label.textContent = originalLabel;\n copyBtn.classList.remove('ds-toast');\n }, 2000);\n }\n });\n }\n}\n\nfunction renderError(card: HTMLElement, lang: Lang, theme: ResolvedTheme) {\n card.className = `ds-card ds-${theme}`;\n const s = t(lang);\n card.innerHTML = `<p class=\"ds-error\">${escape(s.loadFailed)}</p>`;\n}\n\nasync function fetchSchedule(scheduleUrl: string, lang: Lang): Promise<Schedule | null> {\n const base = scheduleUrl.replace(/\\/$/, '');\n const url = `${base}/schedule-${lang}.json`;\n try {\n const init: RequestInit = base === '' ? { credentials: 'omit' } : { credentials: 'omit', mode: 'cors' };\n const res = await fetch(url, init);\n if (!res.ok) return null;\n return (await res.json()) as Schedule;\n } catch {\n return null;\n }\n}\n\nfunction pickQuote(schedule: Schedule): Quote | null {\n const today = todayUtc8();\n const id = schedule.entries[today];\n if (id && schedule.quotes[id]) return schedule.quotes[id];\n const fallbackId = Object.keys(schedule.quotes).sort()[0];\n if (fallbackId && schedule.quotes[fallbackId]) {\n console.warn('[daily-soup] today entry missing or stale, falling back to first quote');\n return schedule.quotes[fallbackId];\n }\n return null;\n}\n\nfunction applyThemeOverrides(card: HTMLElement, config: ThemeConfig, maxWidth?: string) {\n const colors = getThemeColors(config);\n if (colors) {\n if (colors.bg) card.style.setProperty('--ds-bg', colors.bg);\n if (colors.ink) card.style.setProperty('--ds-fg', colors.ink);\n if (colors.muted) card.style.setProperty('--ds-muted', colors.muted);\n if (colors.border) card.style.setProperty('--ds-border', colors.border);\n if (colors.accent) card.style.setProperty('--ds-accent', colors.accent);\n }\n if (maxWidth) card.style.setProperty('--ds-max-width', maxWidth);\n}\n\nexport function mount(host: HTMLElement, options: MountOptions = {}): MountHandle {\n const lang: Lang = options.lang ?? 'zh';\n const themeConfig: ThemeConfig = options.theme ?? 'auto';\n const scheduleUrl = options.scheduleUrl === undefined ? DEFAULT_SCHEDULE_BASE : options.scheduleUrl;\n const maxWidth = options.maxWidth;\n\n let resolvedTheme = resolveTheme(themeConfig);\n const root = attachRoot(host);\n if (root === host) {\n // light DOM fallback \u2014 clear any prior content\n host.textContent = '';\n } else {\n while ((root as ShadowRoot).firstChild) (root as ShadowRoot).removeChild((root as ShadowRoot).firstChild!);\n }\n injectStyles(root);\n\n const card = buildSkeleton(resolvedTheme);\n applyThemeOverrides(card, themeConfig, maxWidth);\n root.appendChild(card);\n\n const state: WidgetState = {\n lang,\n themeConfig,\n scheduleUrl,\n host,\n root,\n cardEl: card,\n unwatchTheme: () => {},\n unwatchVisibility: () => {},\n schedule: null,\n displayedDate: '',\n };\n\n if (themeConfig === 'auto') {\n state.unwatchTheme = watchSystemTheme((t) => {\n resolvedTheme = t;\n state.cardEl.classList.remove('ds-light', 'ds-dark');\n state.cardEl.classList.add(`ds-${t}`);\n });\n }\n\n let cancelled = false;\n let retried = false;\n\n const load = async () => {\n const schedule = await fetchSchedule(scheduleUrl, lang);\n if (cancelled) return;\n if (!schedule) {\n if (!retried) {\n retried = true;\n setTimeout(load, 2000);\n return;\n }\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n state.schedule = schedule;\n const quote = pickQuote(schedule);\n if (!quote) {\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n state.displayedDate = todayUtc8();\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n load();\n\n if (typeof document !== 'undefined') {\n const onVisibility = () => {\n if (document.visibilityState !== 'visible') return;\n if (!state.schedule) return;\n const today = todayUtc8();\n if (today === state.displayedDate) return;\n const quote = pickQuote(state.schedule);\n if (!quote) return;\n state.displayedDate = today;\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n document.addEventListener('visibilitychange', onVisibility);\n state.unwatchVisibility = () => document.removeEventListener('visibilitychange', onVisibility);\n }\n\n return {\n destroy() {\n cancelled = true;\n state.unwatchTheme();\n state.unwatchVisibility();\n if (root === host) {\n host.textContent = '';\n } else if (host.shadowRoot) {\n while (host.shadowRoot.firstChild) host.shadowRoot.removeChild(host.shadowRoot.firstChild);\n }\n },\n };\n}\n\nexport function mountAll(selector = '[data-daily-soup], #daily-soup'): MountHandle[] {\n if (typeof document === 'undefined') return [];\n const nodes = document.querySelectorAll<HTMLElement>(selector);\n const handles: MountHandle[] = [];\n nodes.forEach((node) => {\n const lang = (node.dataset.lang as Lang | undefined) ?? 'zh';\n const theme = (node.dataset.theme as 'auto' | 'light' | 'dark' | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n const maxWidth = node.dataset.maxWidth;\n handles.push(mount(node, { lang, theme, scheduleUrl, maxWidth }));\n });\n return handles;\n}\n", "import { useEffect, useRef } from 'react';\nimport { mount } from './widget';\nimport type { DailySoupProps } from './types';\n\nexport function DailySoup({ lang = 'zh', theme = 'auto', scheduleUrl, className, maxWidth }: DailySoupProps) {\n const hostRef = useRef<HTMLDivElement | null>(null);\n\n const themeKey = typeof theme === 'string' ? theme : JSON.stringify(theme);\n useEffect(() => {\n if (!hostRef.current) return;\n const handle = mount(hostRef.current, { lang, theme, scheduleUrl, maxWidth });\n return () => handle.destroy();\n }, [lang, themeKey, scheduleUrl, maxWidth]);\n\n return <div ref={hostRef} className={className} data-daily-soup-host=\"\" />;\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["t"]
7
7
  }
package/dist/embed.esm.js CHANGED
@@ -127,9 +127,9 @@ var WIDGET_STYLES = `
127
127
  align-items: center;
128
128
  gap: 0.25rem;
129
129
  }
130
- .ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
130
+ .ds-btn:hover { color: var(--ds-accent); border-color: var(--ds-accent); }
131
131
  .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }
132
- .ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
132
+ .ds-btn.ds-toast { color: var(--ds-accent); border-color: var(--ds-accent); }
133
133
  .ds-powered { font-size: 0.75em; color: var(--ds-muted); }
134
134
  .ds-powered a { color: var(--ds-muted); text-decoration: none; }
135
135
  .ds-powered a:hover { text-decoration: underline; }
@@ -299,7 +299,11 @@ function mount(host, options = {}) {
299
299
  root,
300
300
  cardEl: card,
301
301
  unwatchTheme: () => {
302
- }
302
+ },
303
+ unwatchVisibility: () => {
304
+ },
305
+ schedule: null,
306
+ displayedDate: ""
303
307
  };
304
308
  if (themeConfig === "auto") {
305
309
  state.unwatchTheme = watchSystemTheme((t2) => {
@@ -322,18 +326,35 @@ function mount(host, options = {}) {
322
326
  renderError(state.cardEl, lang, resolvedTheme);
323
327
  return;
324
328
  }
329
+ state.schedule = schedule;
325
330
  const quote = pickQuote(schedule);
326
331
  if (!quote) {
327
332
  renderError(state.cardEl, lang, resolvedTheme);
328
333
  return;
329
334
  }
335
+ state.displayedDate = todayUtc8();
330
336
  renderQuote(state.cardEl, quote, lang, resolvedTheme);
331
337
  };
332
338
  load();
339
+ if (typeof document !== "undefined") {
340
+ const onVisibility = () => {
341
+ if (document.visibilityState !== "visible") return;
342
+ if (!state.schedule) return;
343
+ const today = todayUtc8();
344
+ if (today === state.displayedDate) return;
345
+ const quote = pickQuote(state.schedule);
346
+ if (!quote) return;
347
+ state.displayedDate = today;
348
+ renderQuote(state.cardEl, quote, lang, resolvedTheme);
349
+ };
350
+ document.addEventListener("visibilitychange", onVisibility);
351
+ state.unwatchVisibility = () => document.removeEventListener("visibilitychange", onVisibility);
352
+ }
333
353
  return {
334
354
  destroy() {
335
355
  cancelled = true;
336
356
  state.unwatchTheme();
357
+ state.unwatchVisibility();
337
358
  if (root === host) {
338
359
  host.textContent = "";
339
360
  } else if (host.shadowRoot) {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/i18n.ts", "../src/theme.ts", "../src/share.ts", "../src/styles.ts", "../src/date.ts", "../src/widget.ts", "../src/component.tsx"],
4
- "sourcesContent": ["import type { Lang } from './types';\n\ninterface UiStrings {\n copy: string;\n copied: string;\n share: string;\n source: string;\n poweredBy: string;\n attributedPopular: string;\n shareX: string;\n shareLine: string;\n loadFailed: string;\n}\n\nconst STRINGS: Record<Lang, UiStrings> = {\n zh: {\n copy: '\u8907\u88FD',\n copied: '\u5DF2\u8907\u88FD',\n share: '\u5206\u4EAB',\n source: '\u51FA\u8655',\n poweredBy: '\u7531 mshmwr \u63D0\u4F9B',\n attributedPopular: '\u50B3\u7D71\u6B78\u5C6C',\n shareX: '\u5206\u4EAB\u5230 X',\n shareLine: '\u5206\u4EAB\u5230 LINE',\n loadFailed: '\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557',\n },\n};\n\nexport function t(lang: Lang): UiStrings {\n return STRINGS[lang] ?? STRINGS.zh;\n}\n\nexport type { UiStrings };\n", "import type { ThemeConfig, ResolvedTheme, ThemeColors } from './types';\n\nfunction isThemeColors(config: ThemeConfig): config is ThemeColors {\n return typeof config === 'object' && config !== null;\n}\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\n if (isThemeColors(config)) return config.base ?? 'light';\n if (config === 'light' || config === 'dark') return config;\n if (typeof window === 'undefined' || !window.matchMedia) return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nexport function getThemeColors(config: ThemeConfig): ThemeColors | null {\n return isThemeColors(config) ? config : null;\n}\n\nexport function watchSystemTheme(cb: (theme: ResolvedTheme) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light');\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n}\n", "const SHARE_URL = 'https://daily-soup-widget.vercel.app';\n\nexport interface ShareContent {\n text: string;\n author: string;\n}\n\nexport async function copyToClipboard(content: ShareContent): Promise<boolean> {\n const payload = `${content.text} \u2014 ${content.author}`;\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(payload);\n return true;\n } catch {\n return false;\n }\n }\n return false;\n}\n\nexport function buildXShareUrl(content: ShareContent): string {\n const text = encodeURIComponent(`${content.text} \u2014 ${content.author}`);\n const url = encodeURIComponent(SHARE_URL);\n return `https://twitter.com/intent/tweet?text=${text}&url=${url}`;\n}\n\nexport function buildLineShareUrl(content: ShareContent): string {\n const url = encodeURIComponent(`${SHARE_URL} \u2014 ${content.text}`);\n return `https://social-plugins.line.me/lineit/share?url=${url}`;\n}\n", "export const WIDGET_STYLES = `\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n`;\n", "export function todayUtc8(now: Date = new Date()): string {\n const utc8 = new Date(now.getTime() + 8 * 60 * 60 * 1000);\n const yy = utc8.getUTCFullYear();\n const mm = String(utc8.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(utc8.getUTCDate()).padStart(2, '0');\n return `${yy}-${mm}-${dd}`;\n}\n", "import type { Lang, MountOptions, Quote, ResolvedTheme, Schedule, ThemeConfig } from './types';\nimport { t } from './i18n';\nimport { resolveTheme, watchSystemTheme, getThemeColors } from './theme';\nimport { buildLineShareUrl, buildXShareUrl, copyToClipboard } from './share';\nimport { WIDGET_STYLES } from './styles';\nimport { todayUtc8 } from './date';\n\nconst DEFAULT_SCHEDULE_BASE = 'https://daily-soup-widget.vercel.app';\n\nexport interface MountHandle {\n destroy(): void;\n}\n\ninterface WidgetState {\n lang: Lang;\n themeConfig: ThemeConfig;\n scheduleUrl: string;\n host: HTMLElement;\n root: ShadowRoot | HTMLElement;\n cardEl: HTMLElement;\n unwatchTheme: () => void;\n}\n\nfunction escape(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nfunction attachRoot(host: HTMLElement): ShadowRoot | HTMLElement {\n if (typeof host.attachShadow === 'function') {\n if (host.shadowRoot) return host.shadowRoot;\n return host.attachShadow({ mode: 'open' });\n }\n console.warn('[daily-soup] attachShadow unsupported, falling back to light DOM');\n return host;\n}\n\nfunction injectStyles(root: ShadowRoot | HTMLElement) {\n const style = document.createElement('style');\n style.textContent = WIDGET_STYLES;\n root.appendChild(style);\n}\n\nfunction buildSkeleton(theme: ResolvedTheme): HTMLElement {\n const card = document.createElement('div');\n card.className = `ds-card ds-${theme} ds-skeleton`;\n card.innerHTML = `\n <div class=\"ds-quote\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>\n <div class=\"ds-meta\"><span class=\"ds-author\">&nbsp;</span><span class=\"ds-source\">&nbsp;</span></div>\n `;\n return card;\n}\n\nfunction renderQuote(card: HTMLElement, quote: Quote, lang: Lang, theme: ResolvedTheme) {\n const s = t(lang);\n card.className = `ds-card ds-${theme}`;\n const sourceLabel = quote.sourceUrl\n ? `<a href=\"${escape(quote.sourceUrl)}\" target=\"_blank\" rel=\"noopener noreferrer\">${escape(quote.source)}</a>`\n : escape(quote.source);\n const flag = quote.attribution === 'popular-attribution'\n ? `<span class=\"ds-flag\">${escape(s.attributedPopular)}</span>`\n : '';\n card.innerHTML = `\n <p class=\"ds-quote\">${escape(quote.text)}</p>\n <div class=\"ds-meta\">\n <span class=\"ds-author\">\u2014 ${escape(quote.author)}${flag}</span>\n ${quote.source ? `<span class=\"ds-source\">${s.source}\uFF1A${sourceLabel}</span>` : ''}\n </div>\n <div class=\"ds-actions\">\n <div class=\"ds-share\">\n <button class=\"ds-btn\" data-action=\"copy\" type=\"button\" aria-label=\"${escape(s.copy)}\">\n <span aria-hidden=\"true\">\u29C9</span><span class=\"ds-share-label\">${escape(s.copy)}</span>\n </button>\n <a class=\"ds-btn\" data-action=\"x\" href=\"${escape(buildXShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareX)}\">\n <span aria-hidden=\"true\">\uD835\uDD4F</span><span class=\"ds-share-label\">X</span>\n </a>\n <a class=\"ds-btn\" data-action=\"line\" href=\"${escape(buildLineShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareLine)}\">\n <span aria-hidden=\"true\">L</span><span class=\"ds-share-label\">LINE</span>\n </a>\n </div>\n <span class=\"ds-powered\"><a href=\"https://personal-site-mocha-chi.vercel.app\" target=\"_blank\" rel=\"noopener noreferrer\">${s.poweredBy}</a></span>\n </div>\n `;\n\n const copyBtn = card.querySelector<HTMLButtonElement>('[data-action=\"copy\"]');\n if (copyBtn) {\n copyBtn.addEventListener('click', async () => {\n const ok = await copyToClipboard({ text: quote.text, author: quote.author });\n if (ok) {\n const label = copyBtn.querySelector('.ds-share-label');\n const originalLabel = label?.textContent ?? '';\n if (label) label.textContent = s.copied;\n copyBtn.classList.add('ds-toast');\n setTimeout(() => {\n if (label) label.textContent = originalLabel;\n copyBtn.classList.remove('ds-toast');\n }, 2000);\n }\n });\n }\n}\n\nfunction renderError(card: HTMLElement, lang: Lang, theme: ResolvedTheme) {\n card.className = `ds-card ds-${theme}`;\n const s = t(lang);\n card.innerHTML = `<p class=\"ds-error\">${escape(s.loadFailed)}</p>`;\n}\n\nasync function fetchSchedule(scheduleUrl: string, lang: Lang): Promise<Schedule | null> {\n const base = scheduleUrl.replace(/\\/$/, '');\n const url = `${base}/schedule-${lang}.json`;\n try {\n const init: RequestInit = base === '' ? { credentials: 'omit' } : { credentials: 'omit', mode: 'cors' };\n const res = await fetch(url, init);\n if (!res.ok) return null;\n return (await res.json()) as Schedule;\n } catch {\n return null;\n }\n}\n\nfunction pickQuote(schedule: Schedule): Quote | null {\n const today = todayUtc8();\n const id = schedule.entries[today];\n if (id && schedule.quotes[id]) return schedule.quotes[id];\n const fallbackId = Object.keys(schedule.quotes).sort()[0];\n if (fallbackId && schedule.quotes[fallbackId]) {\n console.warn('[daily-soup] today entry missing or stale, falling back to first quote');\n return schedule.quotes[fallbackId];\n }\n return null;\n}\n\nfunction applyThemeOverrides(card: HTMLElement, config: ThemeConfig, maxWidth?: string) {\n const colors = getThemeColors(config);\n if (colors) {\n if (colors.bg) card.style.setProperty('--ds-bg', colors.bg);\n if (colors.ink) card.style.setProperty('--ds-fg', colors.ink);\n if (colors.muted) card.style.setProperty('--ds-muted', colors.muted);\n if (colors.border) card.style.setProperty('--ds-border', colors.border);\n if (colors.accent) card.style.setProperty('--ds-accent', colors.accent);\n }\n if (maxWidth) card.style.setProperty('--ds-max-width', maxWidth);\n}\n\nexport function mount(host: HTMLElement, options: MountOptions = {}): MountHandle {\n const lang: Lang = options.lang ?? 'zh';\n const themeConfig: ThemeConfig = options.theme ?? 'auto';\n const scheduleUrl = options.scheduleUrl === undefined ? DEFAULT_SCHEDULE_BASE : options.scheduleUrl;\n const maxWidth = options.maxWidth;\n\n let resolvedTheme = resolveTheme(themeConfig);\n const root = attachRoot(host);\n if (root === host) {\n // light DOM fallback \u2014 clear any prior content\n host.textContent = '';\n } else {\n while ((root as ShadowRoot).firstChild) (root as ShadowRoot).removeChild((root as ShadowRoot).firstChild!);\n }\n injectStyles(root);\n\n const card = buildSkeleton(resolvedTheme);\n applyThemeOverrides(card, themeConfig, maxWidth);\n root.appendChild(card);\n\n const state: WidgetState = {\n lang,\n themeConfig,\n scheduleUrl,\n host,\n root,\n cardEl: card,\n unwatchTheme: () => {},\n };\n\n if (themeConfig === 'auto') {\n state.unwatchTheme = watchSystemTheme((t) => {\n resolvedTheme = t;\n state.cardEl.classList.remove('ds-light', 'ds-dark');\n state.cardEl.classList.add(`ds-${t}`);\n });\n }\n\n let cancelled = false;\n let retried = false;\n\n const load = async () => {\n const schedule = await fetchSchedule(scheduleUrl, lang);\n if (cancelled) return;\n if (!schedule) {\n if (!retried) {\n retried = true;\n setTimeout(load, 2000);\n return;\n }\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n const quote = pickQuote(schedule);\n if (!quote) {\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n load();\n\n return {\n destroy() {\n cancelled = true;\n state.unwatchTheme();\n if (root === host) {\n host.textContent = '';\n } else if (host.shadowRoot) {\n while (host.shadowRoot.firstChild) host.shadowRoot.removeChild(host.shadowRoot.firstChild);\n }\n },\n };\n}\n\nexport function mountAll(selector = '[data-daily-soup], #daily-soup'): MountHandle[] {\n if (typeof document === 'undefined') return [];\n const nodes = document.querySelectorAll<HTMLElement>(selector);\n const handles: MountHandle[] = [];\n nodes.forEach((node) => {\n const lang = (node.dataset.lang as Lang | undefined) ?? 'zh';\n const theme = (node.dataset.theme as 'auto' | 'light' | 'dark' | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n const maxWidth = node.dataset.maxWidth;\n handles.push(mount(node, { lang, theme, scheduleUrl, maxWidth }));\n });\n return handles;\n}\n", "import { useEffect, useRef } from 'react';\nimport { mount } from './widget';\nimport type { DailySoupProps } from './types';\n\nexport function DailySoup({ lang = 'zh', theme = 'auto', scheduleUrl, className, maxWidth }: DailySoupProps) {\n const hostRef = useRef<HTMLDivElement | null>(null);\n\n const themeKey = typeof theme === 'string' ? theme : JSON.stringify(theme);\n useEffect(() => {\n if (!hostRef.current) return;\n const handle = mount(hostRef.current, { lang, theme, scheduleUrl, maxWidth });\n return () => handle.destroy();\n }, [lang, themeKey, scheduleUrl, maxWidth]);\n\n return <div ref={hostRef} className={className} data-daily-soup-host=\"\" />;\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { Lang } from './types';\n\ninterface UiStrings {\n copy: string;\n copied: string;\n share: string;\n source: string;\n poweredBy: string;\n attributedPopular: string;\n shareX: string;\n shareLine: string;\n loadFailed: string;\n}\n\nconst STRINGS: Record<Lang, UiStrings> = {\n zh: {\n copy: '\u8907\u88FD',\n copied: '\u5DF2\u8907\u88FD',\n share: '\u5206\u4EAB',\n source: '\u51FA\u8655',\n poweredBy: '\u7531 mshmwr \u63D0\u4F9B',\n attributedPopular: '\u50B3\u7D71\u6B78\u5C6C',\n shareX: '\u5206\u4EAB\u5230 X',\n shareLine: '\u5206\u4EAB\u5230 LINE',\n loadFailed: '\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557',\n },\n};\n\nexport function t(lang: Lang): UiStrings {\n return STRINGS[lang] ?? STRINGS.zh;\n}\n\nexport type { UiStrings };\n", "import type { ThemeConfig, ResolvedTheme, ThemeColors } from './types';\n\nfunction isThemeColors(config: ThemeConfig): config is ThemeColors {\n return typeof config === 'object' && config !== null;\n}\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\n if (isThemeColors(config)) return config.base ?? 'light';\n if (config === 'light' || config === 'dark') return config;\n if (typeof window === 'undefined' || !window.matchMedia) return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nexport function getThemeColors(config: ThemeConfig): ThemeColors | null {\n return isThemeColors(config) ? config : null;\n}\n\nexport function watchSystemTheme(cb: (theme: ResolvedTheme) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light');\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n}\n", "const SHARE_URL = 'https://daily-soup-widget.vercel.app';\n\nexport interface ShareContent {\n text: string;\n author: string;\n}\n\nexport async function copyToClipboard(content: ShareContent): Promise<boolean> {\n const payload = `${content.text} \u2014 ${content.author}`;\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(payload);\n return true;\n } catch {\n return false;\n }\n }\n return false;\n}\n\nexport function buildXShareUrl(content: ShareContent): string {\n const text = encodeURIComponent(`${content.text} \u2014 ${content.author}`);\n const url = encodeURIComponent(SHARE_URL);\n return `https://twitter.com/intent/tweet?text=${text}&url=${url}`;\n}\n\nexport function buildLineShareUrl(content: ShareContent): string {\n const url = encodeURIComponent(`${SHARE_URL} \u2014 ${content.text}`);\n return `https://social-plugins.line.me/lineit/share?url=${url}`;\n}\n", "export const WIDGET_STYLES = `\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n`;\n", "export function todayUtc8(now: Date = new Date()): string {\n const utc8 = new Date(now.getTime() + 8 * 60 * 60 * 1000);\n const yy = utc8.getUTCFullYear();\n const mm = String(utc8.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(utc8.getUTCDate()).padStart(2, '0');\n return `${yy}-${mm}-${dd}`;\n}\n", "import type { Lang, MountOptions, Quote, ResolvedTheme, Schedule, ThemeConfig } from './types';\nimport { t } from './i18n';\nimport { resolveTheme, watchSystemTheme, getThemeColors } from './theme';\nimport { buildLineShareUrl, buildXShareUrl, copyToClipboard } from './share';\nimport { WIDGET_STYLES } from './styles';\nimport { todayUtc8 } from './date';\n\nconst DEFAULT_SCHEDULE_BASE = 'https://daily-soup-widget.vercel.app';\n\nexport interface MountHandle {\n destroy(): void;\n}\n\ninterface WidgetState {\n lang: Lang;\n themeConfig: ThemeConfig;\n scheduleUrl: string;\n host: HTMLElement;\n root: ShadowRoot | HTMLElement;\n cardEl: HTMLElement;\n unwatchTheme: () => void;\n unwatchVisibility: () => void;\n schedule: Schedule | null;\n displayedDate: string;\n}\n\nfunction escape(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nfunction attachRoot(host: HTMLElement): ShadowRoot | HTMLElement {\n if (typeof host.attachShadow === 'function') {\n if (host.shadowRoot) return host.shadowRoot;\n return host.attachShadow({ mode: 'open' });\n }\n console.warn('[daily-soup] attachShadow unsupported, falling back to light DOM');\n return host;\n}\n\nfunction injectStyles(root: ShadowRoot | HTMLElement) {\n const style = document.createElement('style');\n style.textContent = WIDGET_STYLES;\n root.appendChild(style);\n}\n\nfunction buildSkeleton(theme: ResolvedTheme): HTMLElement {\n const card = document.createElement('div');\n card.className = `ds-card ds-${theme} ds-skeleton`;\n card.innerHTML = `\n <div class=\"ds-quote\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>\n <div class=\"ds-meta\"><span class=\"ds-author\">&nbsp;</span><span class=\"ds-source\">&nbsp;</span></div>\n `;\n return card;\n}\n\nfunction renderQuote(card: HTMLElement, quote: Quote, lang: Lang, theme: ResolvedTheme) {\n const s = t(lang);\n card.className = `ds-card ds-${theme}`;\n const sourceLabel = quote.sourceUrl\n ? `<a href=\"${escape(quote.sourceUrl)}\" target=\"_blank\" rel=\"noopener noreferrer\">${escape(quote.source)}</a>`\n : escape(quote.source);\n const flag = quote.attribution === 'popular-attribution'\n ? `<span class=\"ds-flag\">${escape(s.attributedPopular)}</span>`\n : '';\n card.innerHTML = `\n <p class=\"ds-quote\">${escape(quote.text)}</p>\n <div class=\"ds-meta\">\n <span class=\"ds-author\">\u2014 ${escape(quote.author)}${flag}</span>\n ${quote.source ? `<span class=\"ds-source\">${s.source}\uFF1A${sourceLabel}</span>` : ''}\n </div>\n <div class=\"ds-actions\">\n <div class=\"ds-share\">\n <button class=\"ds-btn\" data-action=\"copy\" type=\"button\" aria-label=\"${escape(s.copy)}\">\n <span aria-hidden=\"true\">\u29C9</span><span class=\"ds-share-label\">${escape(s.copy)}</span>\n </button>\n <a class=\"ds-btn\" data-action=\"x\" href=\"${escape(buildXShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareX)}\">\n <span aria-hidden=\"true\">\uD835\uDD4F</span><span class=\"ds-share-label\">X</span>\n </a>\n <a class=\"ds-btn\" data-action=\"line\" href=\"${escape(buildLineShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareLine)}\">\n <span aria-hidden=\"true\">L</span><span class=\"ds-share-label\">LINE</span>\n </a>\n </div>\n <span class=\"ds-powered\"><a href=\"https://personal-site-mocha-chi.vercel.app\" target=\"_blank\" rel=\"noopener noreferrer\">${s.poweredBy}</a></span>\n </div>\n `;\n\n const copyBtn = card.querySelector<HTMLButtonElement>('[data-action=\"copy\"]');\n if (copyBtn) {\n copyBtn.addEventListener('click', async () => {\n const ok = await copyToClipboard({ text: quote.text, author: quote.author });\n if (ok) {\n const label = copyBtn.querySelector('.ds-share-label');\n const originalLabel = label?.textContent ?? '';\n if (label) label.textContent = s.copied;\n copyBtn.classList.add('ds-toast');\n setTimeout(() => {\n if (label) label.textContent = originalLabel;\n copyBtn.classList.remove('ds-toast');\n }, 2000);\n }\n });\n }\n}\n\nfunction renderError(card: HTMLElement, lang: Lang, theme: ResolvedTheme) {\n card.className = `ds-card ds-${theme}`;\n const s = t(lang);\n card.innerHTML = `<p class=\"ds-error\">${escape(s.loadFailed)}</p>`;\n}\n\nasync function fetchSchedule(scheduleUrl: string, lang: Lang): Promise<Schedule | null> {\n const base = scheduleUrl.replace(/\\/$/, '');\n const url = `${base}/schedule-${lang}.json`;\n try {\n const init: RequestInit = base === '' ? { credentials: 'omit' } : { credentials: 'omit', mode: 'cors' };\n const res = await fetch(url, init);\n if (!res.ok) return null;\n return (await res.json()) as Schedule;\n } catch {\n return null;\n }\n}\n\nfunction pickQuote(schedule: Schedule): Quote | null {\n const today = todayUtc8();\n const id = schedule.entries[today];\n if (id && schedule.quotes[id]) return schedule.quotes[id];\n const fallbackId = Object.keys(schedule.quotes).sort()[0];\n if (fallbackId && schedule.quotes[fallbackId]) {\n console.warn('[daily-soup] today entry missing or stale, falling back to first quote');\n return schedule.quotes[fallbackId];\n }\n return null;\n}\n\nfunction applyThemeOverrides(card: HTMLElement, config: ThemeConfig, maxWidth?: string) {\n const colors = getThemeColors(config);\n if (colors) {\n if (colors.bg) card.style.setProperty('--ds-bg', colors.bg);\n if (colors.ink) card.style.setProperty('--ds-fg', colors.ink);\n if (colors.muted) card.style.setProperty('--ds-muted', colors.muted);\n if (colors.border) card.style.setProperty('--ds-border', colors.border);\n if (colors.accent) card.style.setProperty('--ds-accent', colors.accent);\n }\n if (maxWidth) card.style.setProperty('--ds-max-width', maxWidth);\n}\n\nexport function mount(host: HTMLElement, options: MountOptions = {}): MountHandle {\n const lang: Lang = options.lang ?? 'zh';\n const themeConfig: ThemeConfig = options.theme ?? 'auto';\n const scheduleUrl = options.scheduleUrl === undefined ? DEFAULT_SCHEDULE_BASE : options.scheduleUrl;\n const maxWidth = options.maxWidth;\n\n let resolvedTheme = resolveTheme(themeConfig);\n const root = attachRoot(host);\n if (root === host) {\n // light DOM fallback \u2014 clear any prior content\n host.textContent = '';\n } else {\n while ((root as ShadowRoot).firstChild) (root as ShadowRoot).removeChild((root as ShadowRoot).firstChild!);\n }\n injectStyles(root);\n\n const card = buildSkeleton(resolvedTheme);\n applyThemeOverrides(card, themeConfig, maxWidth);\n root.appendChild(card);\n\n const state: WidgetState = {\n lang,\n themeConfig,\n scheduleUrl,\n host,\n root,\n cardEl: card,\n unwatchTheme: () => {},\n unwatchVisibility: () => {},\n schedule: null,\n displayedDate: '',\n };\n\n if (themeConfig === 'auto') {\n state.unwatchTheme = watchSystemTheme((t) => {\n resolvedTheme = t;\n state.cardEl.classList.remove('ds-light', 'ds-dark');\n state.cardEl.classList.add(`ds-${t}`);\n });\n }\n\n let cancelled = false;\n let retried = false;\n\n const load = async () => {\n const schedule = await fetchSchedule(scheduleUrl, lang);\n if (cancelled) return;\n if (!schedule) {\n if (!retried) {\n retried = true;\n setTimeout(load, 2000);\n return;\n }\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n state.schedule = schedule;\n const quote = pickQuote(schedule);\n if (!quote) {\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n state.displayedDate = todayUtc8();\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n load();\n\n if (typeof document !== 'undefined') {\n const onVisibility = () => {\n if (document.visibilityState !== 'visible') return;\n if (!state.schedule) return;\n const today = todayUtc8();\n if (today === state.displayedDate) return;\n const quote = pickQuote(state.schedule);\n if (!quote) return;\n state.displayedDate = today;\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n document.addEventListener('visibilitychange', onVisibility);\n state.unwatchVisibility = () => document.removeEventListener('visibilitychange', onVisibility);\n }\n\n return {\n destroy() {\n cancelled = true;\n state.unwatchTheme();\n state.unwatchVisibility();\n if (root === host) {\n host.textContent = '';\n } else if (host.shadowRoot) {\n while (host.shadowRoot.firstChild) host.shadowRoot.removeChild(host.shadowRoot.firstChild);\n }\n },\n };\n}\n\nexport function mountAll(selector = '[data-daily-soup], #daily-soup'): MountHandle[] {\n if (typeof document === 'undefined') return [];\n const nodes = document.querySelectorAll<HTMLElement>(selector);\n const handles: MountHandle[] = [];\n nodes.forEach((node) => {\n const lang = (node.dataset.lang as Lang | undefined) ?? 'zh';\n const theme = (node.dataset.theme as 'auto' | 'light' | 'dark' | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n const maxWidth = node.dataset.maxWidth;\n handles.push(mount(node, { lang, theme, scheduleUrl, maxWidth }));\n });\n return handles;\n}\n", "import { useEffect, useRef } from 'react';\nimport { mount } from './widget';\nimport type { DailySoupProps } from './types';\n\nexport function DailySoup({ lang = 'zh', theme = 'auto', scheduleUrl, className, maxWidth }: DailySoupProps) {\n const hostRef = useRef<HTMLDivElement | null>(null);\n\n const themeKey = typeof theme === 'string' ? theme : JSON.stringify(theme);\n useEffect(() => {\n if (!hostRef.current) return;\n const handle = mount(hostRef.current, { lang, theme, scheduleUrl, maxWidth });\n return () => handle.destroy();\n }, [lang, themeKey, scheduleUrl, maxWidth]);\n\n return <div ref={hostRef} className={className} data-daily-soup-host=\"\" />;\n}\n"],
5
+ "mappings": ";AAcA,IAAM,UAAmC;AAAA,EACvC,IAAI;AAAA,IACF,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,mBAAmB;AAAA,IACnB,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,YAAY;AAAA,EACd;AACF;AAEO,SAAS,EAAE,MAAuB;AACvC,SAAO,QAAQ,IAAI,KAAK,QAAQ;AAClC;;;AC5BA,SAAS,cAAc,QAA4C;AACjE,SAAO,OAAO,WAAW,YAAY,WAAW;AAClD;AAEO,SAAS,aAAa,QAAoC;AAC/D,MAAI,cAAc,MAAM,EAAG,QAAO,OAAO,QAAQ;AACjD,MAAI,WAAW,WAAW,WAAW,OAAQ,QAAO;AACpD,MAAI,OAAO,WAAW,eAAe,CAAC,OAAO,WAAY,QAAO;AAChE,SAAO,OAAO,WAAW,8BAA8B,EAAE,UAAU,SAAS;AAC9E;AAEO,SAAS,eAAe,QAAyC;AACtE,SAAO,cAAc,MAAM,IAAI,SAAS;AAC1C;AAEO,SAAS,iBAAiB,IAAgD;AAC/E,MAAI,OAAO,WAAW,eAAe,CAAC,OAAO,WAAY,QAAO,MAAM;AAAA,EAAC;AACvE,QAAM,MAAM,OAAO,WAAW,8BAA8B;AAC5D,QAAM,UAAU,CAAC,MAA2B,GAAG,EAAE,UAAU,SAAS,OAAO;AAC3E,MAAI,iBAAiB,UAAU,OAAO;AACtC,SAAO,MAAM,IAAI,oBAAoB,UAAU,OAAO;AACxD;;;ACvBA,IAAM,YAAY;AAOlB,eAAsB,gBAAgB,SAAyC;AAC7E,QAAM,UAAU,GAAG,QAAQ,IAAI,WAAM,QAAQ,MAAM;AACnD,MAAI,OAAO,cAAc,eAAe,UAAU,WAAW;AAC3D,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,OAAO;AAC3C,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEO,SAAS,eAAe,SAA+B;AAC5D,QAAM,OAAO,mBAAmB,GAAG,QAAQ,IAAI,WAAM,QAAQ,MAAM,EAAE;AACrE,QAAM,MAAM,mBAAmB,SAAS;AACxC,SAAO,yCAAyC,IAAI,QAAQ,GAAG;AACjE;AAEO,SAAS,kBAAkB,SAA+B;AAC/D,QAAM,MAAM,mBAAmB,GAAG,SAAS,WAAM,QAAQ,IAAI,EAAE;AAC/D,SAAO,mDAAmD,GAAG;AAC/D;;;AC7BO,IAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAtB,SAAS,UAAU,MAAY,oBAAI,KAAK,GAAW;AACxD,QAAM,OAAO,IAAI,KAAK,IAAI,QAAQ,IAAI,IAAI,KAAK,KAAK,GAAI;AACxD,QAAM,KAAK,KAAK,eAAe;AAC/B,QAAM,KAAK,OAAO,KAAK,YAAY,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG;AACzD,QAAM,KAAK,OAAO,KAAK,WAAW,CAAC,EAAE,SAAS,GAAG,GAAG;AACpD,SAAO,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE;AAC1B;;;ACCA,IAAM,wBAAwB;AAmB9B,SAAS,OAAO,GAAmB;AACjC,SAAO,EACJ,QAAQ,MAAM,OAAO,EACrB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,MAAM,EACpB,QAAQ,MAAM,QAAQ,EACtB,QAAQ,MAAM,OAAO;AAC1B;AAEA,SAAS,WAAW,MAA6C;AAC/D,MAAI,OAAO,KAAK,iBAAiB,YAAY;AAC3C,QAAI,KAAK,WAAY,QAAO,KAAK;AACjC,WAAO,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAAA,EAC3C;AACA,UAAQ,KAAK,kEAAkE;AAC/E,SAAO;AACT;AAEA,SAAS,aAAa,MAAgC;AACpD,QAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,QAAM,cAAc;AACpB,OAAK,YAAY,KAAK;AACxB;AAEA,SAAS,cAAc,OAAmC;AACxD,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,YAAY,cAAc,KAAK;AACpC,OAAK,YAAY;AAAA;AAAA;AAAA;AAIjB,SAAO;AACT;AAEA,SAAS,YAAY,MAAmB,OAAc,MAAY,OAAsB;AACtF,QAAM,IAAI,EAAE,IAAI;AAChB,OAAK,YAAY,cAAc,KAAK;AACpC,QAAM,cAAc,MAAM,YACtB,YAAY,OAAO,MAAM,SAAS,CAAC,+CAA+C,OAAO,MAAM,MAAM,CAAC,SACtG,OAAO,MAAM,MAAM;AACvB,QAAM,OAAO,MAAM,gBAAgB,wBAC/B,yBAAyB,OAAO,EAAE,iBAAiB,CAAC,YACpD;AACJ,OAAK,YAAY;AAAA,0BACO,OAAO,MAAM,IAAI,CAAC;AAAA;AAAA,uCAEV,OAAO,MAAM,MAAM,CAAC,GAAG,IAAI;AAAA,QACrD,MAAM,SAAS,2BAA2B,EAAE,MAAM,SAAI,WAAW,YAAY,EAAE;AAAA;AAAA;AAAA;AAAA,8EAIT,OAAO,EAAE,IAAI,CAAC;AAAA,+EAClB,OAAO,EAAE,IAAI,CAAC;AAAA;AAAA,kDAEtC,OAAO,eAAe,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,CAAC,2DAA2D,OAAO,EAAE,MAAM,CAAC;AAAA;AAAA;AAAA,qDAG1I,OAAO,kBAAkB,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,CAAC,2DAA2D,OAAO,EAAE,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA,gIAIxE,EAAE,SAAS;AAAA;AAAA;AAIzI,QAAM,UAAU,KAAK,cAAiC,sBAAsB;AAC5E,MAAI,SAAS;AACX,YAAQ,iBAAiB,SAAS,YAAY;AAC5C,YAAM,KAAK,MAAM,gBAAgB,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO,CAAC;AAC3E,UAAI,IAAI;AACN,cAAM,QAAQ,QAAQ,cAAc,iBAAiB;AACrD,cAAM,gBAAgB,OAAO,eAAe;AAC5C,YAAI,MAAO,OAAM,cAAc,EAAE;AACjC,gBAAQ,UAAU,IAAI,UAAU;AAChC,mBAAW,MAAM;AACf,cAAI,MAAO,OAAM,cAAc;AAC/B,kBAAQ,UAAU,OAAO,UAAU;AAAA,QACrC,GAAG,GAAI;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEA,SAAS,YAAY,MAAmB,MAAY,OAAsB;AACxE,OAAK,YAAY,cAAc,KAAK;AACpC,QAAM,IAAI,EAAE,IAAI;AAChB,OAAK,YAAY,uBAAuB,OAAO,EAAE,UAAU,CAAC;AAC9D;AAEA,eAAe,cAAc,aAAqB,MAAsC;AACtF,QAAM,OAAO,YAAY,QAAQ,OAAO,EAAE;AAC1C,QAAM,MAAM,GAAG,IAAI,aAAa,IAAI;AACpC,MAAI;AACF,UAAM,OAAoB,SAAS,KAAK,EAAE,aAAa,OAAO,IAAI,EAAE,aAAa,QAAQ,MAAM,OAAO;AACtG,UAAM,MAAM,MAAM,MAAM,KAAK,IAAI;AACjC,QAAI,CAAC,IAAI,GAAI,QAAO;AACpB,WAAQ,MAAM,IAAI,KAAK;AAAA,EACzB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,UAAU,UAAkC;AACnD,QAAM,QAAQ,UAAU;AACxB,QAAM,KAAK,SAAS,QAAQ,KAAK;AACjC,MAAI,MAAM,SAAS,OAAO,EAAE,EAAG,QAAO,SAAS,OAAO,EAAE;AACxD,QAAM,aAAa,OAAO,KAAK,SAAS,MAAM,EAAE,KAAK,EAAE,CAAC;AACxD,MAAI,cAAc,SAAS,OAAO,UAAU,GAAG;AAC7C,YAAQ,KAAK,wEAAwE;AACrF,WAAO,SAAS,OAAO,UAAU;AAAA,EACnC;AACA,SAAO;AACT;AAEA,SAAS,oBAAoB,MAAmB,QAAqB,UAAmB;AACtF,QAAM,SAAS,eAAe,MAAM;AACpC,MAAI,QAAQ;AACV,QAAI,OAAO,GAAI,MAAK,MAAM,YAAY,WAAW,OAAO,EAAE;AAC1D,QAAI,OAAO,IAAK,MAAK,MAAM,YAAY,WAAW,OAAO,GAAG;AAC5D,QAAI,OAAO,MAAO,MAAK,MAAM,YAAY,cAAc,OAAO,KAAK;AACnE,QAAI,OAAO,OAAQ,MAAK,MAAM,YAAY,eAAe,OAAO,MAAM;AACtE,QAAI,OAAO,OAAQ,MAAK,MAAM,YAAY,eAAe,OAAO,MAAM;AAAA,EACxE;AACA,MAAI,SAAU,MAAK,MAAM,YAAY,kBAAkB,QAAQ;AACjE;AAEO,SAAS,MAAM,MAAmB,UAAwB,CAAC,GAAgB;AAChF,QAAM,OAAa,QAAQ,QAAQ;AACnC,QAAM,cAA2B,QAAQ,SAAS;AAClD,QAAM,cAAc,QAAQ,gBAAgB,SAAY,wBAAwB,QAAQ;AACxF,QAAM,WAAW,QAAQ;AAEzB,MAAI,gBAAgB,aAAa,WAAW;AAC5C,QAAM,OAAO,WAAW,IAAI;AAC5B,MAAI,SAAS,MAAM;AAEjB,SAAK,cAAc;AAAA,EACrB,OAAO;AACL,WAAQ,KAAoB,WAAY,CAAC,KAAoB,YAAa,KAAoB,UAAW;AAAA,EAC3G;AACA,eAAa,IAAI;AAEjB,QAAM,OAAO,cAAc,aAAa;AACxC,sBAAoB,MAAM,aAAa,QAAQ;AAC/C,OAAK,YAAY,IAAI;AAErB,QAAM,QAAqB;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,cAAc,MAAM;AAAA,IAAC;AAAA,IACrB,mBAAmB,MAAM;AAAA,IAAC;AAAA,IAC1B,UAAU;AAAA,IACV,eAAe;AAAA,EACjB;AAEA,MAAI,gBAAgB,QAAQ;AAC1B,UAAM,eAAe,iBAAiB,CAACA,OAAM;AAC3C,sBAAgBA;AAChB,YAAM,OAAO,UAAU,OAAO,YAAY,SAAS;AACnD,YAAM,OAAO,UAAU,IAAI,MAAMA,EAAC,EAAE;AAAA,IACtC,CAAC;AAAA,EACH;AAEA,MAAI,YAAY;AAChB,MAAI,UAAU;AAEd,QAAM,OAAO,YAAY;AACvB,UAAM,WAAW,MAAM,cAAc,aAAa,IAAI;AACtD,QAAI,UAAW;AACf,QAAI,CAAC,UAAU;AACb,UAAI,CAAC,SAAS;AACZ,kBAAU;AACV,mBAAW,MAAM,GAAI;AACrB;AAAA,MACF;AACA,kBAAY,MAAM,QAAQ,MAAM,aAAa;AAC7C;AAAA,IACF;AACA,UAAM,WAAW;AACjB,UAAM,QAAQ,UAAU,QAAQ;AAChC,QAAI,CAAC,OAAO;AACV,kBAAY,MAAM,QAAQ,MAAM,aAAa;AAC7C;AAAA,IACF;AACA,UAAM,gBAAgB,UAAU;AAChC,gBAAY,MAAM,QAAQ,OAAO,MAAM,aAAa;AAAA,EACtD;AACA,OAAK;AAEL,MAAI,OAAO,aAAa,aAAa;AACnC,UAAM,eAAe,MAAM;AACzB,UAAI,SAAS,oBAAoB,UAAW;AAC5C,UAAI,CAAC,MAAM,SAAU;AACrB,YAAM,QAAQ,UAAU;AACxB,UAAI,UAAU,MAAM,cAAe;AACnC,YAAM,QAAQ,UAAU,MAAM,QAAQ;AACtC,UAAI,CAAC,MAAO;AACZ,YAAM,gBAAgB;AACtB,kBAAY,MAAM,QAAQ,OAAO,MAAM,aAAa;AAAA,IACtD;AACA,aAAS,iBAAiB,oBAAoB,YAAY;AAC1D,UAAM,oBAAoB,MAAM,SAAS,oBAAoB,oBAAoB,YAAY;AAAA,EAC/F;AAEA,SAAO;AAAA,IACL,UAAU;AACR,kBAAY;AACZ,YAAM,aAAa;AACnB,YAAM,kBAAkB;AACxB,UAAI,SAAS,MAAM;AACjB,aAAK,cAAc;AAAA,MACrB,WAAW,KAAK,YAAY;AAC1B,eAAO,KAAK,WAAW,WAAY,MAAK,WAAW,YAAY,KAAK,WAAW,UAAU;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,SAAS,WAAW,kCAAiD;AACnF,MAAI,OAAO,aAAa,YAAa,QAAO,CAAC;AAC7C,QAAM,QAAQ,SAAS,iBAA8B,QAAQ;AAC7D,QAAM,UAAyB,CAAC;AAChC,QAAM,QAAQ,CAAC,SAAS;AACtB,UAAM,OAAQ,KAAK,QAAQ,QAA6B;AACxD,UAAM,QAAS,KAAK,QAAQ,SAAmD;AAC/E,UAAM,cAAc,KAAK,QAAQ;AACjC,UAAM,WAAW,KAAK,QAAQ;AAC9B,YAAQ,KAAK,MAAM,MAAM,EAAE,MAAM,OAAO,aAAa,SAAS,CAAC,CAAC;AAAA,EAClE,CAAC;AACD,SAAO;AACT;;;ACpQA,SAAS,WAAW,cAAc;AAczB;AAVF,SAAS,UAAU,EAAE,OAAO,MAAM,QAAQ,QAAQ,aAAa,WAAW,SAAS,GAAmB;AAC3G,QAAM,UAAU,OAA8B,IAAI;AAElD,QAAM,WAAW,OAAO,UAAU,WAAW,QAAQ,KAAK,UAAU,KAAK;AACzE,YAAU,MAAM;AACd,QAAI,CAAC,QAAQ,QAAS;AACtB,UAAM,SAAS,MAAM,QAAQ,SAAS,EAAE,MAAM,OAAO,aAAa,SAAS,CAAC;AAC5E,WAAO,MAAM,OAAO,QAAQ;AAAA,EAC9B,GAAG,CAAC,MAAM,UAAU,aAAa,QAAQ,CAAC;AAE1C,SAAO,oBAAC,SAAI,KAAK,SAAS,WAAsB,wBAAqB,IAAG;AAC1E;",
6
6
  "names": ["t"]
7
7
  }
package/dist/embed.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";var DailySoup=(()=>{var b=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var c=(e,t)=>()=>(e&&(t=e(e=0)),t);var T=(e,t)=>{for(var n in t)b(e,n,{get:t[n],enumerable:!0})},O=(e,t,n,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of j(t))!B.call(e,o)&&o!==n&&b(e,o,{get:()=>t[o],enumerable:!(r=X(t,o))||r.enumerable});return e};var Q=e=>O(b({},"__esModule",{value:!0}),e);function y(e){return S[e]??S.zh}var S,L=c(()=>{"use strict";S={zh:{copy:"\u8907\u88FD",copied:"\u5DF2\u8907\u88FD",share:"\u5206\u4EAB",source:"\u51FA\u8655",poweredBy:"\u7531 mshmwr \u63D0\u4F9B",attributedPopular:"\u50B3\u7D71\u6B78\u5C6C",shareX:"\u5206\u4EAB\u5230 X",shareLine:"\u5206\u4EAB\u5230 LINE",loadFailed:"\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557"}}});function C(e){return typeof e=="object"&&e!==null}function E(e){return C(e)?e.base??"light":e==="light"||e==="dark"?e:typeof window>"u"||!window.matchMedia?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function k(e){return C(e)?e:null}function $(e){if(typeof window>"u"||!window.matchMedia)return()=>{};let t=window.matchMedia("(prefers-color-scheme: dark)"),n=r=>e(r.matches?"dark":"light");return t.addEventListener("change",n),()=>t.removeEventListener("change",n)}var M=c(()=>{"use strict"});async function U(e){let t=`${e.text} \u2014 ${e.author}`;if(typeof navigator<"u"&&navigator.clipboard)try{return await navigator.clipboard.writeText(t),!0}catch{return!1}return!1}function H(e){let t=encodeURIComponent(`${e.text} \u2014 ${e.author}`),n=encodeURIComponent(R);return`https://twitter.com/intent/tweet?text=${t}&url=${n}`}function D(e){return`https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(`${R} \u2014 ${e.text}`)}`}var R,z=c(()=>{"use strict";R="https://daily-soup-widget.vercel.app"});var q,I=c(()=>{"use strict";q=`
1
+ "use strict";var DailySoup=(()=>{var w=Object.defineProperty;var O=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var F=Object.prototype.hasOwnProperty;var u=(e,t)=>()=>(e&&(t=e(e=0)),t);var L=(e,t)=>{for(var r in t)w(e,r,{get:t[r],enumerable:!0})},V=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Q(t))!F.call(e,o)&&o!==r&&w(e,o,{get:()=>t[o],enumerable:!(n=O(t,o))||n.enumerable});return e};var G=e=>V(w({},"__esModule",{value:!0}),e);function v(e){return C[e]??C.zh}var C,E=u(()=>{"use strict";C={zh:{copy:"\u8907\u88FD",copied:"\u5DF2\u8907\u88FD",share:"\u5206\u4EAB",source:"\u51FA\u8655",poweredBy:"\u7531 mshmwr \u63D0\u4F9B",attributedPopular:"\u50B3\u7D71\u6B78\u5C6C",shareX:"\u5206\u4EAB\u5230 X",shareLine:"\u5206\u4EAB\u5230 LINE",loadFailed:"\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557"}}});function $(e){return typeof e=="object"&&e!==null}function k(e){return $(e)?e.base??"light":e==="light"||e==="dark"?e:typeof window>"u"||!window.matchMedia?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function M(e){return $(e)?e:null}function R(e){if(typeof window>"u"||!window.matchMedia)return()=>{};let t=window.matchMedia("(prefers-color-scheme: dark)"),r=n=>e(n.matches?"dark":"light");return t.addEventListener("change",r),()=>t.removeEventListener("change",r)}var U=u(()=>{"use strict"});async function H(e){let t=`${e.text} \u2014 ${e.author}`;if(typeof navigator<"u"&&navigator.clipboard)try{return await navigator.clipboard.writeText(t),!0}catch{return!1}return!1}function z(e){let t=encodeURIComponent(`${e.text} \u2014 ${e.author}`),r=encodeURIComponent(D);return`https://twitter.com/intent/tweet?text=${t}&url=${r}`}function q(e){return`https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(`${D} \u2014 ${e.text}`)}`}var D,I=u(()=>{"use strict";D="https://daily-soup-widget.vercel.app"});var P,A=u(()=>{"use strict";P=`
2
2
  :host { all: initial; display: block; font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans TC", sans-serif; }
3
3
  * { box-sizing: border-box; }
4
4
  .ds-card {
@@ -62,9 +62,9 @@
62
62
  align-items: center;
63
63
  gap: 0.25rem;
64
64
  }
65
- .ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
65
+ .ds-btn:hover { color: var(--ds-accent); border-color: var(--ds-accent); }
66
66
  .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }
67
- .ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
67
+ .ds-btn.ds-toast { color: var(--ds-accent); border-color: var(--ds-accent); }
68
68
  .ds-powered { font-size: 0.75em; color: var(--ds-muted); }
69
69
  .ds-powered a { color: var(--ds-muted); text-decoration: none; }
70
70
  .ds-powered a:hover { text-decoration: underline; }
@@ -90,28 +90,28 @@
90
90
  @media (prefers-reduced-motion: reduce) {
91
91
  .ds-card, .ds-btn { transition: none; }
92
92
  }
93
- `});function P(e=new Date){let t=new Date(e.getTime()+288e5),n=t.getUTCFullYear(),r=String(t.getUTCMonth()+1).padStart(2,"0"),o=String(t.getUTCDate()).padStart(2,"0");return`${n}-${r}-${o}`}var A=c(()=>{"use strict"});var _={};T(_,{mount:()=>f,mountAll:()=>p});function d(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function G(e){return typeof e.attachShadow=="function"?e.shadowRoot?e.shadowRoot:e.attachShadow({mode:"open"}):(console.warn("[daily-soup] attachShadow unsupported, falling back to light DOM"),e)}function Y(e){let t=document.createElement("style");t.textContent=q,e.appendChild(t)}function J(e){let t=document.createElement("div");return t.className=`ds-card ds-${e} ds-skeleton`,t.innerHTML=`
93
+ `});function g(e=new Date){let t=new Date(e.getTime()+288e5),r=t.getUTCFullYear(),n=String(t.getUTCMonth()+1).padStart(2,"0"),o=String(t.getUTCDate()).padStart(2,"0");return`${r}-${n}-${o}`}var W=u(()=>{"use strict"});var j={};L(j,{mount:()=>b,mountAll:()=>p});function i(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#39;")}function J(e){return typeof e.attachShadow=="function"?e.shadowRoot?e.shadowRoot:e.attachShadow({mode:"open"}):(console.warn("[daily-soup] attachShadow unsupported, falling back to light DOM"),e)}function K(e){let t=document.createElement("style");t.textContent=P,e.appendChild(t)}function Z(e){let t=document.createElement("div");return t.className=`ds-card ds-${e} ds-skeleton`,t.innerHTML=`
94
94
  <div class="ds-quote">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
95
95
  <div class="ds-meta"><span class="ds-author">&nbsp;</span><span class="ds-source">&nbsp;</span></div>
96
- `,t}function K(e,t,n,r){let o=y(n);e.className=`ds-card ds-${r}`;let l=t.sourceUrl?`<a href="${d(t.sourceUrl)}" target="_blank" rel="noopener noreferrer">${d(t.source)}</a>`:d(t.source),i=t.attribution==="popular-attribution"?`<span class="ds-flag">${d(o.attributedPopular)}</span>`:"";e.innerHTML=`
97
- <p class="ds-quote">${d(t.text)}</p>
96
+ `,t}function _(e,t,r,n){let o=v(r);e.className=`ds-card ds-${n}`;let c=t.sourceUrl?`<a href="${i(t.sourceUrl)}" target="_blank" rel="noopener noreferrer">${i(t.source)}</a>`:i(t.source),d=t.attribution==="popular-attribution"?`<span class="ds-flag">${i(o.attributedPopular)}</span>`:"";e.innerHTML=`
97
+ <p class="ds-quote">${i(t.text)}</p>
98
98
  <div class="ds-meta">
99
- <span class="ds-author">\u2014 ${d(t.author)}${i}</span>
100
- ${t.source?`<span class="ds-source">${o.source}\uFF1A${l}</span>`:""}
99
+ <span class="ds-author">\u2014 ${i(t.author)}${d}</span>
100
+ ${t.source?`<span class="ds-source">${o.source}\uFF1A${c}</span>`:""}
101
101
  </div>
102
102
  <div class="ds-actions">
103
103
  <div class="ds-share">
104
- <button class="ds-btn" data-action="copy" type="button" aria-label="${d(o.copy)}">
105
- <span aria-hidden="true">\u29C9</span><span class="ds-share-label">${d(o.copy)}</span>
104
+ <button class="ds-btn" data-action="copy" type="button" aria-label="${i(o.copy)}">
105
+ <span aria-hidden="true">\u29C9</span><span class="ds-share-label">${i(o.copy)}</span>
106
106
  </button>
107
- <a class="ds-btn" data-action="x" href="${d(H({text:t.text,author:t.author}))}" target="_blank" rel="noopener noreferrer" aria-label="${d(o.shareX)}">
107
+ <a class="ds-btn" data-action="x" href="${i(z({text:t.text,author:t.author}))}" target="_blank" rel="noopener noreferrer" aria-label="${i(o.shareX)}">
108
108
  <span aria-hidden="true">\u{1D54F}</span><span class="ds-share-label">X</span>
109
109
  </a>
110
- <a class="ds-btn" data-action="line" href="${d(D({text:t.text,author:t.author}))}" target="_blank" rel="noopener noreferrer" aria-label="${d(o.shareLine)}">
110
+ <a class="ds-btn" data-action="line" href="${i(q({text:t.text,author:t.author}))}" target="_blank" rel="noopener noreferrer" aria-label="${i(o.shareLine)}">
111
111
  <span aria-hidden="true">L</span><span class="ds-share-label">LINE</span>
112
112
  </a>
113
113
  </div>
114
114
  <span class="ds-powered"><a href="https://personal-site-mocha-chi.vercel.app" target="_blank" rel="noopener noreferrer">${o.poweredBy}</a></span>
115
115
  </div>
116
- `;let a=e.querySelector('[data-action="copy"]');a&&a.addEventListener("click",async()=>{if(await U({text:t.text,author:t.author})){let s=a.querySelector(".ds-share-label"),h=s?.textContent??"";s&&(s.textContent=o.copied),a.classList.add("ds-toast"),setTimeout(()=>{s&&(s.textContent=h),a.classList.remove("ds-toast")},2e3)}})}function W(e,t,n){e.className=`ds-card ds-${n}`;let r=y(t);e.innerHTML=`<p class="ds-error">${d(r.loadFailed)}</p>`}async function V(e,t){let n=e.replace(/\/$/,""),r=`${n}/schedule-${t}.json`;try{let l=await fetch(r,n===""?{credentials:"omit"}:{credentials:"omit",mode:"cors"});return l.ok?await l.json():null}catch{return null}}function Z(e){let t=P(),n=e.entries[t];if(n&&e.quotes[n])return e.quotes[n];let r=Object.keys(e.quotes).sort()[0];return r&&e.quotes[r]?(console.warn("[daily-soup] today entry missing or stale, falling back to first quote"),e.quotes[r]):null}function ee(e,t,n){let r=k(t);r&&(r.bg&&e.style.setProperty("--ds-bg",r.bg),r.ink&&e.style.setProperty("--ds-fg",r.ink),r.muted&&e.style.setProperty("--ds-muted",r.muted),r.border&&e.style.setProperty("--ds-border",r.border),r.accent&&e.style.setProperty("--ds-accent",r.accent)),n&&e.style.setProperty("--ds-max-width",n)}function f(e,t={}){let n=t.lang??"zh",r=t.theme??"auto",o=t.scheduleUrl===void 0?F:t.scheduleUrl,l=t.maxWidth,i=E(r),a=G(e);if(a===e)e.textContent="";else for(;a.firstChild;)a.removeChild(a.firstChild);Y(a);let m=J(i);ee(m,r,l),a.appendChild(m);let s={lang:n,themeConfig:r,scheduleUrl:o,host:e,root:a,cardEl:m,unwatchTheme:()=>{}};r==="auto"&&(s.unwatchTheme=$(u=>{i=u,s.cardEl.classList.remove("ds-light","ds-dark"),s.cardEl.classList.add(`ds-${u}`)}));let h=!1,w=!1,v=async()=>{let u=await V(o,n);if(h)return;if(!u){if(!w){w=!0,setTimeout(v,2e3);return}W(s.cardEl,n,i);return}let x=Z(u);if(!x){W(s.cardEl,n,i);return}K(s.cardEl,x,n,i)};return v(),{destroy(){if(h=!0,s.unwatchTheme(),a===e)e.textContent="";else if(e.shadowRoot)for(;e.shadowRoot.firstChild;)e.shadowRoot.removeChild(e.shadowRoot.firstChild)}}}function p(e="[data-daily-soup], #daily-soup"){if(typeof document>"u")return[];let t=document.querySelectorAll(e),n=[];return t.forEach(r=>{let o=r.dataset.lang??"zh",l=r.dataset.theme??"auto",i=r.dataset.scheduleUrl,a=r.dataset.maxWidth;n.push(f(r,{lang:o,theme:l,scheduleUrl:i,maxWidth:a}))}),n}var F,g=c(()=>{"use strict";L();M();z();I();A();F="https://daily-soup-widget.vercel.app"});var te={};T(te,{mount:()=>f,mountAll:()=>p});g();g();function N(){let e=p();return typeof window<"u"&&(window.DailySoup=window.DailySoup??{},Promise.resolve().then(()=>(g(),_)).then(({mount:t})=>{window.DailySoup&&(window.DailySoup.mount=t,window.DailySoup.mountAll=p)})),e}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",N,{once:!0}):N());return Q(te);})();
116
+ `;let a=e.querySelector('[data-action="copy"]');a&&a.addEventListener("click",async()=>{if(await H({text:t.text,author:t.author})){let s=a.querySelector(".ds-share-label"),f=s?.textContent??"";s&&(s.textContent=o.copied),a.classList.add("ds-toast"),setTimeout(()=>{s&&(s.textContent=f),a.classList.remove("ds-toast")},2e3)}})}function N(e,t,r){e.className=`ds-card ds-${r}`;let n=v(t);e.innerHTML=`<p class="ds-error">${i(n.loadFailed)}</p>`}async function ee(e,t){let r=e.replace(/\/$/,""),n=`${r}/schedule-${t}.json`;try{let c=await fetch(n,r===""?{credentials:"omit"}:{credentials:"omit",mode:"cors"});return c.ok?await c.json():null}catch{return null}}function X(e){let t=g(),r=e.entries[t];if(r&&e.quotes[r])return e.quotes[r];let n=Object.keys(e.quotes).sort()[0];return n&&e.quotes[n]?(console.warn("[daily-soup] today entry missing or stale, falling back to first quote"),e.quotes[n]):null}function te(e,t,r){let n=M(t);n&&(n.bg&&e.style.setProperty("--ds-bg",n.bg),n.ink&&e.style.setProperty("--ds-fg",n.ink),n.muted&&e.style.setProperty("--ds-muted",n.muted),n.border&&e.style.setProperty("--ds-border",n.border),n.accent&&e.style.setProperty("--ds-accent",n.accent)),r&&e.style.setProperty("--ds-max-width",r)}function b(e,t={}){let r=t.lang??"zh",n=t.theme??"auto",o=t.scheduleUrl===void 0?Y:t.scheduleUrl,c=t.maxWidth,d=k(n),a=J(e);if(a===e)e.textContent="";else for(;a.firstChild;)a.removeChild(a.firstChild);K(a);let h=Z(d);te(h,n,c),a.appendChild(h);let s={lang:r,themeConfig:n,scheduleUrl:o,host:e,root:a,cardEl:h,unwatchTheme:()=>{},unwatchVisibility:()=>{},schedule:null,displayedDate:""};n==="auto"&&(s.unwatchTheme=R(l=>{d=l,s.cardEl.classList.remove("ds-light","ds-dark"),s.cardEl.classList.add(`ds-${l}`)}));let f=!1,x=!1,T=async()=>{let l=await ee(o,r);if(f)return;if(!l){if(!x){x=!0,setTimeout(T,2e3);return}N(s.cardEl,r,d);return}s.schedule=l;let m=X(l);if(!m){N(s.cardEl,r,d);return}s.displayedDate=g(),_(s.cardEl,m,r,d)};if(T(),typeof document<"u"){let l=()=>{if(document.visibilityState!=="visible"||!s.schedule)return;let m=g();if(m===s.displayedDate)return;let S=X(s.schedule);S&&(s.displayedDate=m,_(s.cardEl,S,r,d))};document.addEventListener("visibilitychange",l),s.unwatchVisibility=()=>document.removeEventListener("visibilitychange",l)}return{destroy(){if(f=!0,s.unwatchTheme(),s.unwatchVisibility(),a===e)e.textContent="";else if(e.shadowRoot)for(;e.shadowRoot.firstChild;)e.shadowRoot.removeChild(e.shadowRoot.firstChild)}}}function p(e="[data-daily-soup], #daily-soup"){if(typeof document>"u")return[];let t=document.querySelectorAll(e),r=[];return t.forEach(n=>{let o=n.dataset.lang??"zh",c=n.dataset.theme??"auto",d=n.dataset.scheduleUrl,a=n.dataset.maxWidth;r.push(b(n,{lang:o,theme:c,scheduleUrl:d,maxWidth:a}))}),r}var Y,y=u(()=>{"use strict";E();U();I();A();W();Y="https://daily-soup-widget.vercel.app"});var ne={};L(ne,{mount:()=>b,mountAll:()=>p});y();y();function B(){let e=p();return typeof window<"u"&&(window.DailySoup=window.DailySoup??{},Promise.resolve().then(()=>(y(),j)).then(({mount:t})=>{window.DailySoup&&(window.DailySoup.mount=t,window.DailySoup.mountAll=p)})),e}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",B,{once:!0}):B());return G(ne);})();
117
117
  //# sourceMappingURL=embed.js.map
package/dist/embed.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/i18n.ts", "../src/theme.ts", "../src/share.ts", "../src/styles.ts", "../src/date.ts", "../src/widget.ts", "../src/embed.ts"],
4
- "sourcesContent": ["import type { Lang } from './types';\n\ninterface UiStrings {\n copy: string;\n copied: string;\n share: string;\n source: string;\n poweredBy: string;\n attributedPopular: string;\n shareX: string;\n shareLine: string;\n loadFailed: string;\n}\n\nconst STRINGS: Record<Lang, UiStrings> = {\n zh: {\n copy: '\u8907\u88FD',\n copied: '\u5DF2\u8907\u88FD',\n share: '\u5206\u4EAB',\n source: '\u51FA\u8655',\n poweredBy: '\u7531 mshmwr \u63D0\u4F9B',\n attributedPopular: '\u50B3\u7D71\u6B78\u5C6C',\n shareX: '\u5206\u4EAB\u5230 X',\n shareLine: '\u5206\u4EAB\u5230 LINE',\n loadFailed: '\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557',\n },\n};\n\nexport function t(lang: Lang): UiStrings {\n return STRINGS[lang] ?? STRINGS.zh;\n}\n\nexport type { UiStrings };\n", "import type { ThemeConfig, ResolvedTheme, ThemeColors } from './types';\n\nfunction isThemeColors(config: ThemeConfig): config is ThemeColors {\n return typeof config === 'object' && config !== null;\n}\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\n if (isThemeColors(config)) return config.base ?? 'light';\n if (config === 'light' || config === 'dark') return config;\n if (typeof window === 'undefined' || !window.matchMedia) return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nexport function getThemeColors(config: ThemeConfig): ThemeColors | null {\n return isThemeColors(config) ? config : null;\n}\n\nexport function watchSystemTheme(cb: (theme: ResolvedTheme) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light');\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n}\n", "const SHARE_URL = 'https://daily-soup-widget.vercel.app';\n\nexport interface ShareContent {\n text: string;\n author: string;\n}\n\nexport async function copyToClipboard(content: ShareContent): Promise<boolean> {\n const payload = `${content.text} \u2014 ${content.author}`;\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(payload);\n return true;\n } catch {\n return false;\n }\n }\n return false;\n}\n\nexport function buildXShareUrl(content: ShareContent): string {\n const text = encodeURIComponent(`${content.text} \u2014 ${content.author}`);\n const url = encodeURIComponent(SHARE_URL);\n return `https://twitter.com/intent/tweet?text=${text}&url=${url}`;\n}\n\nexport function buildLineShareUrl(content: ShareContent): string {\n const url = encodeURIComponent(`${SHARE_URL} \u2014 ${content.text}`);\n return `https://social-plugins.line.me/lineit/share?url=${url}`;\n}\n", "export const WIDGET_STYLES = `\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n`;\n", "export function todayUtc8(now: Date = new Date()): string {\n const utc8 = new Date(now.getTime() + 8 * 60 * 60 * 1000);\n const yy = utc8.getUTCFullYear();\n const mm = String(utc8.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(utc8.getUTCDate()).padStart(2, '0');\n return `${yy}-${mm}-${dd}`;\n}\n", "import type { Lang, MountOptions, Quote, ResolvedTheme, Schedule, ThemeConfig } from './types';\nimport { t } from './i18n';\nimport { resolveTheme, watchSystemTheme, getThemeColors } from './theme';\nimport { buildLineShareUrl, buildXShareUrl, copyToClipboard } from './share';\nimport { WIDGET_STYLES } from './styles';\nimport { todayUtc8 } from './date';\n\nconst DEFAULT_SCHEDULE_BASE = 'https://daily-soup-widget.vercel.app';\n\nexport interface MountHandle {\n destroy(): void;\n}\n\ninterface WidgetState {\n lang: Lang;\n themeConfig: ThemeConfig;\n scheduleUrl: string;\n host: HTMLElement;\n root: ShadowRoot | HTMLElement;\n cardEl: HTMLElement;\n unwatchTheme: () => void;\n}\n\nfunction escape(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nfunction attachRoot(host: HTMLElement): ShadowRoot | HTMLElement {\n if (typeof host.attachShadow === 'function') {\n if (host.shadowRoot) return host.shadowRoot;\n return host.attachShadow({ mode: 'open' });\n }\n console.warn('[daily-soup] attachShadow unsupported, falling back to light DOM');\n return host;\n}\n\nfunction injectStyles(root: ShadowRoot | HTMLElement) {\n const style = document.createElement('style');\n style.textContent = WIDGET_STYLES;\n root.appendChild(style);\n}\n\nfunction buildSkeleton(theme: ResolvedTheme): HTMLElement {\n const card = document.createElement('div');\n card.className = `ds-card ds-${theme} ds-skeleton`;\n card.innerHTML = `\n <div class=\"ds-quote\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>\n <div class=\"ds-meta\"><span class=\"ds-author\">&nbsp;</span><span class=\"ds-source\">&nbsp;</span></div>\n `;\n return card;\n}\n\nfunction renderQuote(card: HTMLElement, quote: Quote, lang: Lang, theme: ResolvedTheme) {\n const s = t(lang);\n card.className = `ds-card ds-${theme}`;\n const sourceLabel = quote.sourceUrl\n ? `<a href=\"${escape(quote.sourceUrl)}\" target=\"_blank\" rel=\"noopener noreferrer\">${escape(quote.source)}</a>`\n : escape(quote.source);\n const flag = quote.attribution === 'popular-attribution'\n ? `<span class=\"ds-flag\">${escape(s.attributedPopular)}</span>`\n : '';\n card.innerHTML = `\n <p class=\"ds-quote\">${escape(quote.text)}</p>\n <div class=\"ds-meta\">\n <span class=\"ds-author\">\u2014 ${escape(quote.author)}${flag}</span>\n ${quote.source ? `<span class=\"ds-source\">${s.source}\uFF1A${sourceLabel}</span>` : ''}\n </div>\n <div class=\"ds-actions\">\n <div class=\"ds-share\">\n <button class=\"ds-btn\" data-action=\"copy\" type=\"button\" aria-label=\"${escape(s.copy)}\">\n <span aria-hidden=\"true\">\u29C9</span><span class=\"ds-share-label\">${escape(s.copy)}</span>\n </button>\n <a class=\"ds-btn\" data-action=\"x\" href=\"${escape(buildXShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareX)}\">\n <span aria-hidden=\"true\">\uD835\uDD4F</span><span class=\"ds-share-label\">X</span>\n </a>\n <a class=\"ds-btn\" data-action=\"line\" href=\"${escape(buildLineShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareLine)}\">\n <span aria-hidden=\"true\">L</span><span class=\"ds-share-label\">LINE</span>\n </a>\n </div>\n <span class=\"ds-powered\"><a href=\"https://personal-site-mocha-chi.vercel.app\" target=\"_blank\" rel=\"noopener noreferrer\">${s.poweredBy}</a></span>\n </div>\n `;\n\n const copyBtn = card.querySelector<HTMLButtonElement>('[data-action=\"copy\"]');\n if (copyBtn) {\n copyBtn.addEventListener('click', async () => {\n const ok = await copyToClipboard({ text: quote.text, author: quote.author });\n if (ok) {\n const label = copyBtn.querySelector('.ds-share-label');\n const originalLabel = label?.textContent ?? '';\n if (label) label.textContent = s.copied;\n copyBtn.classList.add('ds-toast');\n setTimeout(() => {\n if (label) label.textContent = originalLabel;\n copyBtn.classList.remove('ds-toast');\n }, 2000);\n }\n });\n }\n}\n\nfunction renderError(card: HTMLElement, lang: Lang, theme: ResolvedTheme) {\n card.className = `ds-card ds-${theme}`;\n const s = t(lang);\n card.innerHTML = `<p class=\"ds-error\">${escape(s.loadFailed)}</p>`;\n}\n\nasync function fetchSchedule(scheduleUrl: string, lang: Lang): Promise<Schedule | null> {\n const base = scheduleUrl.replace(/\\/$/, '');\n const url = `${base}/schedule-${lang}.json`;\n try {\n const init: RequestInit = base === '' ? { credentials: 'omit' } : { credentials: 'omit', mode: 'cors' };\n const res = await fetch(url, init);\n if (!res.ok) return null;\n return (await res.json()) as Schedule;\n } catch {\n return null;\n }\n}\n\nfunction pickQuote(schedule: Schedule): Quote | null {\n const today = todayUtc8();\n const id = schedule.entries[today];\n if (id && schedule.quotes[id]) return schedule.quotes[id];\n const fallbackId = Object.keys(schedule.quotes).sort()[0];\n if (fallbackId && schedule.quotes[fallbackId]) {\n console.warn('[daily-soup] today entry missing or stale, falling back to first quote');\n return schedule.quotes[fallbackId];\n }\n return null;\n}\n\nfunction applyThemeOverrides(card: HTMLElement, config: ThemeConfig, maxWidth?: string) {\n const colors = getThemeColors(config);\n if (colors) {\n if (colors.bg) card.style.setProperty('--ds-bg', colors.bg);\n if (colors.ink) card.style.setProperty('--ds-fg', colors.ink);\n if (colors.muted) card.style.setProperty('--ds-muted', colors.muted);\n if (colors.border) card.style.setProperty('--ds-border', colors.border);\n if (colors.accent) card.style.setProperty('--ds-accent', colors.accent);\n }\n if (maxWidth) card.style.setProperty('--ds-max-width', maxWidth);\n}\n\nexport function mount(host: HTMLElement, options: MountOptions = {}): MountHandle {\n const lang: Lang = options.lang ?? 'zh';\n const themeConfig: ThemeConfig = options.theme ?? 'auto';\n const scheduleUrl = options.scheduleUrl === undefined ? DEFAULT_SCHEDULE_BASE : options.scheduleUrl;\n const maxWidth = options.maxWidth;\n\n let resolvedTheme = resolveTheme(themeConfig);\n const root = attachRoot(host);\n if (root === host) {\n // light DOM fallback \u2014 clear any prior content\n host.textContent = '';\n } else {\n while ((root as ShadowRoot).firstChild) (root as ShadowRoot).removeChild((root as ShadowRoot).firstChild!);\n }\n injectStyles(root);\n\n const card = buildSkeleton(resolvedTheme);\n applyThemeOverrides(card, themeConfig, maxWidth);\n root.appendChild(card);\n\n const state: WidgetState = {\n lang,\n themeConfig,\n scheduleUrl,\n host,\n root,\n cardEl: card,\n unwatchTheme: () => {},\n };\n\n if (themeConfig === 'auto') {\n state.unwatchTheme = watchSystemTheme((t) => {\n resolvedTheme = t;\n state.cardEl.classList.remove('ds-light', 'ds-dark');\n state.cardEl.classList.add(`ds-${t}`);\n });\n }\n\n let cancelled = false;\n let retried = false;\n\n const load = async () => {\n const schedule = await fetchSchedule(scheduleUrl, lang);\n if (cancelled) return;\n if (!schedule) {\n if (!retried) {\n retried = true;\n setTimeout(load, 2000);\n return;\n }\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n const quote = pickQuote(schedule);\n if (!quote) {\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n load();\n\n return {\n destroy() {\n cancelled = true;\n state.unwatchTheme();\n if (root === host) {\n host.textContent = '';\n } else if (host.shadowRoot) {\n while (host.shadowRoot.firstChild) host.shadowRoot.removeChild(host.shadowRoot.firstChild);\n }\n },\n };\n}\n\nexport function mountAll(selector = '[data-daily-soup], #daily-soup'): MountHandle[] {\n if (typeof document === 'undefined') return [];\n const nodes = document.querySelectorAll<HTMLElement>(selector);\n const handles: MountHandle[] = [];\n nodes.forEach((node) => {\n const lang = (node.dataset.lang as Lang | undefined) ?? 'zh';\n const theme = (node.dataset.theme as 'auto' | 'light' | 'dark' | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n const maxWidth = node.dataset.maxWidth;\n handles.push(mount(node, { lang, theme, scheduleUrl, maxWidth }));\n });\n return handles;\n}\n", "import { mountAll } from './widget';\n\ndeclare global {\n interface Window {\n DailySoup?: { mount: typeof import('./widget').mount; mountAll: typeof mountAll };\n }\n}\n\nfunction init() {\n const handles = mountAll();\n if (typeof window !== 'undefined') {\n window.DailySoup = window.DailySoup ?? ({} as Window['DailySoup']);\n // expose mount + mountAll for advanced consumers\n import('./widget').then(({ mount }) => {\n if (window.DailySoup) {\n window.DailySoup.mount = mount;\n window.DailySoup.mountAll = mountAll;\n }\n });\n }\n return handles;\n}\n\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', init, { once: true });\n } else {\n init();\n }\n}\n\nexport { mount, mountAll } from './widget';\n"],
5
- "mappings": "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",
6
- "names": ["t", "lang", "STRINGS", "init_i18n", "__esmMin", "isThemeColors", "config", "resolveTheme", "getThemeColors", "watchSystemTheme", "cb", "mql", "handler", "e", "init_theme", "__esmMin", "copyToClipboard", "content", "payload", "buildXShareUrl", "text", "url", "SHARE_URL", "buildLineShareUrl", "init_share", "__esmMin", "WIDGET_STYLES", "init_styles", "__esmMin", "todayUtc8", "now", "utc8", "yy", "mm", "dd", "init_date", "__esmMin", "widget_exports", "__export", "mount", "mountAll", "escape", "s", "attachRoot", "host", "injectStyles", "root", "style", "WIDGET_STYLES", "buildSkeleton", "theme", "card", "renderQuote", "quote", "lang", "t", "sourceLabel", "flag", "buildXShareUrl", "buildLineShareUrl", "copyBtn", "copyToClipboard", "label", "originalLabel", "renderError", "fetchSchedule", "scheduleUrl", "base", "url", "res", "pickQuote", "schedule", "today", "todayUtc8", "id", "fallbackId", "applyThemeOverrides", "config", "maxWidth", "colors", "getThemeColors", "options", "themeConfig", "DEFAULT_SCHEDULE_BASE", "resolvedTheme", "resolveTheme", "state", "watchSystemTheme", "cancelled", "retried", "load", "selector", "nodes", "handles", "node", "init_widget", "__esmMin", "init_i18n", "init_theme", "init_share", "init_styles", "init_date", "embed_exports", "__export", "mount", "mountAll", "init_widget", "init", "handles"]
4
+ "sourcesContent": ["import type { Lang } from './types';\n\ninterface UiStrings {\n copy: string;\n copied: string;\n share: string;\n source: string;\n poweredBy: string;\n attributedPopular: string;\n shareX: string;\n shareLine: string;\n loadFailed: string;\n}\n\nconst STRINGS: Record<Lang, UiStrings> = {\n zh: {\n copy: '\u8907\u88FD',\n copied: '\u5DF2\u8907\u88FD',\n share: '\u5206\u4EAB',\n source: '\u51FA\u8655',\n poweredBy: '\u7531 mshmwr \u63D0\u4F9B',\n attributedPopular: '\u50B3\u7D71\u6B78\u5C6C',\n shareX: '\u5206\u4EAB\u5230 X',\n shareLine: '\u5206\u4EAB\u5230 LINE',\n loadFailed: '\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557',\n },\n};\n\nexport function t(lang: Lang): UiStrings {\n return STRINGS[lang] ?? STRINGS.zh;\n}\n\nexport type { UiStrings };\n", "import type { ThemeConfig, ResolvedTheme, ThemeColors } from './types';\n\nfunction isThemeColors(config: ThemeConfig): config is ThemeColors {\n return typeof config === 'object' && config !== null;\n}\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\n if (isThemeColors(config)) return config.base ?? 'light';\n if (config === 'light' || config === 'dark') return config;\n if (typeof window === 'undefined' || !window.matchMedia) return 'light';\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n}\n\nexport function getThemeColors(config: ThemeConfig): ThemeColors | null {\n return isThemeColors(config) ? config : null;\n}\n\nexport function watchSystemTheme(cb: (theme: ResolvedTheme) => void): () => void {\n if (typeof window === 'undefined' || !window.matchMedia) return () => {};\n const mql = window.matchMedia('(prefers-color-scheme: dark)');\n const handler = (e: MediaQueryListEvent) => cb(e.matches ? 'dark' : 'light');\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n}\n", "const SHARE_URL = 'https://daily-soup-widget.vercel.app';\n\nexport interface ShareContent {\n text: string;\n author: string;\n}\n\nexport async function copyToClipboard(content: ShareContent): Promise<boolean> {\n const payload = `${content.text} \u2014 ${content.author}`;\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n try {\n await navigator.clipboard.writeText(payload);\n return true;\n } catch {\n return false;\n }\n }\n return false;\n}\n\nexport function buildXShareUrl(content: ShareContent): string {\n const text = encodeURIComponent(`${content.text} \u2014 ${content.author}`);\n const url = encodeURIComponent(SHARE_URL);\n return `https://twitter.com/intent/tweet?text=${text}&url=${url}`;\n}\n\nexport function buildLineShareUrl(content: ShareContent): string {\n const url = encodeURIComponent(`${SHARE_URL} \u2014 ${content.text}`);\n return `https://social-plugins.line.me/lineit/share?url=${url}`;\n}\n", "export const WIDGET_STYLES = `\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n`;\n", "export function todayUtc8(now: Date = new Date()): string {\n const utc8 = new Date(now.getTime() + 8 * 60 * 60 * 1000);\n const yy = utc8.getUTCFullYear();\n const mm = String(utc8.getUTCMonth() + 1).padStart(2, '0');\n const dd = String(utc8.getUTCDate()).padStart(2, '0');\n return `${yy}-${mm}-${dd}`;\n}\n", "import type { Lang, MountOptions, Quote, ResolvedTheme, Schedule, ThemeConfig } from './types';\nimport { t } from './i18n';\nimport { resolveTheme, watchSystemTheme, getThemeColors } from './theme';\nimport { buildLineShareUrl, buildXShareUrl, copyToClipboard } from './share';\nimport { WIDGET_STYLES } from './styles';\nimport { todayUtc8 } from './date';\n\nconst DEFAULT_SCHEDULE_BASE = 'https://daily-soup-widget.vercel.app';\n\nexport interface MountHandle {\n destroy(): void;\n}\n\ninterface WidgetState {\n lang: Lang;\n themeConfig: ThemeConfig;\n scheduleUrl: string;\n host: HTMLElement;\n root: ShadowRoot | HTMLElement;\n cardEl: HTMLElement;\n unwatchTheme: () => void;\n unwatchVisibility: () => void;\n schedule: Schedule | null;\n displayedDate: string;\n}\n\nfunction escape(s: string): string {\n return s\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\nfunction attachRoot(host: HTMLElement): ShadowRoot | HTMLElement {\n if (typeof host.attachShadow === 'function') {\n if (host.shadowRoot) return host.shadowRoot;\n return host.attachShadow({ mode: 'open' });\n }\n console.warn('[daily-soup] attachShadow unsupported, falling back to light DOM');\n return host;\n}\n\nfunction injectStyles(root: ShadowRoot | HTMLElement) {\n const style = document.createElement('style');\n style.textContent = WIDGET_STYLES;\n root.appendChild(style);\n}\n\nfunction buildSkeleton(theme: ResolvedTheme): HTMLElement {\n const card = document.createElement('div');\n card.className = `ds-card ds-${theme} ds-skeleton`;\n card.innerHTML = `\n <div class=\"ds-quote\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>\n <div class=\"ds-meta\"><span class=\"ds-author\">&nbsp;</span><span class=\"ds-source\">&nbsp;</span></div>\n `;\n return card;\n}\n\nfunction renderQuote(card: HTMLElement, quote: Quote, lang: Lang, theme: ResolvedTheme) {\n const s = t(lang);\n card.className = `ds-card ds-${theme}`;\n const sourceLabel = quote.sourceUrl\n ? `<a href=\"${escape(quote.sourceUrl)}\" target=\"_blank\" rel=\"noopener noreferrer\">${escape(quote.source)}</a>`\n : escape(quote.source);\n const flag = quote.attribution === 'popular-attribution'\n ? `<span class=\"ds-flag\">${escape(s.attributedPopular)}</span>`\n : '';\n card.innerHTML = `\n <p class=\"ds-quote\">${escape(quote.text)}</p>\n <div class=\"ds-meta\">\n <span class=\"ds-author\">\u2014 ${escape(quote.author)}${flag}</span>\n ${quote.source ? `<span class=\"ds-source\">${s.source}\uFF1A${sourceLabel}</span>` : ''}\n </div>\n <div class=\"ds-actions\">\n <div class=\"ds-share\">\n <button class=\"ds-btn\" data-action=\"copy\" type=\"button\" aria-label=\"${escape(s.copy)}\">\n <span aria-hidden=\"true\">\u29C9</span><span class=\"ds-share-label\">${escape(s.copy)}</span>\n </button>\n <a class=\"ds-btn\" data-action=\"x\" href=\"${escape(buildXShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareX)}\">\n <span aria-hidden=\"true\">\uD835\uDD4F</span><span class=\"ds-share-label\">X</span>\n </a>\n <a class=\"ds-btn\" data-action=\"line\" href=\"${escape(buildLineShareUrl({ text: quote.text, author: quote.author }))}\" target=\"_blank\" rel=\"noopener noreferrer\" aria-label=\"${escape(s.shareLine)}\">\n <span aria-hidden=\"true\">L</span><span class=\"ds-share-label\">LINE</span>\n </a>\n </div>\n <span class=\"ds-powered\"><a href=\"https://personal-site-mocha-chi.vercel.app\" target=\"_blank\" rel=\"noopener noreferrer\">${s.poweredBy}</a></span>\n </div>\n `;\n\n const copyBtn = card.querySelector<HTMLButtonElement>('[data-action=\"copy\"]');\n if (copyBtn) {\n copyBtn.addEventListener('click', async () => {\n const ok = await copyToClipboard({ text: quote.text, author: quote.author });\n if (ok) {\n const label = copyBtn.querySelector('.ds-share-label');\n const originalLabel = label?.textContent ?? '';\n if (label) label.textContent = s.copied;\n copyBtn.classList.add('ds-toast');\n setTimeout(() => {\n if (label) label.textContent = originalLabel;\n copyBtn.classList.remove('ds-toast');\n }, 2000);\n }\n });\n }\n}\n\nfunction renderError(card: HTMLElement, lang: Lang, theme: ResolvedTheme) {\n card.className = `ds-card ds-${theme}`;\n const s = t(lang);\n card.innerHTML = `<p class=\"ds-error\">${escape(s.loadFailed)}</p>`;\n}\n\nasync function fetchSchedule(scheduleUrl: string, lang: Lang): Promise<Schedule | null> {\n const base = scheduleUrl.replace(/\\/$/, '');\n const url = `${base}/schedule-${lang}.json`;\n try {\n const init: RequestInit = base === '' ? { credentials: 'omit' } : { credentials: 'omit', mode: 'cors' };\n const res = await fetch(url, init);\n if (!res.ok) return null;\n return (await res.json()) as Schedule;\n } catch {\n return null;\n }\n}\n\nfunction pickQuote(schedule: Schedule): Quote | null {\n const today = todayUtc8();\n const id = schedule.entries[today];\n if (id && schedule.quotes[id]) return schedule.quotes[id];\n const fallbackId = Object.keys(schedule.quotes).sort()[0];\n if (fallbackId && schedule.quotes[fallbackId]) {\n console.warn('[daily-soup] today entry missing or stale, falling back to first quote');\n return schedule.quotes[fallbackId];\n }\n return null;\n}\n\nfunction applyThemeOverrides(card: HTMLElement, config: ThemeConfig, maxWidth?: string) {\n const colors = getThemeColors(config);\n if (colors) {\n if (colors.bg) card.style.setProperty('--ds-bg', colors.bg);\n if (colors.ink) card.style.setProperty('--ds-fg', colors.ink);\n if (colors.muted) card.style.setProperty('--ds-muted', colors.muted);\n if (colors.border) card.style.setProperty('--ds-border', colors.border);\n if (colors.accent) card.style.setProperty('--ds-accent', colors.accent);\n }\n if (maxWidth) card.style.setProperty('--ds-max-width', maxWidth);\n}\n\nexport function mount(host: HTMLElement, options: MountOptions = {}): MountHandle {\n const lang: Lang = options.lang ?? 'zh';\n const themeConfig: ThemeConfig = options.theme ?? 'auto';\n const scheduleUrl = options.scheduleUrl === undefined ? DEFAULT_SCHEDULE_BASE : options.scheduleUrl;\n const maxWidth = options.maxWidth;\n\n let resolvedTheme = resolveTheme(themeConfig);\n const root = attachRoot(host);\n if (root === host) {\n // light DOM fallback \u2014 clear any prior content\n host.textContent = '';\n } else {\n while ((root as ShadowRoot).firstChild) (root as ShadowRoot).removeChild((root as ShadowRoot).firstChild!);\n }\n injectStyles(root);\n\n const card = buildSkeleton(resolvedTheme);\n applyThemeOverrides(card, themeConfig, maxWidth);\n root.appendChild(card);\n\n const state: WidgetState = {\n lang,\n themeConfig,\n scheduleUrl,\n host,\n root,\n cardEl: card,\n unwatchTheme: () => {},\n unwatchVisibility: () => {},\n schedule: null,\n displayedDate: '',\n };\n\n if (themeConfig === 'auto') {\n state.unwatchTheme = watchSystemTheme((t) => {\n resolvedTheme = t;\n state.cardEl.classList.remove('ds-light', 'ds-dark');\n state.cardEl.classList.add(`ds-${t}`);\n });\n }\n\n let cancelled = false;\n let retried = false;\n\n const load = async () => {\n const schedule = await fetchSchedule(scheduleUrl, lang);\n if (cancelled) return;\n if (!schedule) {\n if (!retried) {\n retried = true;\n setTimeout(load, 2000);\n return;\n }\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n state.schedule = schedule;\n const quote = pickQuote(schedule);\n if (!quote) {\n renderError(state.cardEl, lang, resolvedTheme);\n return;\n }\n state.displayedDate = todayUtc8();\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n load();\n\n if (typeof document !== 'undefined') {\n const onVisibility = () => {\n if (document.visibilityState !== 'visible') return;\n if (!state.schedule) return;\n const today = todayUtc8();\n if (today === state.displayedDate) return;\n const quote = pickQuote(state.schedule);\n if (!quote) return;\n state.displayedDate = today;\n renderQuote(state.cardEl, quote, lang, resolvedTheme);\n };\n document.addEventListener('visibilitychange', onVisibility);\n state.unwatchVisibility = () => document.removeEventListener('visibilitychange', onVisibility);\n }\n\n return {\n destroy() {\n cancelled = true;\n state.unwatchTheme();\n state.unwatchVisibility();\n if (root === host) {\n host.textContent = '';\n } else if (host.shadowRoot) {\n while (host.shadowRoot.firstChild) host.shadowRoot.removeChild(host.shadowRoot.firstChild);\n }\n },\n };\n}\n\nexport function mountAll(selector = '[data-daily-soup], #daily-soup'): MountHandle[] {\n if (typeof document === 'undefined') return [];\n const nodes = document.querySelectorAll<HTMLElement>(selector);\n const handles: MountHandle[] = [];\n nodes.forEach((node) => {\n const lang = (node.dataset.lang as Lang | undefined) ?? 'zh';\n const theme = (node.dataset.theme as 'auto' | 'light' | 'dark' | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n const maxWidth = node.dataset.maxWidth;\n handles.push(mount(node, { lang, theme, scheduleUrl, maxWidth }));\n });\n return handles;\n}\n", "import { mountAll } from './widget';\n\ndeclare global {\n interface Window {\n DailySoup?: { mount: typeof import('./widget').mount; mountAll: typeof mountAll };\n }\n}\n\nfunction init() {\n const handles = mountAll();\n if (typeof window !== 'undefined') {\n window.DailySoup = window.DailySoup ?? ({} as Window['DailySoup']);\n // expose mount + mountAll for advanced consumers\n import('./widget').then(({ mount }) => {\n if (window.DailySoup) {\n window.DailySoup.mount = mount;\n window.DailySoup.mountAll = mountAll;\n }\n });\n }\n return handles;\n}\n\nif (typeof document !== 'undefined') {\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', init, { once: true });\n } else {\n init();\n }\n}\n\nexport { mount, mountAll } from './widget';\n"],
5
+ "mappings": "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",
6
+ "names": ["t", "lang", "STRINGS", "init_i18n", "__esmMin", "isThemeColors", "config", "resolveTheme", "getThemeColors", "watchSystemTheme", "cb", "mql", "handler", "e", "init_theme", "__esmMin", "copyToClipboard", "content", "payload", "buildXShareUrl", "text", "url", "SHARE_URL", "buildLineShareUrl", "init_share", "__esmMin", "WIDGET_STYLES", "init_styles", "__esmMin", "todayUtc8", "now", "utc8", "yy", "mm", "dd", "init_date", "__esmMin", "widget_exports", "__export", "mount", "mountAll", "escape", "s", "attachRoot", "host", "injectStyles", "root", "style", "WIDGET_STYLES", "buildSkeleton", "theme", "card", "renderQuote", "quote", "lang", "t", "sourceLabel", "flag", "buildXShareUrl", "buildLineShareUrl", "copyBtn", "copyToClipboard", "label", "originalLabel", "renderError", "fetchSchedule", "scheduleUrl", "base", "url", "res", "pickQuote", "schedule", "today", "todayUtc8", "id", "fallbackId", "applyThemeOverrides", "config", "maxWidth", "colors", "getThemeColors", "options", "themeConfig", "DEFAULT_SCHEDULE_BASE", "resolvedTheme", "resolveTheme", "state", "watchSystemTheme", "cancelled", "retried", "load", "onVisibility", "selector", "nodes", "handles", "node", "init_widget", "__esmMin", "init_i18n", "init_theme", "init_share", "init_styles", "init_date", "embed_exports", "__export", "mount", "mountAll", "init_widget", "init", "handles"]
7
7
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "launchDate": "2026-05-15",
3
- "generatedAt": "2026-05-16T11:30:42.974Z",
3
+ "generatedAt": "2026-05-16T14:47:20.102Z",
4
4
  "lang": "zh",
5
5
  "entries": {
6
6
  "2026-05-15": "0001",
@@ -23,46 +23,46 @@
23
23
  "2026-06-01": "0026",
24
24
  "2026-06-02": "0027",
25
25
  "2026-06-03": "0030",
26
- "2026-06-04": "0001",
27
- "2026-06-05": "0003",
28
- "2026-06-06": "0004",
29
- "2026-06-07": "0005",
30
- "2026-06-08": "0006",
31
- "2026-06-09": "0007",
32
- "2026-06-10": "0008",
33
- "2026-06-11": "0009",
34
- "2026-06-12": "0011",
35
- "2026-06-13": "0012",
36
- "2026-06-14": "0013",
37
- "2026-06-15": "0014",
38
- "2026-06-16": "0016",
39
- "2026-06-17": "0017",
40
- "2026-06-18": "0021",
41
- "2026-06-19": "0022",
42
- "2026-06-20": "0025",
43
- "2026-06-21": "0026",
44
- "2026-06-22": "0027",
45
- "2026-06-23": "0030",
46
- "2026-06-24": "0001",
47
- "2026-06-25": "0003",
48
- "2026-06-26": "0004",
49
- "2026-06-27": "0005",
50
- "2026-06-28": "0006",
51
- "2026-06-29": "0007",
52
- "2026-06-30": "0008",
53
- "2026-07-01": "0009",
54
- "2026-07-02": "0011",
55
- "2026-07-03": "0012",
56
- "2026-07-04": "0013",
57
- "2026-07-05": "0014",
58
- "2026-07-06": "0016",
59
- "2026-07-07": "0017",
60
- "2026-07-08": "0021",
61
- "2026-07-09": "0022",
62
- "2026-07-10": "0025",
63
- "2026-07-11": "0026",
64
- "2026-07-12": "0027",
65
- "2026-07-13": "0030",
26
+ "2026-06-04": "0031",
27
+ "2026-06-05": "0032",
28
+ "2026-06-06": "0033",
29
+ "2026-06-07": "0034",
30
+ "2026-06-08": "0035",
31
+ "2026-06-09": "0036",
32
+ "2026-06-10": "0037",
33
+ "2026-06-11": "0038",
34
+ "2026-06-12": "0039",
35
+ "2026-06-13": "0040",
36
+ "2026-06-14": "0001",
37
+ "2026-06-15": "0003",
38
+ "2026-06-16": "0004",
39
+ "2026-06-17": "0005",
40
+ "2026-06-18": "0006",
41
+ "2026-06-19": "0007",
42
+ "2026-06-20": "0008",
43
+ "2026-06-21": "0009",
44
+ "2026-06-22": "0011",
45
+ "2026-06-23": "0012",
46
+ "2026-06-24": "0013",
47
+ "2026-06-25": "0014",
48
+ "2026-06-26": "0016",
49
+ "2026-06-27": "0017",
50
+ "2026-06-28": "0021",
51
+ "2026-06-29": "0022",
52
+ "2026-06-30": "0025",
53
+ "2026-07-01": "0026",
54
+ "2026-07-02": "0027",
55
+ "2026-07-03": "0030",
56
+ "2026-07-04": "0031",
57
+ "2026-07-05": "0032",
58
+ "2026-07-06": "0033",
59
+ "2026-07-07": "0034",
60
+ "2026-07-08": "0035",
61
+ "2026-07-09": "0036",
62
+ "2026-07-10": "0037",
63
+ "2026-07-11": "0038",
64
+ "2026-07-12": "0039",
65
+ "2026-07-13": "0040",
66
66
  "2026-07-14": "0001",
67
67
  "2026-07-15": "0003",
68
68
  "2026-07-16": "0004",
@@ -83,18 +83,18 @@
83
83
  "2026-07-31": "0026",
84
84
  "2026-08-01": "0027",
85
85
  "2026-08-02": "0030",
86
- "2026-08-03": "0001",
87
- "2026-08-04": "0003",
88
- "2026-08-05": "0004",
89
- "2026-08-06": "0005",
90
- "2026-08-07": "0006",
91
- "2026-08-08": "0007",
92
- "2026-08-09": "0008",
93
- "2026-08-10": "0009",
94
- "2026-08-11": "0011",
95
- "2026-08-12": "0012",
96
- "2026-08-13": "0013",
97
- "2026-08-14": "0014"
86
+ "2026-08-03": "0031",
87
+ "2026-08-04": "0032",
88
+ "2026-08-05": "0033",
89
+ "2026-08-06": "0034",
90
+ "2026-08-07": "0035",
91
+ "2026-08-08": "0036",
92
+ "2026-08-09": "0037",
93
+ "2026-08-10": "0038",
94
+ "2026-08-11": "0039",
95
+ "2026-08-12": "0040",
96
+ "2026-08-13": "0001",
97
+ "2026-08-14": "0003"
98
98
  },
99
99
  "quotes": {
100
100
  "0001": {
@@ -110,7 +110,7 @@
110
110
  "text": "知是行之始,行是知之成。",
111
111
  "author": "王陽明",
112
112
  "source": "《傳習錄·上》",
113
- "sourceUrl": "https://ctext.org/wiki.pl?if=gb&res=86081",
113
+ "sourceUrl": "",
114
114
  "attribution": "verified",
115
115
  "dimension": "action",
116
116
  "style": "classical"
@@ -290,7 +290,7 @@
290
290
  "text": "窮且益堅,不墜青雲之志。",
291
291
  "author": "王勃",
292
292
  "source": "《滕王閣序》",
293
- "sourceUrl": "https://ctext.org/wiki.pl?if=gb&chapter=343050",
293
+ "sourceUrl": "",
294
294
  "attribution": "verified",
295
295
  "dimension": "perseverance",
296
296
  "style": "classical"
@@ -299,7 +299,7 @@
299
299
  "text": "博觀而約取,厚積而薄發。",
300
300
  "author": "蘇軾",
301
301
  "source": "《稼說送張琥》",
302
- "sourceUrl": "https://ctext.org/wiki.pl?if=gb&chapter=596072",
302
+ "sourceUrl": "",
303
303
  "attribution": "verified",
304
304
  "dimension": "learning",
305
305
  "style": "classical"
@@ -1 +1 @@
1
- export declare const WIDGET_STYLES = "\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n";
1
+ export declare const WIDGET_STYLES = "\n :host { all: initial; display: block; font-family: system-ui, -apple-system, \"Segoe UI\", Roboto, \"Noto Sans TC\", sans-serif; }\n * { box-sizing: border-box; }\n .ds-card {\n container-type: inline-size;\n width: 100%;\n max-width: var(--ds-max-width, 32rem);\n margin: 0 auto;\n padding: 1.25rem 1.5rem;\n border-radius: 0.75rem;\n border: 1px solid var(--ds-border);\n background: var(--ds-bg);\n color: var(--ds-fg);\n font-size: clamp(0.875rem, 2.5cqi, 1.25rem);\n line-height: 1.7;\n transition: background 0.2s ease, color 0.2s ease;\n }\n .ds-card.ds-light {\n --ds-bg: #fdfcf7;\n --ds-fg: #1f2933;\n --ds-accent: #5b6b9e;\n --ds-muted: #6b7280;\n --ds-border: #e5e7eb;\n }\n .ds-card.ds-dark {\n --ds-bg: #1a1d24;\n --ds-fg: #e5e7eb;\n --ds-accent: #9aa9d4;\n --ds-muted: #9ca3af;\n --ds-border: #2d323d;\n }\n .ds-quote {\n margin: 0 0 0.875rem;\n font-size: 1.1em;\n font-weight: 500;\n letter-spacing: 0.01em;\n white-space: pre-wrap;\n }\n .ds-quote::before { content: '\\201C'; margin-right: 0.15em; color: var(--ds-accent); }\n .ds-quote::after { content: '\\201D'; margin-left: 0.15em; color: var(--ds-accent); }\n .ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }\n .ds-author { font-weight: 500; color: var(--ds-fg); }\n .ds-source { font-size: 0.95em; }\n .ds-source a { color: var(--ds-accent); text-decoration: none; }\n .ds-source a:hover { text-decoration: underline; }\n .ds-flag { display: inline-block; margin-left: 0.25rem; padding: 0 0.4rem; font-size: 0.75em; border: 1px solid var(--ds-border); border-radius: 9999px; color: var(--ds-muted); }\n .ds-actions { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--ds-border); }\n .ds-share { display: flex; gap: 0.35rem; }\n .ds-btn {\n appearance: none;\n background: transparent;\n color: var(--ds-fg);\n border: 1px solid var(--ds-border);\n border-radius: 0.5rem;\n padding: 0.3rem 0.7rem;\n font-size: 0.85em;\n font-family: inherit;\n cursor: pointer;\n transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;\n text-decoration: none;\n display: inline-flex;\n align-items: center;\n gap: 0.25rem;\n }\n .ds-btn:hover { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }\n .ds-btn.ds-toast { color: var(--ds-accent); border-color: var(--ds-accent); }\n .ds-powered { font-size: 0.75em; color: var(--ds-muted); }\n .ds-powered a { color: var(--ds-muted); text-decoration: none; }\n .ds-powered a:hover { text-decoration: underline; }\n .ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }\n .ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }\n .ds-error { color: var(--ds-muted); font-size: 0.875em; }\n\n @container (max-width: 320px) {\n .ds-card { padding: 1rem 1.1rem; }\n .ds-share-label { display: none; }\n .ds-actions { flex-wrap: wrap; }\n }\n @container (min-width: 500px) {\n .ds-quote { font-size: 1.25em; }\n .ds-meta { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 0.25rem 0.75rem; }\n }\n @container (min-width: 700px) {\n .ds-card { padding: 1.75rem 2rem; }\n .ds-quote { font-size: 1.35em; margin-bottom: 1.125rem; }\n .ds-meta { gap: 0.25rem 1rem; margin-bottom: 1.125rem; }\n .ds-actions { margin-top: 1.125rem; padding-top: 1.125rem; }\n }\n @media (prefers-reduced-motion: reduce) {\n .ds-card, .ds-btn { transition: none; }\n }\n";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "daily-soup-widget",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Embeddable daily quote widget — growth-themed, deterministic, copyright-safe. Drop a script tag or npm install.",
5
5
  "keywords": ["widget", "embed", "daily-quote", "shadow-dom", "react", "umd"],
6
6
  "homepage": "https://daily-soup-widget.vercel.app",
@@ -29,10 +29,12 @@
29
29
  "LICENSE"
30
30
  ],
31
31
  "scripts": {
32
+ "clean": "rm -rf dist",
32
33
  "build:schedule": "tsx scripts/build-schedule.ts",
34
+ "check:source-urls": "tsx scripts/check-source-urls.ts",
33
35
  "build:bundle": "tsx scripts/build-bundle.ts",
34
36
  "build:types": "tsc -p tsconfig.build.json",
35
- "build:lib": "npm run build:schedule && npm run build:bundle && npm run build:types",
37
+ "build:lib": "npm run clean && npm run build:schedule && npm run build:bundle && npm run build:types",
36
38
  "build": "npm run build:lib && next build",
37
39
  "prepublishOnly": "npm run build:lib",
38
40
  "dev": "next dev",
@@ -1,191 +0,0 @@
1
- {
2
- "launchDate": "2026-05-15",
3
- "generatedAt": "2026-05-15T18:27:53.468Z",
4
- "lang": "en",
5
- "entries": {
6
- "2026-05-15": "0002",
7
- "2026-05-16": "0010",
8
- "2026-05-17": "0015",
9
- "2026-05-18": "0018",
10
- "2026-05-19": "0019",
11
- "2026-05-20": "0020",
12
- "2026-05-21": "0023",
13
- "2026-05-22": "0024",
14
- "2026-05-23": "0028",
15
- "2026-05-24": "0029",
16
- "2026-05-25": "0002",
17
- "2026-05-26": "0010",
18
- "2026-05-27": "0015",
19
- "2026-05-28": "0018",
20
- "2026-05-29": "0019",
21
- "2026-05-30": "0020",
22
- "2026-05-31": "0023",
23
- "2026-06-01": "0024",
24
- "2026-06-02": "0028",
25
- "2026-06-03": "0029",
26
- "2026-06-04": "0002",
27
- "2026-06-05": "0010",
28
- "2026-06-06": "0015",
29
- "2026-06-07": "0018",
30
- "2026-06-08": "0019",
31
- "2026-06-09": "0020",
32
- "2026-06-10": "0023",
33
- "2026-06-11": "0024",
34
- "2026-06-12": "0028",
35
- "2026-06-13": "0029",
36
- "2026-06-14": "0002",
37
- "2026-06-15": "0010",
38
- "2026-06-16": "0015",
39
- "2026-06-17": "0018",
40
- "2026-06-18": "0019",
41
- "2026-06-19": "0020",
42
- "2026-06-20": "0023",
43
- "2026-06-21": "0024",
44
- "2026-06-22": "0028",
45
- "2026-06-23": "0029",
46
- "2026-06-24": "0002",
47
- "2026-06-25": "0010",
48
- "2026-06-26": "0015",
49
- "2026-06-27": "0018",
50
- "2026-06-28": "0019",
51
- "2026-06-29": "0020",
52
- "2026-06-30": "0023",
53
- "2026-07-01": "0024",
54
- "2026-07-02": "0028",
55
- "2026-07-03": "0029",
56
- "2026-07-04": "0002",
57
- "2026-07-05": "0010",
58
- "2026-07-06": "0015",
59
- "2026-07-07": "0018",
60
- "2026-07-08": "0019",
61
- "2026-07-09": "0020",
62
- "2026-07-10": "0023",
63
- "2026-07-11": "0024",
64
- "2026-07-12": "0028",
65
- "2026-07-13": "0029",
66
- "2026-07-14": "0002",
67
- "2026-07-15": "0010",
68
- "2026-07-16": "0015",
69
- "2026-07-17": "0018",
70
- "2026-07-18": "0019",
71
- "2026-07-19": "0020",
72
- "2026-07-20": "0023",
73
- "2026-07-21": "0024",
74
- "2026-07-22": "0028",
75
- "2026-07-23": "0029",
76
- "2026-07-24": "0002",
77
- "2026-07-25": "0010",
78
- "2026-07-26": "0015",
79
- "2026-07-27": "0018",
80
- "2026-07-28": "0019",
81
- "2026-07-29": "0020",
82
- "2026-07-30": "0023",
83
- "2026-07-31": "0024",
84
- "2026-08-01": "0028",
85
- "2026-08-02": "0029",
86
- "2026-08-03": "0002",
87
- "2026-08-04": "0010",
88
- "2026-08-05": "0015",
89
- "2026-08-06": "0018",
90
- "2026-08-07": "0019",
91
- "2026-08-08": "0020",
92
- "2026-08-09": "0023",
93
- "2026-08-10": "0024",
94
- "2026-08-11": "0028",
95
- "2026-08-12": "0029",
96
- "2026-08-13": "0002",
97
- "2026-08-14": "0010"
98
- },
99
- "quotes": {
100
- "0002": {
101
- "text": "The beginning is the most important part of the work.",
102
- "author": "Plato",
103
- "source": "Republic, Book II",
104
- "sourceUrl": "https://en.wikisource.org/wiki/The_Republic_of_Plato",
105
- "attribution": "verified",
106
- "dimension": "action",
107
- "style": "classical"
108
- },
109
- "0010": {
110
- "text": "We are what we repeatedly do. Excellence, then, is not an act, but a habit.",
111
- "author": "Aristotle (paraphrase by Will Durant)",
112
- "source": "Nicomachean Ethics, Book II (paraphrase); originated in Durant's The Story of Philosophy",
113
- "sourceUrl": "https://en.wikisource.org/wiki/Nicomachean_Ethics",
114
- "attribution": "popular-attribution",
115
- "dimension": "learning",
116
- "style": "classical"
117
- },
118
- "0015": {
119
- "text": "That which does not kill us makes us stronger.",
120
- "author": "Friedrich Nietzsche",
121
- "source": "Twilight of the Idols (1889)",
122
- "sourceUrl": "https://en.wikisource.org/wiki/Twilight_of_the_Idols",
123
- "attribution": "verified",
124
- "dimension": "perseverance",
125
- "style": "modern"
126
- },
127
- "0018": {
128
- "text": "You have power over your mind — not outside events. Realize this, and you will find strength.",
129
- "author": "Marcus Aurelius",
130
- "source": "Meditations, Book VIII",
131
- "sourceUrl": "https://en.wikisource.org/wiki/Meditations",
132
- "attribution": "verified",
133
- "dimension": "mindset",
134
- "style": "classical"
135
- },
136
- "0019": {
137
- "text": "The happiness of your life depends upon the quality of your thoughts.",
138
- "author": "Marcus Aurelius",
139
- "source": "Meditations",
140
- "sourceUrl": "https://en.wikisource.org/wiki/Meditations",
141
- "attribution": "verified",
142
- "dimension": "mindset",
143
- "style": "classical"
144
- },
145
- "0020": {
146
- "text": "It is not what happens to you, but how you react to it that matters.",
147
- "author": "Epictetus",
148
- "source": "Enchiridion",
149
- "sourceUrl": "https://en.wikisource.org/wiki/Enchiridion",
150
- "attribution": "verified",
151
- "dimension": "mindset",
152
- "style": "classical"
153
- },
154
- "0023": {
155
- "text": "When I let go of what I am, I become what I might be.",
156
- "author": "Lao Tzu (popular English rendering)",
157
- "source": "Tao Te Ching, popular English translation",
158
- "sourceUrl": "",
159
- "attribution": "popular-attribution",
160
- "dimension": "transformation",
161
- "style": "modern"
162
- },
163
- "0024": {
164
- "text": "I am not what happened to me, I am what I choose to become.",
165
- "author": "Carl Jung (popularly attributed)",
166
- "source": "Popularly attributed to Jung",
167
- "sourceUrl": "",
168
- "attribution": "popular-attribution",
169
- "dimension": "transformation",
170
- "style": "modern"
171
- },
172
- "0028": {
173
- "text": "He who has a why to live for can bear almost any how.",
174
- "author": "Friedrich Nietzsche",
175
- "source": "Twilight of the Idols (1889)",
176
- "sourceUrl": "https://en.wikisource.org/wiki/Twilight_of_the_Idols",
177
- "attribution": "verified",
178
- "dimension": "purpose",
179
- "style": "modern"
180
- },
181
- "0029": {
182
- "text": "The two most important days in your life are the day you are born and the day you find out why.",
183
- "author": "Mark Twain (popularly attributed)",
184
- "source": "Popularly attributed; Twain d. 1910, PD globally",
185
- "sourceUrl": "",
186
- "attribution": "popular-attribution",
187
- "dimension": "purpose",
188
- "style": "modern"
189
- }
190
- }
191
- }