koishi-plugin-dew-bot 1.0.242 → 1.0.243
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/lib/index.js +25 -19
- package/lib/plugin/appearanceCardTemplate.d.ts +2 -2
- package/lib/plugin/skillCardTemplate.d.ts +2 -1
- package/package.json +1 -1
- package/src/plugin/appearanceCardTemplate.ts +10 -10
- package/src/plugin/cardLayout.ts +2 -0
- package/src/plugin/serverHandel/image.ts +0 -1
- package/src/plugin/skillCard.ts +1 -1
- package/src/plugin/skillCardTemplate.ts +20 -11
package/lib/index.js
CHANGED
|
@@ -77,16 +77,16 @@ var AnalysisMsg = class {
|
|
|
77
77
|
|
|
78
78
|
// src/plugin/appearanceCardTemplate.ts
|
|
79
79
|
var escape = /* @__PURE__ */ __name((value) => String(value ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]), "escape");
|
|
80
|
-
function appearanceCardHtml(card, artwork,
|
|
81
|
-
const slice = /* @__PURE__ */ __name((y, height) => `<svg class="frame" viewBox="0 ${y} 760 ${height}" preserveAspectRatio="none" aria-hidden="true"><image href="${escape(frame2)}" width="760" height="1107" preserveAspectRatio="none"/></svg>`, "slice");
|
|
80
|
+
function appearanceCardHtml(card, artwork, paper) {
|
|
82
81
|
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>
|
|
83
|
-
*{box-sizing:border-box}html,body{margin:0;width:760px;font-family:'Microsoft YaHei','Noto Sans CJK SC',sans-serif
|
|
84
|
-
#capture{width:760px
|
|
85
|
-
.
|
|
86
|
-
.
|
|
87
|
-
.
|
|
88
|
-
.
|
|
89
|
-
|
|
82
|
+
*{box-sizing:border-box}html,body{margin:0;width:760px;background:#ece8df;color:#625a49;font-family:'Microsoft YaHei','Noto Sans CJK SC',sans-serif}
|
|
83
|
+
#capture{width:760px;padding:25px 18px 29px;background:radial-gradient(ellipse at center,#f6f2e9,#e4ded2)}
|
|
84
|
+
.scroll{position:relative;padding:18px 0}.sheet{position:relative;margin:0 29px;padding:0 23px;background:#eee5cf;border-left:1px solid #b8a37b;border-right:1px solid #b8a37b;box-shadow:0 7px 16px #49381c24;overflow:hidden}
|
|
85
|
+
.paper{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.22;pointer-events:none}.sheet:after{content:'';position:absolute;inset:0;pointer-events:none;box-shadow:inset 0 18px 20px -18px #49351cb0,inset 0 -18px 20px -18px #49351c90}
|
|
86
|
+
.title{position:relative;margin:0;padding:29px 0 23px;text-align:center;font-family:'KaiTi','STKaiti','SimSun',serif;font-size:34px;font-weight:400;line-height:1.4;letter-spacing:8px;color:#514630}.portrait{position:relative;padding:5px;border:1px solid #ae9360;background:#e8dec5}.item-artwork{display:block;width:100%;height:auto;aspect-ratio:3/5;object-fit:contain}
|
|
87
|
+
.details{position:relative;display:flex;justify-content:flex-end;gap:24px;padding:24px 8px 29px;font-size:17px;line-height:1.6;letter-spacing:1px}.details span{min-width:0;overflow-wrap:anywhere}.details span:last-child{text-align:right}.details b{font-weight:400;color:#403c31;margin-left:10px}
|
|
88
|
+
.roller{position:absolute;left:12px;right:12px;height:30px;z-index:2;border:1px solid #665033;border-radius:5px;background:linear-gradient(180deg,#695136 0%,#aa8b5f 16%,#dfc89a 38%,#b99a67 56%,#80613c 84%,#503a26 100%);box-shadow:0 4px 6px #44311933}.roller.top{top:0}.roller.bottom{bottom:0;height:34px}.roller:before,.roller:after{content:'';position:absolute;top:-4px;width:22px;height:calc(100% + 8px);border:1px solid #443321;border-radius:5px;background:linear-gradient(180deg,#493727,#987b50 28%,#bda071 42%,#745533 65%,#3d2d20);box-shadow:inset 3px 0 2px #d2b88166,inset -3px 0 2px #2c201c66}.roller:before{left:-14px}.roller:after{right:-14px}
|
|
89
|
+
</style></head><body><article id="capture"><div class="scroll"><div class="roller top" aria-hidden="true"></div><div class="sheet">${paper ? `<img class="paper" src="${escape(paper)}" alt="" aria-hidden="true">` : ""}<h1 class="title">形象卡</h1><div class="portrait"><img class="item-artwork" src="${escape(artwork)}" alt="${escape(card.name)}"></div><div class="details"><span>参考价格<b>${escape(card.referencePrice)}</b></span></div></div><div class="roller bottom" aria-hidden="true"></div></div></article></body></html>`;
|
|
90
90
|
}
|
|
91
91
|
__name(appearanceCardHtml, "appearanceCardHtml");
|
|
92
92
|
|
|
@@ -225,6 +225,7 @@ async function layoutCard(document = globalThis.document) {
|
|
|
225
225
|
if (avatar.scrollWidth <= avatar.clientWidth) break;
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
|
+
if (document.getElementById("capture")?.classList.contains("skill-sheet")) return;
|
|
228
229
|
const name2 = document.getElementById("name");
|
|
229
230
|
if (!name2) return;
|
|
230
231
|
for (let size = 36; size >= 20; size--) {
|
|
@@ -276,15 +277,21 @@ var import_node_path = __toESM(require("node:path"));
|
|
|
276
277
|
|
|
277
278
|
// src/plugin/skillCardTemplate.ts
|
|
278
279
|
var escape5 = /* @__PURE__ */ __name((value) => String(value ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]), "escape");
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
const
|
|
282
|
-
const desc = card.description || "暂无描述";
|
|
280
|
+
function skillCardHtml(card, _frame, artwork) {
|
|
281
|
+
const description = escape5((card.description || "暂无技能效果说明").replace(/\s*\n+\s*/g, ""));
|
|
282
|
+
const grain = "data:image/svg+xml," + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="180" height="180"><filter id="paper"><feTurbulence type="fractalNoise" baseFrequency=".72" numOctaves="3" stitchTiles="stitch"/></filter><rect width="100%" height="100%" opacity=".15" filter="url(#paper)"/></svg>');
|
|
283
283
|
return `<!doctype html><html><head><meta charset="utf-8"><style>
|
|
284
|
-
*{box-sizing:border-box}
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
284
|
+
*{box-sizing:border-box}
|
|
285
|
+
html,body{margin:0;width:760px;background:#f1eee5;font-family:'Microsoft YaHei','Noto Sans CJK SC',sans-serif;color:#34372f}
|
|
286
|
+
#capture{position:relative;isolation:isolate;width:760px;min-height:1060px;padding:57px 58px 38px;background:radial-gradient(ellipse at 0 0,#ddd9c744,transparent 48%),radial-gradient(ellipse at 100% 90%,#c9cdb938,transparent 45%),#f4f1e8;border:1px solid #dedbcf}
|
|
287
|
+
#capture:before{content:'';position:absolute;inset:0;z-index:-1;background-image:url('${grain}');opacity:.42;pointer-events:none}
|
|
288
|
+
#capture:after{content:'';position:absolute;inset:17px;border:1px solid #8c8b6f22;pointer-events:none}
|
|
289
|
+
header{position:relative}.heading{display:flex;align-items:center;gap:24px}.heading-copy{flex:1;min-width:0}.overline{font-size:14px;letter-spacing:6px;color:#868a76;margin-bottom:13px}.name{font-family:'KaiTi','STKaiti','Noto Serif CJK SC','SimSun',serif;font-size:43px;font-weight:700;line-height:1.35;margin:0;color:#303a31;overflow-wrap:anywhere}
|
|
290
|
+
.seal{flex-shrink:0;width:66px;min-height:74px;transform:rotate(3deg);padding:8px 3px;color:#a04b40;border:2px solid #a04b40;outline:1px solid #a04b40;outline-offset:-6px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;border-radius:3px 1px 4px 2px}.seal strong{font:700 24px Georgia;letter-spacing:-1px}.seal span{font-family:'KaiTi','SimSun',serif;font-size:16px;letter-spacing:4px;padding-left:4px}
|
|
291
|
+
.meta{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 22px;margin:24px 0 0;padding:15px 0;border-top:1px solid #8a8a7144;border-bottom:1px solid #8a8a7128;font-size:19px;color:#535d50;line-height:1.5}.meta span{overflow-wrap:anywhere;max-width:100%}.meta small{font-size:16px;color:#92917f;margin-right:7px}.meta .kind{color:#915344;font-family:'KaiTi','SimSun',serif;font-size:21px}
|
|
292
|
+
.art{position:relative;width:calc(100% + 44px);height:570px;margin:14px -22px -8px;display:grid;place-items:center;isolation:isolate}.art:before{content:'';position:absolute;inset:15% 10%;border-radius:48% 52% 56% 44%;background:radial-gradient(ellipse,#aab4a443,transparent 69%);transform:rotate(-12deg)}.skill-artwork{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 43%;filter:saturate(.68) contrast(.94);mix-blend-mode:multiply;mask-image:linear-gradient(to bottom,transparent 0,#000 9%,#000 72%,transparent 100%),linear-gradient(to right,transparent 0,#000 8%,#000 92%,transparent 100%);mask-composite:intersect}.art-fallback{position:relative;z-index:-1;width:300px;height:300px;border:2px solid #7c887d33;border-radius:48% 52% 50% 46%;transform:rotate(-12deg);display:grid;place-items:center;color:#8c948177;font:70px 'KaiTi','SimSun',serif}.art-fallback span{transform:rotate(12deg)}.art:has(.skill-artwork) .art-fallback{visibility:hidden}
|
|
293
|
+
.effect{position:relative;margin-top:0}h2{display:flex;align-items:center;gap:15px;margin:0 0 17px;font:22px 'KaiTi','SimSun',serif;letter-spacing:5px;color:#626e5e}h2:before{content:'';width:5px;height:17px;background:#a04b40;transform:rotate(8deg);opacity:.75}h2:after{content:'';flex:1;height:1px;background:linear-gradient(to right,#7f897c55,transparent)}p{margin:0;font-size:25px;line-height:1.85;white-space:pre-wrap;overflow-wrap:anywhere;text-align:justify}.footer{margin-top:24px;padding-top:17px;border-top:1px solid #8a8a7128}.footer p{font-size:18px;color:#7d8070;line-height:1.75;text-align:left}.edition{display:flex;align-items:center;gap:12px;justify-content:center;margin-top:36px;color:#a6a38e;font:14px 'KaiTi','SimSun',serif;letter-spacing:5px}.edition:before,.edition:after{content:'';height:1px;width:32px;background:#9b9c833d}
|
|
294
|
+
</style></head><body><div id="capture" class="skill-sheet ink-skill-sheet"><header><div class="heading"><div class="heading-copy"><div class="overline">技 艺 图 录</div><h1 class="name">${escape5(card.name)}</h1></div><div class="seal"><strong>${escape5(card.quality)}</strong><span>品阶</span></div></div><div class="meta"><span class="kind">${card.passive ? "被动" : "主动"}</span><span><small>等级</small>${escape5(card.level)} / ${escape5(card.maxLevel)}</span><span><small>消耗</small>${escape5(card.cost || "无消耗")}</span><span><small>冷却</small>${escape5(card.cooldown || "无冷却")}</span></div></header><div class="art"><div class="art-fallback"><span>${card.passive ? "静" : "势"}</span></div>${artwork ? `<img class="skill-artwork" alt="" src="${escape5(artwork)}">` : ""}</div><section class="effect"><h2>技能效果</h2><p>${description}</p></section>${card.sources?.length || card.note ? `<div class="footer">${card.sources?.length ? `<p>获取来源:${escape5(card.sources.join("、"))}</p>` : ""}${card.note ? `<p>${escape5(card.note)}</p>` : ""}</div>` : ""}<div class="edition">露 · 技艺录</div></div></body></html>`;
|
|
288
295
|
}
|
|
289
296
|
__name(skillCardHtml, "skillCardHtml");
|
|
290
297
|
|
|
@@ -386,7 +393,7 @@ async function renderSkillCard(ctx, card, leaderboard, itemCard, characterCard)
|
|
|
386
393
|
const work = /* @__PURE__ */ __name(async () => {
|
|
387
394
|
const art = await loadSkillArtwork(characterCard?.artworkUrl ?? itemCard?.artworkUrl ?? leaderboard?.backgroundUrl ?? card?.artworkUrl);
|
|
388
395
|
if (itemCard && !art) throw new Error("道具图片读取失败");
|
|
389
|
-
const html = characterCard ? characterCardHtml(characterCard, art, await characterAsset("paper.webp"), await characterAsset("default-female.webp")) : itemCard ? itemCard.type === "形象卡" ? appearanceCardHtml(itemCard, art, await
|
|
396
|
+
const html = characterCard ? characterCardHtml(characterCard, art, await characterAsset("paper.webp"), await characterAsset("default-female.webp")) : itemCard ? itemCard.type === "形象卡" ? appearanceCardHtml(itemCard, art, await characterAsset("paper.webp")) : itemCardHtml(itemCard, art, await itemPaper()) : leaderboard ? leaderboardHtml(leaderboard, await leaderboardHeader(), art) : skillCardHtml(card, await frame(card.passive), art);
|
|
390
397
|
page = await ctx.puppeteer.page();
|
|
391
398
|
if (expired) {
|
|
392
399
|
await page.close();
|
|
@@ -497,7 +504,6 @@ var ImageHandler = class extends handel_base {
|
|
|
497
504
|
content = new AnalysisMsg().parse(data);
|
|
498
505
|
}
|
|
499
506
|
await this.send(data, content, rendered ? "image" : "text");
|
|
500
|
-
if (rendered && data.itemCard) await this.send(data, new AnalysisMsg().parse(data));
|
|
501
507
|
}
|
|
502
508
|
};
|
|
503
509
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { ItemCardData } from '../shared/face';
|
|
2
|
-
/**
|
|
3
|
-
export declare function appearanceCardHtml(card: ItemCardData, artwork: string,
|
|
2
|
+
/** Hanging scroll shared by bot screenshots and editor previews. */
|
|
3
|
+
export declare function appearanceCardHtml(card: ItemCardData, artwork: string, paper?: string): string;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import type { SkillCardData } from '../shared/face';
|
|
2
|
-
|
|
2
|
+
/** One continuous rice-paper sheet; the old frame parameter remains API-compatible. */
|
|
3
|
+
export declare function skillCardHtml(card: SkillCardData, _frame: string, artwork?: string): string;
|
package/package.json
CHANGED
|
@@ -2,15 +2,15 @@ import type { ItemCardData } from '../shared/face';
|
|
|
2
2
|
|
|
3
3
|
const escape = (value: unknown) => String(value ?? '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]!));
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
export function appearanceCardHtml(card: ItemCardData, artwork: string,
|
|
7
|
-
const slice = (y: number, height: number) => `<svg class="frame" viewBox="0 ${y} 760 ${height}" preserveAspectRatio="none" aria-hidden="true"><image href="${escape(frame)}" width="760" height="1107" preserveAspectRatio="none"/></svg>`;
|
|
5
|
+
/** Hanging scroll shared by bot screenshots and editor previews. */
|
|
6
|
+
export function appearanceCardHtml(card: ItemCardData, artwork: string, paper?: string): string {
|
|
8
7
|
return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><style>
|
|
9
|
-
*{box-sizing:border-box}html,body{margin:0;width:760px;font-family:'Microsoft YaHei','Noto Sans CJK SC',sans-serif
|
|
10
|
-
#capture{width:760px
|
|
11
|
-
.
|
|
12
|
-
.
|
|
13
|
-
.
|
|
14
|
-
.
|
|
15
|
-
|
|
8
|
+
*{box-sizing:border-box}html,body{margin:0;width:760px;background:#ece8df;color:#625a49;font-family:'Microsoft YaHei','Noto Sans CJK SC',sans-serif}
|
|
9
|
+
#capture{width:760px;padding:25px 18px 29px;background:radial-gradient(ellipse at center,#f6f2e9,#e4ded2)}
|
|
10
|
+
.scroll{position:relative;padding:18px 0}.sheet{position:relative;margin:0 29px;padding:0 23px;background:#eee5cf;border-left:1px solid #b8a37b;border-right:1px solid #b8a37b;box-shadow:0 7px 16px #49381c24;overflow:hidden}
|
|
11
|
+
.paper{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.22;pointer-events:none}.sheet:after{content:'';position:absolute;inset:0;pointer-events:none;box-shadow:inset 0 18px 20px -18px #49351cb0,inset 0 -18px 20px -18px #49351c90}
|
|
12
|
+
.title{position:relative;margin:0;padding:29px 0 23px;text-align:center;font-family:'KaiTi','STKaiti','SimSun',serif;font-size:34px;font-weight:400;line-height:1.4;letter-spacing:8px;color:#514630}.portrait{position:relative;padding:5px;border:1px solid #ae9360;background:#e8dec5}.item-artwork{display:block;width:100%;height:auto;aspect-ratio:3/5;object-fit:contain}
|
|
13
|
+
.details{position:relative;display:flex;justify-content:flex-end;gap:24px;padding:24px 8px 29px;font-size:17px;line-height:1.6;letter-spacing:1px}.details span{min-width:0;overflow-wrap:anywhere}.details span:last-child{text-align:right}.details b{font-weight:400;color:#403c31;margin-left:10px}
|
|
14
|
+
.roller{position:absolute;left:12px;right:12px;height:30px;z-index:2;border:1px solid #665033;border-radius:5px;background:linear-gradient(180deg,#695136 0%,#aa8b5f 16%,#dfc89a 38%,#b99a67 56%,#80613c 84%,#503a26 100%);box-shadow:0 4px 6px #44311933}.roller.top{top:0}.roller.bottom{bottom:0;height:34px}.roller:before,.roller:after{content:'';position:absolute;top:-4px;width:22px;height:calc(100% + 8px);border:1px solid #443321;border-radius:5px;background:linear-gradient(180deg,#493727,#987b50 28%,#bda071 42%,#745533 65%,#3d2d20);box-shadow:inset 3px 0 2px #d2b88166,inset -3px 0 2px #2c201c66}.roller:before{left:-14px}.roller:after{right:-14px}
|
|
15
|
+
</style></head><body><article id="capture"><div class="scroll"><div class="roller top" aria-hidden="true"></div><div class="sheet">${paper ? `<img class="paper" src="${escape(paper)}" alt="" aria-hidden="true">` : ''}<h1 class="title">形象卡</h1><div class="portrait"><img class="item-artwork" src="${escape(artwork)}" alt="${escape(card.name)}"></div><div class="details"><span>参考价格<b>${escape(card.referencePrice)}</b></span></div></div><div class="roller bottom" aria-hidden="true"></div></div></article></body></html>`;
|
|
16
16
|
}
|
package/src/plugin/cardLayout.ts
CHANGED
|
@@ -31,6 +31,8 @@ export async function layoutCard(document: Document = globalThis.document) {
|
|
|
31
31
|
for (const avatar of document.querySelectorAll<HTMLElement>('.avatar')) {
|
|
32
32
|
for (let size = 30; size >= 16; size--) { avatar.style.fontSize = size + 'px'; if (avatar.scrollWidth <= avatar.clientWidth) break }
|
|
33
33
|
}
|
|
34
|
+
// Skill details use normal document flow and a fixed readable font size.
|
|
35
|
+
if (document.getElementById('capture')?.classList.contains('skill-sheet')) return;
|
|
34
36
|
const name = document.getElementById('name');
|
|
35
37
|
if (!name) return;
|
|
36
38
|
for (let size=36; size>=20; size--) { name.style.fontSize=size+'px'; if(name.scrollWidth<=name.clientWidth && name.scrollHeight<=name.clientHeight) break }
|
package/src/plugin/skillCard.ts
CHANGED
|
@@ -54,7 +54,7 @@ export async function renderSkillCard(ctx: Context, card?: SkillCardData, leader
|
|
|
54
54
|
const work = async () => {
|
|
55
55
|
const art = await loadSkillArtwork(characterCard?.artworkUrl ?? itemCard?.artworkUrl ?? leaderboard?.backgroundUrl ?? card?.artworkUrl)
|
|
56
56
|
if (itemCard && !art) throw new Error('道具图片读取失败')
|
|
57
|
-
const html = characterCard ? characterCardHtml(characterCard, art, await characterAsset('paper.webp'), await characterAsset('default-female.webp')) : itemCard ? (itemCard.type === '形象卡' ? appearanceCardHtml(itemCard, art!, await
|
|
57
|
+
const html = characterCard ? characterCardHtml(characterCard, art, await characterAsset('paper.webp'), await characterAsset('default-female.webp')) : itemCard ? (itemCard.type === '形象卡' ? appearanceCardHtml(itemCard, art!, await characterAsset('paper.webp')) : itemCardHtml(itemCard, art!, await itemPaper())) : leaderboard ? leaderboardHtml(leaderboard, await leaderboardHeader(), art) : skillCardHtml(card!, await frame(card!.passive), art)
|
|
58
58
|
page = await ctx.puppeteer.page()
|
|
59
59
|
if (expired) { await page.close(); throw new Error('绘图超时') }
|
|
60
60
|
await page.setViewport({ width:760,height:1107,deviceScaleFactor:1 })
|
|
@@ -1,12 +1,21 @@
|
|
|
1
|
-
import type { SkillCardData } from '../shared/face'
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
import type { SkillCardData } from '../shared/face'
|
|
2
|
+
|
|
3
|
+
const escape = (value: unknown) => String(value ?? '').replace(/[&<>"']/g, c => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c]!))
|
|
4
|
+
|
|
5
|
+
/** One continuous rice-paper sheet; the old frame parameter remains API-compatible. */
|
|
6
|
+
export function skillCardHtml(card: SkillCardData, _frame: string, artwork?: string): string {
|
|
7
|
+
const description = escape((card.description || '暂无技能效果说明').replace(/\s*\n+\s*/g, ''))
|
|
8
|
+
const grain = 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="180" height="180"><filter id="paper"><feTurbulence type="fractalNoise" baseFrequency=".72" numOctaves="3" stitchTiles="stitch"/></filter><rect width="100%" height="100%" opacity=".15" filter="url(#paper)"/></svg>')
|
|
9
|
+
return `<!doctype html><html><head><meta charset="utf-8"><style>
|
|
10
|
+
*{box-sizing:border-box}
|
|
11
|
+
html,body{margin:0;width:760px;background:#f1eee5;font-family:'Microsoft YaHei','Noto Sans CJK SC',sans-serif;color:#34372f}
|
|
12
|
+
#capture{position:relative;isolation:isolate;width:760px;min-height:1060px;padding:57px 58px 38px;background:radial-gradient(ellipse at 0 0,#ddd9c744,transparent 48%),radial-gradient(ellipse at 100% 90%,#c9cdb938,transparent 45%),#f4f1e8;border:1px solid #dedbcf}
|
|
13
|
+
#capture:before{content:'';position:absolute;inset:0;z-index:-1;background-image:url('${grain}');opacity:.42;pointer-events:none}
|
|
14
|
+
#capture:after{content:'';position:absolute;inset:17px;border:1px solid #8c8b6f22;pointer-events:none}
|
|
15
|
+
header{position:relative}.heading{display:flex;align-items:center;gap:24px}.heading-copy{flex:1;min-width:0}.overline{font-size:14px;letter-spacing:6px;color:#868a76;margin-bottom:13px}.name{font-family:'KaiTi','STKaiti','Noto Serif CJK SC','SimSun',serif;font-size:43px;font-weight:700;line-height:1.35;margin:0;color:#303a31;overflow-wrap:anywhere}
|
|
16
|
+
.seal{flex-shrink:0;width:66px;min-height:74px;transform:rotate(3deg);padding:8px 3px;color:#a04b40;border:2px solid #a04b40;outline:1px solid #a04b40;outline-offset:-6px;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;border-radius:3px 1px 4px 2px}.seal strong{font:700 24px Georgia;letter-spacing:-1px}.seal span{font-family:'KaiTi','SimSun',serif;font-size:16px;letter-spacing:4px;padding-left:4px}
|
|
17
|
+
.meta{display:flex;flex-wrap:wrap;align-items:baseline;gap:8px 22px;margin:24px 0 0;padding:15px 0;border-top:1px solid #8a8a7144;border-bottom:1px solid #8a8a7128;font-size:19px;color:#535d50;line-height:1.5}.meta span{overflow-wrap:anywhere;max-width:100%}.meta small{font-size:16px;color:#92917f;margin-right:7px}.meta .kind{color:#915344;font-family:'KaiTi','SimSun',serif;font-size:21px}
|
|
18
|
+
.art{position:relative;width:calc(100% + 44px);height:570px;margin:14px -22px -8px;display:grid;place-items:center;isolation:isolate}.art:before{content:'';position:absolute;inset:15% 10%;border-radius:48% 52% 56% 44%;background:radial-gradient(ellipse,#aab4a443,transparent 69%);transform:rotate(-12deg)}.skill-artwork{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 43%;filter:saturate(.68) contrast(.94);mix-blend-mode:multiply;mask-image:linear-gradient(to bottom,transparent 0,#000 9%,#000 72%,transparent 100%),linear-gradient(to right,transparent 0,#000 8%,#000 92%,transparent 100%);mask-composite:intersect}.art-fallback{position:relative;z-index:-1;width:300px;height:300px;border:2px solid #7c887d33;border-radius:48% 52% 50% 46%;transform:rotate(-12deg);display:grid;place-items:center;color:#8c948177;font:70px 'KaiTi','SimSun',serif}.art-fallback span{transform:rotate(12deg)}.art:has(.skill-artwork) .art-fallback{visibility:hidden}
|
|
19
|
+
.effect{position:relative;margin-top:0}h2{display:flex;align-items:center;gap:15px;margin:0 0 17px;font:22px 'KaiTi','SimSun',serif;letter-spacing:5px;color:#626e5e}h2:before{content:'';width:5px;height:17px;background:#a04b40;transform:rotate(8deg);opacity:.75}h2:after{content:'';flex:1;height:1px;background:linear-gradient(to right,#7f897c55,transparent)}p{margin:0;font-size:25px;line-height:1.85;white-space:pre-wrap;overflow-wrap:anywhere;text-align:justify}.footer{margin-top:24px;padding-top:17px;border-top:1px solid #8a8a7128}.footer p{font-size:18px;color:#7d8070;line-height:1.75;text-align:left}.edition{display:flex;align-items:center;gap:12px;justify-content:center;margin-top:36px;color:#a6a38e;font:14px 'KaiTi','SimSun',serif;letter-spacing:5px}.edition:before,.edition:after{content:'';height:1px;width:32px;background:#9b9c833d}
|
|
20
|
+
</style></head><body><div id="capture" class="skill-sheet ink-skill-sheet"><header><div class="heading"><div class="heading-copy"><div class="overline">技 艺 图 录</div><h1 class="name">${escape(card.name)}</h1></div><div class="seal"><strong>${escape(card.quality)}</strong><span>品阶</span></div></div><div class="meta"><span class="kind">${card.passive ? '被动' : '主动'}</span><span><small>等级</small>${escape(card.level)} / ${escape(card.maxLevel)}</span><span><small>消耗</small>${escape(card.cost || '无消耗')}</span><span><small>冷却</small>${escape(card.cooldown || '无冷却')}</span></div></header><div class="art"><div class="art-fallback"><span>${card.passive ? '静' : '势'}</span></div>${artwork ? `<img class="skill-artwork" alt="" src="${escape(artwork)}">` : ''}</div><section class="effect"><h2>技能效果</h2><p>${description}</p></section>${card.sources?.length || card.note ? `<div class="footer">${card.sources?.length ? `<p>获取来源:${escape(card.sources.join('、'))}</p>` : ''}${card.note ? `<p>${escape(card.note)}</p>` : ''}</div>` : ''}<div class="edition">露 · 技艺录</div></div></body></html>`
|
|
12
21
|
}
|