daily-soup-widget 0.1.0
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/LICENSE +21 -0
- package/README.md +166 -0
- package/dist/embed.cjs.js +381 -0
- package/dist/embed.cjs.js.map +7 -0
- package/dist/embed.esm.js +358 -0
- package/dist/embed.esm.js.map +7 -0
- package/dist/embed.js +110 -0
- package/dist/embed.js.map +7 -0
- package/dist/schedule-en.json +191 -0
- package/dist/schedule-zh.json +281 -0
- package/dist/types/component.d.ts +2 -0
- package/dist/types/date.d.ts +1 -0
- package/dist/types/embed.d.ts +10 -0
- package/dist/types/i18n.d.ts +14 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/share.d.ts +7 -0
- package/dist/types/styles.d.ts +1 -0
- package/dist/types/theme.d.ts +3 -0
- package/dist/types/types.d.ts +30 -0
- package/dist/types/widget.d.ts +6 -0
- package/package.json +67 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
// src/i18n.ts
|
|
2
|
+
var STRINGS = {
|
|
3
|
+
zh: {
|
|
4
|
+
copy: "\u8907\u88FD",
|
|
5
|
+
copied: "\u5DF2\u8907\u88FD",
|
|
6
|
+
share: "\u5206\u4EAB",
|
|
7
|
+
source: "\u51FA\u8655",
|
|
8
|
+
poweredBy: "\u7531 coco-c.dev \u63D0\u4F9B",
|
|
9
|
+
attributedPopular: "\u50B3\u7D71\u6B78\u5C6C",
|
|
10
|
+
shareX: "\u5206\u4EAB\u5230 X",
|
|
11
|
+
shareLine: "\u5206\u4EAB\u5230 LINE",
|
|
12
|
+
loadFailed: "\u672C\u65E5\u5C0F\u8A9E\u8F09\u5165\u5931\u6557"
|
|
13
|
+
},
|
|
14
|
+
en: {
|
|
15
|
+
copy: "Copy",
|
|
16
|
+
copied: "Copied!",
|
|
17
|
+
share: "Share",
|
|
18
|
+
source: "Source",
|
|
19
|
+
poweredBy: "powered by coco-c.dev",
|
|
20
|
+
attributedPopular: "popularly attributed",
|
|
21
|
+
shareX: "Share on X",
|
|
22
|
+
shareLine: "Share on LINE",
|
|
23
|
+
loadFailed: "Failed to load daily quote"
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
function t(lang) {
|
|
27
|
+
return STRINGS[lang] ?? STRINGS.zh;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/theme.ts
|
|
31
|
+
function resolveTheme(config) {
|
|
32
|
+
if (config === "light" || config === "dark") return config;
|
|
33
|
+
if (typeof window === "undefined" || !window.matchMedia) return "light";
|
|
34
|
+
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
35
|
+
}
|
|
36
|
+
function watchSystemTheme(cb) {
|
|
37
|
+
if (typeof window === "undefined" || !window.matchMedia) return () => {
|
|
38
|
+
};
|
|
39
|
+
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
|
40
|
+
const handler = (e) => cb(e.matches ? "dark" : "light");
|
|
41
|
+
mql.addEventListener("change", handler);
|
|
42
|
+
return () => mql.removeEventListener("change", handler);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// src/share.ts
|
|
46
|
+
var SHARE_URL = "https://daily-soup-widget.vercel.app";
|
|
47
|
+
async function copyToClipboard(content) {
|
|
48
|
+
const payload = `${content.text} \u2014 ${content.author}`;
|
|
49
|
+
if (typeof navigator !== "undefined" && navigator.clipboard) {
|
|
50
|
+
try {
|
|
51
|
+
await navigator.clipboard.writeText(payload);
|
|
52
|
+
return true;
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
function buildXShareUrl(content) {
|
|
60
|
+
const text = encodeURIComponent(`${content.text} \u2014 ${content.author}`);
|
|
61
|
+
const url = encodeURIComponent(SHARE_URL);
|
|
62
|
+
return `https://twitter.com/intent/tweet?text=${text}&url=${url}`;
|
|
63
|
+
}
|
|
64
|
+
function buildLineShareUrl(content) {
|
|
65
|
+
const url = encodeURIComponent(`${SHARE_URL} \u2014 ${content.text}`);
|
|
66
|
+
return `https://social-plugins.line.me/lineit/share?url=${url}`;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/styles.ts
|
|
70
|
+
var WIDGET_STYLES = `
|
|
71
|
+
:host { all: initial; display: block; font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans TC", sans-serif; }
|
|
72
|
+
* { box-sizing: border-box; }
|
|
73
|
+
.ds-card {
|
|
74
|
+
container-type: inline-size;
|
|
75
|
+
width: 100%;
|
|
76
|
+
max-width: 32rem;
|
|
77
|
+
margin: 0 auto;
|
|
78
|
+
padding: 1.25rem 1.5rem;
|
|
79
|
+
border-radius: 0.75rem;
|
|
80
|
+
border: 1px solid var(--ds-border);
|
|
81
|
+
background: var(--ds-bg);
|
|
82
|
+
color: var(--ds-fg);
|
|
83
|
+
font-size: clamp(0.875rem, 2.5cqi, 1.125rem);
|
|
84
|
+
line-height: 1.7;
|
|
85
|
+
transition: background 0.2s ease, color 0.2s ease;
|
|
86
|
+
}
|
|
87
|
+
.ds-card.ds-light {
|
|
88
|
+
--ds-bg: #fdfcf7;
|
|
89
|
+
--ds-fg: #1f2933;
|
|
90
|
+
--ds-accent: #5b6b9e;
|
|
91
|
+
--ds-muted: #6b7280;
|
|
92
|
+
--ds-border: #e5e7eb;
|
|
93
|
+
}
|
|
94
|
+
.ds-card.ds-dark {
|
|
95
|
+
--ds-bg: #1a1d24;
|
|
96
|
+
--ds-fg: #e5e7eb;
|
|
97
|
+
--ds-accent: #9aa9d4;
|
|
98
|
+
--ds-muted: #9ca3af;
|
|
99
|
+
--ds-border: #2d323d;
|
|
100
|
+
}
|
|
101
|
+
.ds-quote {
|
|
102
|
+
margin: 0 0 0.875rem;
|
|
103
|
+
font-size: 1.1em;
|
|
104
|
+
font-weight: 500;
|
|
105
|
+
letter-spacing: 0.01em;
|
|
106
|
+
white-space: pre-wrap;
|
|
107
|
+
}
|
|
108
|
+
.ds-quote::before { content: '\\201C'; margin-right: 0.15em; color: var(--ds-accent); }
|
|
109
|
+
.ds-quote::after { content: '\\201D'; margin-left: 0.15em; color: var(--ds-accent); }
|
|
110
|
+
.ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }
|
|
111
|
+
.ds-author { font-weight: 500; color: var(--ds-fg); }
|
|
112
|
+
.ds-source { font-size: 0.95em; }
|
|
113
|
+
.ds-source a { color: var(--ds-accent); text-decoration: none; }
|
|
114
|
+
.ds-source a:hover { text-decoration: underline; }
|
|
115
|
+
.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); }
|
|
116
|
+
.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); }
|
|
117
|
+
.ds-share { display: flex; gap: 0.35rem; }
|
|
118
|
+
.ds-btn {
|
|
119
|
+
appearance: none;
|
|
120
|
+
background: transparent;
|
|
121
|
+
color: var(--ds-fg);
|
|
122
|
+
border: 1px solid var(--ds-border);
|
|
123
|
+
border-radius: 0.5rem;
|
|
124
|
+
padding: 0.3rem 0.7rem;
|
|
125
|
+
font-size: 0.85em;
|
|
126
|
+
font-family: inherit;
|
|
127
|
+
cursor: pointer;
|
|
128
|
+
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
|
129
|
+
text-decoration: none;
|
|
130
|
+
display: inline-flex;
|
|
131
|
+
align-items: center;
|
|
132
|
+
gap: 0.25rem;
|
|
133
|
+
}
|
|
134
|
+
.ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
|
|
135
|
+
.ds-btn:focus-visible { outline: 2px solid var(--ds-accent); outline-offset: 2px; }
|
|
136
|
+
.ds-btn.ds-toast { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
|
|
137
|
+
.ds-powered { font-size: 0.75em; color: var(--ds-muted); }
|
|
138
|
+
.ds-powered a { color: var(--ds-muted); text-decoration: none; }
|
|
139
|
+
.ds-powered a:hover { text-decoration: underline; }
|
|
140
|
+
.ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }
|
|
141
|
+
.ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }
|
|
142
|
+
.ds-error { color: var(--ds-muted); font-size: 0.875em; }
|
|
143
|
+
|
|
144
|
+
@container (max-width: 320px) {
|
|
145
|
+
.ds-card { padding: 1rem 1.1rem; }
|
|
146
|
+
.ds-share-label { display: none; }
|
|
147
|
+
.ds-actions { flex-wrap: wrap; }
|
|
148
|
+
}
|
|
149
|
+
@container (min-width: 500px) {
|
|
150
|
+
.ds-quote { font-size: 1.25em; }
|
|
151
|
+
}
|
|
152
|
+
@media (prefers-reduced-motion: reduce) {
|
|
153
|
+
.ds-card, .ds-btn { transition: none; }
|
|
154
|
+
}
|
|
155
|
+
`;
|
|
156
|
+
|
|
157
|
+
// src/date.ts
|
|
158
|
+
function todayUtc8(now = /* @__PURE__ */ new Date()) {
|
|
159
|
+
const utc8 = new Date(now.getTime() + 8 * 60 * 60 * 1e3);
|
|
160
|
+
const yy = utc8.getUTCFullYear();
|
|
161
|
+
const mm = String(utc8.getUTCMonth() + 1).padStart(2, "0");
|
|
162
|
+
const dd = String(utc8.getUTCDate()).padStart(2, "0");
|
|
163
|
+
return `${yy}-${mm}-${dd}`;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// src/widget.ts
|
|
167
|
+
var DEFAULT_SCHEDULE_BASE = "https://daily-soup-widget.vercel.app";
|
|
168
|
+
function escape(s) {
|
|
169
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
170
|
+
}
|
|
171
|
+
function attachRoot(host) {
|
|
172
|
+
if (typeof host.attachShadow === "function") {
|
|
173
|
+
if (host.shadowRoot) return host.shadowRoot;
|
|
174
|
+
return host.attachShadow({ mode: "open" });
|
|
175
|
+
}
|
|
176
|
+
console.warn("[daily-soup] attachShadow unsupported, falling back to light DOM");
|
|
177
|
+
return host;
|
|
178
|
+
}
|
|
179
|
+
function injectStyles(root) {
|
|
180
|
+
const style = document.createElement("style");
|
|
181
|
+
style.textContent = WIDGET_STYLES;
|
|
182
|
+
root.appendChild(style);
|
|
183
|
+
}
|
|
184
|
+
function buildSkeleton(theme) {
|
|
185
|
+
const card = document.createElement("div");
|
|
186
|
+
card.className = `ds-card ds-${theme} ds-skeleton`;
|
|
187
|
+
card.innerHTML = `
|
|
188
|
+
<div class="ds-quote"> </div>
|
|
189
|
+
<div class="ds-meta"><span class="ds-author"> </span><span class="ds-source"> </span></div>
|
|
190
|
+
`;
|
|
191
|
+
return card;
|
|
192
|
+
}
|
|
193
|
+
function renderQuote(card, quote, lang, theme) {
|
|
194
|
+
const s = t(lang);
|
|
195
|
+
card.className = `ds-card ds-${theme}`;
|
|
196
|
+
const sourceLabel = quote.sourceUrl ? `<a href="${escape(quote.sourceUrl)}" target="_blank" rel="noopener noreferrer">${escape(quote.source)}</a>` : escape(quote.source);
|
|
197
|
+
const flag = quote.attribution === "popular-attribution" ? `<span class="ds-flag">${escape(s.attributedPopular)}</span>` : "";
|
|
198
|
+
card.innerHTML = `
|
|
199
|
+
<p class="ds-quote">${escape(quote.text)}</p>
|
|
200
|
+
<div class="ds-meta">
|
|
201
|
+
<span class="ds-author">\u2014 ${escape(quote.author)}${flag}</span>
|
|
202
|
+
${quote.source ? `<span class="ds-source">${s.source}\uFF1A${sourceLabel}</span>` : ""}
|
|
203
|
+
</div>
|
|
204
|
+
<div class="ds-actions">
|
|
205
|
+
<div class="ds-share">
|
|
206
|
+
<button class="ds-btn" data-action="copy" type="button" aria-label="${escape(s.copy)}">
|
|
207
|
+
<span aria-hidden="true">\u29C9</span><span class="ds-share-label">${escape(s.copy)}</span>
|
|
208
|
+
</button>
|
|
209
|
+
<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)}">
|
|
210
|
+
<span aria-hidden="true">\u{1D54F}</span><span class="ds-share-label">X</span>
|
|
211
|
+
</a>
|
|
212
|
+
<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)}">
|
|
213
|
+
<span aria-hidden="true">L</span><span class="ds-share-label">LINE</span>
|
|
214
|
+
</a>
|
|
215
|
+
</div>
|
|
216
|
+
<span class="ds-powered"><a href="https://coco-c.dev" target="_blank" rel="noopener noreferrer">${s.poweredBy}</a></span>
|
|
217
|
+
</div>
|
|
218
|
+
`;
|
|
219
|
+
const copyBtn = card.querySelector('[data-action="copy"]');
|
|
220
|
+
if (copyBtn) {
|
|
221
|
+
copyBtn.addEventListener("click", async () => {
|
|
222
|
+
const ok = await copyToClipboard({ text: quote.text, author: quote.author });
|
|
223
|
+
if (ok) {
|
|
224
|
+
const label = copyBtn.querySelector(".ds-share-label");
|
|
225
|
+
const originalLabel = label?.textContent ?? "";
|
|
226
|
+
if (label) label.textContent = s.copied;
|
|
227
|
+
copyBtn.classList.add("ds-toast");
|
|
228
|
+
setTimeout(() => {
|
|
229
|
+
if (label) label.textContent = originalLabel;
|
|
230
|
+
copyBtn.classList.remove("ds-toast");
|
|
231
|
+
}, 2e3);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
function renderError(card, lang, theme) {
|
|
237
|
+
card.className = `ds-card ds-${theme}`;
|
|
238
|
+
const s = t(lang);
|
|
239
|
+
card.innerHTML = `<p class="ds-error">${escape(s.loadFailed)}</p>`;
|
|
240
|
+
}
|
|
241
|
+
async function fetchSchedule(scheduleUrl, lang) {
|
|
242
|
+
const base = scheduleUrl.replace(/\/$/, "");
|
|
243
|
+
const url = `${base}/schedule-${lang}.json`;
|
|
244
|
+
try {
|
|
245
|
+
const init = base === "" ? { credentials: "omit" } : { credentials: "omit", mode: "cors" };
|
|
246
|
+
const res = await fetch(url, init);
|
|
247
|
+
if (!res.ok) return null;
|
|
248
|
+
return await res.json();
|
|
249
|
+
} catch {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function pickQuote(schedule) {
|
|
254
|
+
const today = todayUtc8();
|
|
255
|
+
const id = schedule.entries[today];
|
|
256
|
+
if (id && schedule.quotes[id]) return schedule.quotes[id];
|
|
257
|
+
const fallbackId = Object.keys(schedule.quotes).sort()[0];
|
|
258
|
+
if (fallbackId && schedule.quotes[fallbackId]) {
|
|
259
|
+
console.warn("[daily-soup] today entry missing or stale, falling back to first quote");
|
|
260
|
+
return schedule.quotes[fallbackId];
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
function mount(host, options = {}) {
|
|
265
|
+
const lang = options.lang ?? "zh";
|
|
266
|
+
const themeConfig = options.theme ?? "auto";
|
|
267
|
+
const scheduleUrl = options.scheduleUrl === void 0 ? DEFAULT_SCHEDULE_BASE : options.scheduleUrl;
|
|
268
|
+
let resolvedTheme = resolveTheme(themeConfig);
|
|
269
|
+
const root = attachRoot(host);
|
|
270
|
+
if (root === host) {
|
|
271
|
+
host.textContent = "";
|
|
272
|
+
} else {
|
|
273
|
+
while (root.firstChild) root.removeChild(root.firstChild);
|
|
274
|
+
}
|
|
275
|
+
injectStyles(root);
|
|
276
|
+
const card = buildSkeleton(resolvedTheme);
|
|
277
|
+
root.appendChild(card);
|
|
278
|
+
const state = {
|
|
279
|
+
lang,
|
|
280
|
+
themeConfig,
|
|
281
|
+
scheduleUrl,
|
|
282
|
+
host,
|
|
283
|
+
root,
|
|
284
|
+
cardEl: card,
|
|
285
|
+
unwatchTheme: () => {
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
if (themeConfig === "auto") {
|
|
289
|
+
state.unwatchTheme = watchSystemTheme((t2) => {
|
|
290
|
+
resolvedTheme = t2;
|
|
291
|
+
state.cardEl.classList.remove("ds-light", "ds-dark");
|
|
292
|
+
state.cardEl.classList.add(`ds-${t2}`);
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
let cancelled = false;
|
|
296
|
+
let retried = false;
|
|
297
|
+
const load = async () => {
|
|
298
|
+
const schedule = await fetchSchedule(scheduleUrl, lang);
|
|
299
|
+
if (cancelled) return;
|
|
300
|
+
if (!schedule) {
|
|
301
|
+
if (!retried) {
|
|
302
|
+
retried = true;
|
|
303
|
+
setTimeout(load, 2e3);
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
renderError(state.cardEl, lang, resolvedTheme);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
const quote = pickQuote(schedule);
|
|
310
|
+
if (!quote) {
|
|
311
|
+
renderError(state.cardEl, lang, resolvedTheme);
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
renderQuote(state.cardEl, quote, lang, resolvedTheme);
|
|
315
|
+
};
|
|
316
|
+
load();
|
|
317
|
+
return {
|
|
318
|
+
destroy() {
|
|
319
|
+
cancelled = true;
|
|
320
|
+
state.unwatchTheme();
|
|
321
|
+
if (root === host) {
|
|
322
|
+
host.textContent = "";
|
|
323
|
+
} else if (host.shadowRoot) {
|
|
324
|
+
while (host.shadowRoot.firstChild) host.shadowRoot.removeChild(host.shadowRoot.firstChild);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
function mountAll(selector = "[data-daily-soup], #daily-soup") {
|
|
330
|
+
if (typeof document === "undefined") return [];
|
|
331
|
+
const nodes = document.querySelectorAll(selector);
|
|
332
|
+
const handles = [];
|
|
333
|
+
nodes.forEach((node) => {
|
|
334
|
+
const lang = node.dataset.lang ?? "zh";
|
|
335
|
+
const theme = node.dataset.theme ?? "auto";
|
|
336
|
+
const scheduleUrl = node.dataset.scheduleUrl;
|
|
337
|
+
handles.push(mount(node, { lang, theme, scheduleUrl }));
|
|
338
|
+
});
|
|
339
|
+
return handles;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// src/component.tsx
|
|
343
|
+
import { useEffect, useRef } from "react";
|
|
344
|
+
function DailySoup({ lang = "zh", theme = "auto", scheduleUrl, className }) {
|
|
345
|
+
const hostRef = useRef(null);
|
|
346
|
+
useEffect(() => {
|
|
347
|
+
if (!hostRef.current) return;
|
|
348
|
+
const handle = mount(hostRef.current, { lang, theme, scheduleUrl });
|
|
349
|
+
return () => handle.destroy();
|
|
350
|
+
}, [lang, theme, scheduleUrl]);
|
|
351
|
+
return /* @__PURE__ */ React.createElement("div", { ref: hostRef, className, "data-daily-soup-host": "" });
|
|
352
|
+
}
|
|
353
|
+
export {
|
|
354
|
+
DailySoup,
|
|
355
|
+
mount,
|
|
356
|
+
mountAll
|
|
357
|
+
};
|
|
358
|
+
//# sourceMappingURL=embed.esm.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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 coco-c.dev \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 en: {\n copy: 'Copy',\n copied: 'Copied!',\n share: 'Share',\n source: 'Source',\n poweredBy: 'powered by coco-c.dev',\n attributedPopular: 'popularly attributed',\n shareX: 'Share on X',\n shareLine: 'Share on LINE',\n loadFailed: 'Failed to load daily quote',\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 } from './types';\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\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 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: 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.125rem);\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 }\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 } 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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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\"> </div>\n <div class=\"ds-meta\"><span class=\"ds-author\"> </span><span class=\"ds-source\"> </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://coco-c.dev\" 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\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\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 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 ThemeConfig | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n handles.push(mount(node, { lang, theme, scheduleUrl }));\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 }: DailySoupProps) {\n const hostRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n if (!hostRef.current) return;\n const handle = mount(hostRef.current, { lang, theme, scheduleUrl });\n return () => handle.destroy();\n }, [lang, theme, scheduleUrl]);\n\n return <div ref={hostRef} className={className} data-daily-soup-host=\"\" />;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["t"]
|
|
7
|
+
}
|
package/dist/embed.js
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";var DailySoup=(()=>{var b=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var B=Object.prototype.hasOwnProperty;var u=(e,t)=>()=>(e&&(t=e(e=0)),t);var S=(e,t)=>{for(var n in t)b(e,n,{get:t[n],enumerable:!0})},F=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of N(t))!B.call(e,r)&&r!==n&&b(e,r,{get:()=>t[r],enumerable:!(o=_(t,r))||o.enumerable});return e};var P=e=>F(b({},"__esModule",{value:!0}),e);function y(e){return x[e]??x.zh}var x,T=u(()=>{"use strict";x={zh:{copy:"\u8907\u88FD",copied:"\u5DF2\u8907\u88FD",share:"\u5206\u4EAB",source:"\u51FA\u8655",poweredBy:"\u7531 coco-c.dev \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"},en:{copy:"Copy",copied:"Copied!",share:"Share",source:"Source",poweredBy:"powered by coco-c.dev",attributedPopular:"popularly attributed",shareX:"Share on X",shareLine:"Share on LINE",loadFailed:"Failed to load daily quote"}}});function L(e){return e==="light"||e==="dark"?e:typeof window>"u"||!window.matchMedia?"light":window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}function C(e){if(typeof window>"u"||!window.matchMedia)return()=>{};let t=window.matchMedia("(prefers-color-scheme: dark)"),n=o=>e(o.matches?"dark":"light");return t.addEventListener("change",n),()=>t.removeEventListener("change",n)}var E=u(()=>{"use strict"});async function k(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 M(e){let t=encodeURIComponent(`${e.text} \u2014 ${e.author}`),n=encodeURIComponent($);return`https://twitter.com/intent/tweet?text=${t}&url=${n}`}function R(e){return`https://social-plugins.line.me/lineit/share?url=${encodeURIComponent(`${$} \u2014 ${e.text}`)}`}var $,U=u(()=>{"use strict";$="https://daily-soup-widget.vercel.app"});var H,D=u(()=>{"use strict";H=`
|
|
2
|
+
:host { all: initial; display: block; font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Noto Sans TC", sans-serif; }
|
|
3
|
+
* { box-sizing: border-box; }
|
|
4
|
+
.ds-card {
|
|
5
|
+
container-type: inline-size;
|
|
6
|
+
width: 100%;
|
|
7
|
+
max-width: 32rem;
|
|
8
|
+
margin: 0 auto;
|
|
9
|
+
padding: 1.25rem 1.5rem;
|
|
10
|
+
border-radius: 0.75rem;
|
|
11
|
+
border: 1px solid var(--ds-border);
|
|
12
|
+
background: var(--ds-bg);
|
|
13
|
+
color: var(--ds-fg);
|
|
14
|
+
font-size: clamp(0.875rem, 2.5cqi, 1.125rem);
|
|
15
|
+
line-height: 1.7;
|
|
16
|
+
transition: background 0.2s ease, color 0.2s ease;
|
|
17
|
+
}
|
|
18
|
+
.ds-card.ds-light {
|
|
19
|
+
--ds-bg: #fdfcf7;
|
|
20
|
+
--ds-fg: #1f2933;
|
|
21
|
+
--ds-accent: #5b6b9e;
|
|
22
|
+
--ds-muted: #6b7280;
|
|
23
|
+
--ds-border: #e5e7eb;
|
|
24
|
+
}
|
|
25
|
+
.ds-card.ds-dark {
|
|
26
|
+
--ds-bg: #1a1d24;
|
|
27
|
+
--ds-fg: #e5e7eb;
|
|
28
|
+
--ds-accent: #9aa9d4;
|
|
29
|
+
--ds-muted: #9ca3af;
|
|
30
|
+
--ds-border: #2d323d;
|
|
31
|
+
}
|
|
32
|
+
.ds-quote {
|
|
33
|
+
margin: 0 0 0.875rem;
|
|
34
|
+
font-size: 1.1em;
|
|
35
|
+
font-weight: 500;
|
|
36
|
+
letter-spacing: 0.01em;
|
|
37
|
+
white-space: pre-wrap;
|
|
38
|
+
}
|
|
39
|
+
.ds-quote::before { content: '\\201C'; margin-right: 0.15em; color: var(--ds-accent); }
|
|
40
|
+
.ds-quote::after { content: '\\201D'; margin-left: 0.15em; color: var(--ds-accent); }
|
|
41
|
+
.ds-meta { display: flex; flex-direction: column; gap: 0.15rem; margin-bottom: 0.875rem; font-size: 0.875em; color: var(--ds-muted); }
|
|
42
|
+
.ds-author { font-weight: 500; color: var(--ds-fg); }
|
|
43
|
+
.ds-source { font-size: 0.95em; }
|
|
44
|
+
.ds-source a { color: var(--ds-accent); text-decoration: none; }
|
|
45
|
+
.ds-source a:hover { text-decoration: underline; }
|
|
46
|
+
.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); }
|
|
47
|
+
.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); }
|
|
48
|
+
.ds-share { display: flex; gap: 0.35rem; }
|
|
49
|
+
.ds-btn {
|
|
50
|
+
appearance: none;
|
|
51
|
+
background: transparent;
|
|
52
|
+
color: var(--ds-fg);
|
|
53
|
+
border: 1px solid var(--ds-border);
|
|
54
|
+
border-radius: 0.5rem;
|
|
55
|
+
padding: 0.3rem 0.7rem;
|
|
56
|
+
font-size: 0.85em;
|
|
57
|
+
font-family: inherit;
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
|
|
60
|
+
text-decoration: none;
|
|
61
|
+
display: inline-flex;
|
|
62
|
+
align-items: center;
|
|
63
|
+
gap: 0.25rem;
|
|
64
|
+
}
|
|
65
|
+
.ds-btn:hover { background: var(--ds-accent); color: var(--ds-bg); border-color: var(--ds-accent); }
|
|
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); }
|
|
68
|
+
.ds-powered { font-size: 0.75em; color: var(--ds-muted); }
|
|
69
|
+
.ds-powered a { color: var(--ds-muted); text-decoration: none; }
|
|
70
|
+
.ds-powered a:hover { text-decoration: underline; }
|
|
71
|
+
.ds-skeleton .ds-quote { background: var(--ds-border); border-radius: 0.25rem; color: transparent; }
|
|
72
|
+
.ds-skeleton .ds-quote::before, .ds-skeleton .ds-quote::after { content: ''; }
|
|
73
|
+
.ds-error { color: var(--ds-muted); font-size: 0.875em; }
|
|
74
|
+
|
|
75
|
+
@container (max-width: 320px) {
|
|
76
|
+
.ds-card { padding: 1rem 1.1rem; }
|
|
77
|
+
.ds-share-label { display: none; }
|
|
78
|
+
.ds-actions { flex-wrap: wrap; }
|
|
79
|
+
}
|
|
80
|
+
@container (min-width: 500px) {
|
|
81
|
+
.ds-quote { font-size: 1.25em; }
|
|
82
|
+
}
|
|
83
|
+
@media (prefers-reduced-motion: reduce) {
|
|
84
|
+
.ds-card, .ds-btn { transition: none; }
|
|
85
|
+
}
|
|
86
|
+
`});function z(e=new Date){let t=new Date(e.getTime()+288e5),n=t.getUTCFullYear(),o=String(t.getUTCMonth()+1).padStart(2,"0"),r=String(t.getUTCDate()).padStart(2,"0");return`${n}-${o}-${r}`}var I=u(()=>{"use strict"});var A={};S(A,{mount:()=>f,mountAll:()=>p});function a(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function W(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 j(e){let t=document.createElement("style");t.textContent=H,e.appendChild(t)}function O(e){let t=document.createElement("div");return t.className=`ds-card ds-${e} ds-skeleton`,t.innerHTML=`
|
|
87
|
+
<div class="ds-quote"> </div>
|
|
88
|
+
<div class="ds-meta"><span class="ds-author"> </span><span class="ds-source"> </span></div>
|
|
89
|
+
`,t}function G(e,t,n,o){let r=y(n);e.className=`ds-card ds-${o}`;let s=t.sourceUrl?`<a href="${a(t.sourceUrl)}" target="_blank" rel="noopener noreferrer">${a(t.source)}</a>`:a(t.source),d=t.attribution==="popular-attribution"?`<span class="ds-flag">${a(r.attributedPopular)}</span>`:"";e.innerHTML=`
|
|
90
|
+
<p class="ds-quote">${a(t.text)}</p>
|
|
91
|
+
<div class="ds-meta">
|
|
92
|
+
<span class="ds-author">\u2014 ${a(t.author)}${d}</span>
|
|
93
|
+
${t.source?`<span class="ds-source">${r.source}\uFF1A${s}</span>`:""}
|
|
94
|
+
</div>
|
|
95
|
+
<div class="ds-actions">
|
|
96
|
+
<div class="ds-share">
|
|
97
|
+
<button class="ds-btn" data-action="copy" type="button" aria-label="${a(r.copy)}">
|
|
98
|
+
<span aria-hidden="true">\u29C9</span><span class="ds-share-label">${a(r.copy)}</span>
|
|
99
|
+
</button>
|
|
100
|
+
<a class="ds-btn" data-action="x" href="${a(M({text:t.text,author:t.author}))}" target="_blank" rel="noopener noreferrer" aria-label="${a(r.shareX)}">
|
|
101
|
+
<span aria-hidden="true">\u{1D54F}</span><span class="ds-share-label">X</span>
|
|
102
|
+
</a>
|
|
103
|
+
<a class="ds-btn" data-action="line" href="${a(R({text:t.text,author:t.author}))}" target="_blank" rel="noopener noreferrer" aria-label="${a(r.shareLine)}">
|
|
104
|
+
<span aria-hidden="true">L</span><span class="ds-share-label">LINE</span>
|
|
105
|
+
</a>
|
|
106
|
+
</div>
|
|
107
|
+
<span class="ds-powered"><a href="https://coco-c.dev" target="_blank" rel="noopener noreferrer">${r.poweredBy}</a></span>
|
|
108
|
+
</div>
|
|
109
|
+
`;let i=e.querySelector('[data-action="copy"]');i&&i.addEventListener("click",async()=>{if(await k({text:t.text,author:t.author})){let c=i.querySelector(".ds-share-label"),h=c?.textContent??"";c&&(c.textContent=r.copied),i.classList.add("ds-toast"),setTimeout(()=>{c&&(c.textContent=h),i.classList.remove("ds-toast")},2e3)}})}function q(e,t,n){e.className=`ds-card ds-${n}`;let o=y(t);e.innerHTML=`<p class="ds-error">${a(o.loadFailed)}</p>`}async function Y(e,t){let n=e.replace(/\/$/,""),o=`${n}/schedule-${t}.json`;try{let s=await fetch(o,n===""?{credentials:"omit"}:{credentials:"omit",mode:"cors"});return s.ok?await s.json():null}catch{return null}}function J(e){let t=z(),n=e.entries[t];if(n&&e.quotes[n])return e.quotes[n];let o=Object.keys(e.quotes).sort()[0];return o&&e.quotes[o]?(console.warn("[daily-soup] today entry missing or stale, falling back to first quote"),e.quotes[o]):null}function f(e,t={}){let n=t.lang??"zh",o=t.theme??"auto",r=t.scheduleUrl===void 0?Q:t.scheduleUrl,s=L(o),d=W(e);if(d===e)e.textContent="";else for(;d.firstChild;)d.removeChild(d.firstChild);j(d);let i=O(s);d.appendChild(i);let l={lang:n,themeConfig:o,scheduleUrl:r,host:e,root:d,cardEl:i,unwatchTheme:()=>{}};o==="auto"&&(l.unwatchTheme=C(m=>{s=m,l.cardEl.classList.remove("ds-light","ds-dark"),l.cardEl.classList.add(`ds-${m}`)}));let c=!1,h=!1,w=async()=>{let m=await Y(r,n);if(c)return;if(!m){if(!h){h=!0,setTimeout(w,2e3);return}q(l.cardEl,n,s);return}let v=J(m);if(!v){q(l.cardEl,n,s);return}G(l.cardEl,v,n,s)};return w(),{destroy(){if(c=!0,l.unwatchTheme(),d===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(o=>{let r=o.dataset.lang??"zh",s=o.dataset.theme??"auto",d=o.dataset.scheduleUrl;n.push(f(o,{lang:r,theme:s,scheduleUrl:d}))}),n}var Q,g=u(()=>{"use strict";T();E();U();D();I();Q="https://daily-soup-widget.vercel.app"});var K={};S(K,{mount:()=>f,mountAll:()=>p});g();g();function X(){let e=p();return typeof window<"u"&&(window.DailySoup=window.DailySoup??{},Promise.resolve().then(()=>(g(),A)).then(({mount:t})=>{window.DailySoup&&(window.DailySoup.mount=t,window.DailySoup.mountAll=p)})),e}typeof document<"u"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",X,{once:!0}):X());return P(K);})();
|
|
110
|
+
//# sourceMappingURL=embed.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 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 coco-c.dev \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 en: {\n copy: 'Copy',\n copied: 'Copied!',\n share: 'Share',\n source: 'Source',\n poweredBy: 'powered by coco-c.dev',\n attributedPopular: 'popularly attributed',\n shareX: 'Share on X',\n shareLine: 'Share on LINE',\n loadFailed: 'Failed to load daily quote',\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 } from './types';\n\nexport function resolveTheme(config: ThemeConfig): ResolvedTheme {\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 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: 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.125rem);\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 }\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 } 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, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\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\"> </div>\n <div class=\"ds-meta\"><span class=\"ds-author\"> </span><span class=\"ds-source\"> </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://coco-c.dev\" 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\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\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 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 ThemeConfig | undefined) ?? 'auto';\n const scheduleUrl = node.dataset.scheduleUrl;\n handles.push(mount(node, { lang, theme, scheduleUrl }));\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", "resolveTheme", "config", "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", "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"]
|
|
7
|
+
}
|