create-komorebi 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/README.md +7 -0
- package/dist/cli.js +414 -0
- package/package.json +39 -0
- package/template/README.md +15 -0
- package/template/astro.config.ts +10 -0
- package/template/package.json +11 -0
- package/template/public/favicon.ico +0 -0
- package/template/public/favicon.svg +9 -0
- package/template/src/content/about.md +9 -0
- package/template/src/content/blog/hello-world.md +9 -0
- package/template/src/content.config.ts +7 -0
- package/template/tsconfig.json +5 -0
package/README.md
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { cpSync, existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
4
|
+
import { basename, dirname, join, relative, resolve } from "node:path";
|
|
5
|
+
import process from "node:process";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
import prompts from "prompts";
|
|
9
|
+
const TEMPLATE_TEXT_FILES = [
|
|
10
|
+
".gitignore",
|
|
11
|
+
"README.md",
|
|
12
|
+
"package.json",
|
|
13
|
+
"astro.config.ts",
|
|
14
|
+
"tsconfig.json",
|
|
15
|
+
"src/content.config.ts",
|
|
16
|
+
"src/content/about.md",
|
|
17
|
+
"src/content/blog/hello-world.md",
|
|
18
|
+
];
|
|
19
|
+
const ASCII_LOGO = [
|
|
20
|
+
" _ __ _ _ ",
|
|
21
|
+
" | |/ /___ _ __ ___ ___ _ __ ___| |__ (_)",
|
|
22
|
+
" | ' // _ \\| '_ ` _ \\ / _ \\| '__/ _ \\ '_ \\| |",
|
|
23
|
+
" | . \\ (_) | | | | | | (_) | | | __/ |_) | |",
|
|
24
|
+
" |_|\\_\\___/|_| |_| |_|\\___/|_| \\___|_.__/|_|",
|
|
25
|
+
];
|
|
26
|
+
const HELP_TEXT = `create-komorebi
|
|
27
|
+
|
|
28
|
+
用法:
|
|
29
|
+
npm create komorebi@latest`;
|
|
30
|
+
const scriptDir = dirname(fileURLToPath(import.meta.url));
|
|
31
|
+
const packageRoot = resolve(scriptDir, "..");
|
|
32
|
+
const templateDir = resolve(packageRoot, "template");
|
|
33
|
+
await main();
|
|
34
|
+
async function main() {
|
|
35
|
+
validateArgs(process.argv.slice(2));
|
|
36
|
+
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
37
|
+
fail("当前版本需要在交互式终端中运行,请直接在终端执行 `npm create komorebi@latest`。");
|
|
38
|
+
}
|
|
39
|
+
const packageManager = detectPackageManager();
|
|
40
|
+
printBanner(packageManager);
|
|
41
|
+
const answers = await promptProjectAnswers(packageManager);
|
|
42
|
+
const targetDir = resolve(process.cwd(), answers.projectDir);
|
|
43
|
+
const projectName = normalizeProjectName(basename(targetDir));
|
|
44
|
+
const shouldInstall = answers.installMode === "install";
|
|
45
|
+
const createdDate = formatCurrentDate();
|
|
46
|
+
printSummary({
|
|
47
|
+
packageManager,
|
|
48
|
+
shouldInstall,
|
|
49
|
+
siteTitle: answers.siteTitle,
|
|
50
|
+
siteUrl: answers.siteUrl,
|
|
51
|
+
targetDir,
|
|
52
|
+
});
|
|
53
|
+
printStep("写入模板");
|
|
54
|
+
copyTemplate(templateDir, targetDir);
|
|
55
|
+
const replacements = {
|
|
56
|
+
...getReadmeCommandReplacements(packageManager),
|
|
57
|
+
"__PROJECT_NAME__": projectName,
|
|
58
|
+
"__SITE_TITLE__": answers.siteTitle,
|
|
59
|
+
"__SITE_TITLE_JSON__": JSON.stringify(answers.siteTitle),
|
|
60
|
+
"__SITE_URL_BLOCK__": answers.siteUrl
|
|
61
|
+
? `\n site: ${JSON.stringify(answers.siteUrl)},`
|
|
62
|
+
: "",
|
|
63
|
+
"__CONTENT_DATE__": createdDate,
|
|
64
|
+
"__ABOUT_TITLE_YAML__": JSON.stringify(`关于 ${answers.siteTitle}`),
|
|
65
|
+
"__ABOUT_DESCRIPTION_YAML__": JSON.stringify(`${answers.siteTitle} 的关于页面。`),
|
|
66
|
+
"__HELLO_DESCRIPTION_YAML__": JSON.stringify(`${answers.siteTitle} 的第一篇文章。`),
|
|
67
|
+
};
|
|
68
|
+
for (const relativePath of TEMPLATE_TEXT_FILES) {
|
|
69
|
+
const filePath = join(targetDir, relativePath);
|
|
70
|
+
const content = readFileSync(filePath, "utf-8");
|
|
71
|
+
writeFileSync(filePath, applyReplacements(content, replacements), "utf-8");
|
|
72
|
+
}
|
|
73
|
+
let installSucceeded = false;
|
|
74
|
+
if (shouldInstall) {
|
|
75
|
+
installSucceeded = installDependencies(targetDir, packageManager);
|
|
76
|
+
}
|
|
77
|
+
printSuccess({
|
|
78
|
+
packageManager,
|
|
79
|
+
shouldInstall,
|
|
80
|
+
installSucceeded,
|
|
81
|
+
targetDir,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
function validateArgs(argv) {
|
|
85
|
+
const args = argv.filter((arg) => arg !== "--");
|
|
86
|
+
if (args.length === 0) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
if (args.length === 1 && (args[0] === "--help" || args[0] === "-h")) {
|
|
90
|
+
console.log(HELP_TEXT);
|
|
91
|
+
process.exit(0);
|
|
92
|
+
}
|
|
93
|
+
fail("请直接运行 `npm create komorebi@latest`。");
|
|
94
|
+
}
|
|
95
|
+
function printBanner(packageManager) {
|
|
96
|
+
console.log("");
|
|
97
|
+
for (const line of ASCII_LOGO) {
|
|
98
|
+
console.log(pc.cyan(line));
|
|
99
|
+
}
|
|
100
|
+
console.log(pc.dim(" create-komorebi · 木漏れ日 Astro 博客初始化"));
|
|
101
|
+
console.log(pc.dim(` ${packageManager} · astro@^5`));
|
|
102
|
+
console.log("");
|
|
103
|
+
}
|
|
104
|
+
async function promptProjectAnswers(packageManager) {
|
|
105
|
+
const answers = await prompts([
|
|
106
|
+
{
|
|
107
|
+
type: "text",
|
|
108
|
+
name: "projectDir",
|
|
109
|
+
message: "项目目录",
|
|
110
|
+
validate: validateProjectDir,
|
|
111
|
+
format: (value) => value.trim(),
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
type: "text",
|
|
115
|
+
name: "siteTitle",
|
|
116
|
+
message: "博客标题",
|
|
117
|
+
validate: validateSiteTitle,
|
|
118
|
+
format: (value) => value.trim(),
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: "text",
|
|
122
|
+
name: "siteUrl",
|
|
123
|
+
message: "站点地址(可留空)",
|
|
124
|
+
validate: validateSiteUrl,
|
|
125
|
+
format: formatSiteUrl,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
type: "select",
|
|
129
|
+
name: "installMode",
|
|
130
|
+
message: `依赖安装(${packageManager})`,
|
|
131
|
+
hint: "使用方向键选择,回车确认",
|
|
132
|
+
initial: 0,
|
|
133
|
+
choices: [
|
|
134
|
+
{
|
|
135
|
+
title: "立即安装",
|
|
136
|
+
description: "安装 astro@^5、komorebi-theme、@astrojs/check、typescript",
|
|
137
|
+
value: "install",
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
title: "仅生成文件",
|
|
141
|
+
description: "稍后手动安装依赖",
|
|
142
|
+
value: "skip",
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
},
|
|
146
|
+
], {
|
|
147
|
+
onCancel: () => cancel(),
|
|
148
|
+
});
|
|
149
|
+
return answers;
|
|
150
|
+
}
|
|
151
|
+
function validateProjectDir(value) {
|
|
152
|
+
const trimmed = value.trim();
|
|
153
|
+
if (!trimmed) {
|
|
154
|
+
return "请输入项目目录";
|
|
155
|
+
}
|
|
156
|
+
const targetDir = resolve(process.cwd(), trimmed);
|
|
157
|
+
if (existsSync(targetDir) && !isEffectivelyEmpty(targetDir)) {
|
|
158
|
+
return "目录已存在且不为空";
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
function validateSiteTitle(value) {
|
|
163
|
+
if (!value.trim()) {
|
|
164
|
+
return "请输入博客标题";
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
function validateSiteUrl(value) {
|
|
169
|
+
const trimmed = value.trim();
|
|
170
|
+
if (!trimmed) {
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
normalizeSiteUrl(trimmed);
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
return getErrorMessage(error);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function formatSiteUrl(value) {
|
|
182
|
+
const trimmed = value.trim();
|
|
183
|
+
if (!trimmed) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
return normalizeSiteUrl(trimmed);
|
|
187
|
+
}
|
|
188
|
+
function isEffectivelyEmpty(dir) {
|
|
189
|
+
return readdirSync(dir).every((entry) => entry === ".git" || entry === ".DS_Store");
|
|
190
|
+
}
|
|
191
|
+
function copyTemplate(sourceDir, targetDir) {
|
|
192
|
+
mkdirSync(targetDir, { recursive: true });
|
|
193
|
+
for (const entry of readdirSync(sourceDir, { withFileTypes: true })) {
|
|
194
|
+
cpSync(join(sourceDir, entry.name), join(targetDir, entry.name), {
|
|
195
|
+
recursive: entry.isDirectory(),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function normalizeProjectName(value) {
|
|
200
|
+
const normalized = value
|
|
201
|
+
.trim()
|
|
202
|
+
.toLowerCase()
|
|
203
|
+
.replace(/[^a-z0-9._-]+/g, "-")
|
|
204
|
+
.replace(/^-+|-+$/g, "");
|
|
205
|
+
return normalized || "komorebi-site";
|
|
206
|
+
}
|
|
207
|
+
function normalizeSiteUrl(value) {
|
|
208
|
+
let parsed;
|
|
209
|
+
try {
|
|
210
|
+
parsed = new URL(value);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
throw new Error(`站点地址无效:${value}`);
|
|
214
|
+
}
|
|
215
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
216
|
+
throw new Error(`站点地址必须以 http:// 或 https:// 开头:${value}`);
|
|
217
|
+
}
|
|
218
|
+
return parsed.toString().replace(/\/$/, "");
|
|
219
|
+
}
|
|
220
|
+
function formatCurrentDate() {
|
|
221
|
+
return new Date().toISOString().slice(0, 10);
|
|
222
|
+
}
|
|
223
|
+
function applyReplacements(content, replacements) {
|
|
224
|
+
let output = content;
|
|
225
|
+
for (const [token, value] of Object.entries(replacements)) {
|
|
226
|
+
output = output.replaceAll(token, value);
|
|
227
|
+
}
|
|
228
|
+
return output;
|
|
229
|
+
}
|
|
230
|
+
function detectPackageManager() {
|
|
231
|
+
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
232
|
+
if (userAgent.startsWith("pnpm")) {
|
|
233
|
+
return "pnpm";
|
|
234
|
+
}
|
|
235
|
+
if (userAgent.startsWith("yarn")) {
|
|
236
|
+
return "yarn";
|
|
237
|
+
}
|
|
238
|
+
if (userAgent.startsWith("bun")) {
|
|
239
|
+
return "bun";
|
|
240
|
+
}
|
|
241
|
+
return "npm";
|
|
242
|
+
}
|
|
243
|
+
function installDependencies(targetDir, packageManager) {
|
|
244
|
+
const commands = getInstallCommands(packageManager);
|
|
245
|
+
printStep("安装运行依赖");
|
|
246
|
+
const runtimeInstalled = runCommand(packageManager, commands.runtime, targetDir);
|
|
247
|
+
if (!runtimeInstalled) {
|
|
248
|
+
console.log("");
|
|
249
|
+
console.log(pc.yellow("安装中断,项目文件已创建。"));
|
|
250
|
+
console.log("");
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
printStep("安装开发依赖");
|
|
254
|
+
const devInstalled = runCommand(packageManager, commands.dev, targetDir);
|
|
255
|
+
if (!devInstalled) {
|
|
256
|
+
console.log("");
|
|
257
|
+
console.log(pc.yellow("安装中断,项目文件已创建。"));
|
|
258
|
+
console.log("");
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
function getInstallCommands(packageManager) {
|
|
264
|
+
if (packageManager === "pnpm") {
|
|
265
|
+
return {
|
|
266
|
+
runtime: ["add", "astro@^5", "komorebi-theme"],
|
|
267
|
+
dev: ["add", "-D", "@astrojs/check", "typescript"],
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
if (packageManager === "yarn") {
|
|
271
|
+
return {
|
|
272
|
+
runtime: ["add", "astro@^5", "komorebi-theme"],
|
|
273
|
+
dev: ["add", "-D", "@astrojs/check", "typescript"],
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
if (packageManager === "bun") {
|
|
277
|
+
return {
|
|
278
|
+
runtime: ["add", "astro@^5", "komorebi-theme"],
|
|
279
|
+
dev: ["add", "-d", "@astrojs/check", "typescript"],
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
return {
|
|
283
|
+
runtime: ["install", "astro@^5", "komorebi-theme"],
|
|
284
|
+
dev: ["install", "-D", "@astrojs/check", "typescript"],
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function runCommand(command, args, cwd) {
|
|
288
|
+
const result = spawnSync(command, args, {
|
|
289
|
+
cwd,
|
|
290
|
+
stdio: "inherit",
|
|
291
|
+
});
|
|
292
|
+
if (result.error) {
|
|
293
|
+
console.log(getErrorMessage(result.error));
|
|
294
|
+
return false;
|
|
295
|
+
}
|
|
296
|
+
return result.status === 0;
|
|
297
|
+
}
|
|
298
|
+
function printSuccess(options) {
|
|
299
|
+
const relativeTarget = formatTargetDir(options.targetDir);
|
|
300
|
+
const devCommand = getDevCommand(options.packageManager);
|
|
301
|
+
const installCommands = getManualInstallHints(options.packageManager);
|
|
302
|
+
console.log(pc.green(pc.bold("◆ 创建完成")));
|
|
303
|
+
console.log(pc.dim(` ${relativeTarget}`));
|
|
304
|
+
console.log("");
|
|
305
|
+
console.log(pc.bold("下一步"));
|
|
306
|
+
if (relativeTarget !== ".") {
|
|
307
|
+
console.log(` cd ${relativeTarget}`);
|
|
308
|
+
}
|
|
309
|
+
if (!options.shouldInstall || !options.installSucceeded) {
|
|
310
|
+
console.log(` ${installCommands.runtime}`);
|
|
311
|
+
console.log(` ${installCommands.dev}`);
|
|
312
|
+
}
|
|
313
|
+
console.log(` ${devCommand}`);
|
|
314
|
+
console.log("");
|
|
315
|
+
}
|
|
316
|
+
function getManualInstallHints(packageManager) {
|
|
317
|
+
if (packageManager === "pnpm") {
|
|
318
|
+
return {
|
|
319
|
+
runtime: "pnpm add astro@^5 komorebi-theme",
|
|
320
|
+
dev: "pnpm add -D @astrojs/check typescript",
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
if (packageManager === "yarn") {
|
|
324
|
+
return {
|
|
325
|
+
runtime: "yarn add astro@^5 komorebi-theme",
|
|
326
|
+
dev: "yarn add -D @astrojs/check typescript",
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (packageManager === "bun") {
|
|
330
|
+
return {
|
|
331
|
+
runtime: "bun add astro@^5 komorebi-theme",
|
|
332
|
+
dev: "bun add -d @astrojs/check typescript",
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
return {
|
|
336
|
+
runtime: "npm install astro@^5 komorebi-theme",
|
|
337
|
+
dev: "npm install -D @astrojs/check typescript",
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
function getDevCommand(packageManager) {
|
|
341
|
+
if (packageManager === "pnpm" || packageManager === "yarn") {
|
|
342
|
+
return `${packageManager} dev`;
|
|
343
|
+
}
|
|
344
|
+
if (packageManager === "bun") {
|
|
345
|
+
return "bun run dev";
|
|
346
|
+
}
|
|
347
|
+
return "npm run dev";
|
|
348
|
+
}
|
|
349
|
+
function getReadmeCommandReplacements(packageManager) {
|
|
350
|
+
const installCommands = getManualInstallHints(packageManager);
|
|
351
|
+
return {
|
|
352
|
+
"__INSTALL_RUNTIME_COMMAND__": installCommands.runtime,
|
|
353
|
+
"__INSTALL_DEV_COMMAND__": installCommands.dev,
|
|
354
|
+
"__DEV_COMMAND__": getDevCommand(packageManager),
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function printSummary(options) {
|
|
358
|
+
const rows = [
|
|
359
|
+
["目录", formatTargetDir(options.targetDir)],
|
|
360
|
+
["标题", options.siteTitle],
|
|
361
|
+
["站点", options.siteUrl ?? "未设置"],
|
|
362
|
+
[
|
|
363
|
+
"安装",
|
|
364
|
+
options.shouldInstall
|
|
365
|
+
? `立即安装(${options.packageManager})`
|
|
366
|
+
: "仅生成文件",
|
|
367
|
+
],
|
|
368
|
+
];
|
|
369
|
+
console.log(pc.cyan("┌ 配置"));
|
|
370
|
+
for (const [label, value] of rows) {
|
|
371
|
+
console.log(`${pc.cyan("│")} ${pc.dim(label)} ${value}`);
|
|
372
|
+
}
|
|
373
|
+
console.log(pc.cyan("└"));
|
|
374
|
+
console.log("");
|
|
375
|
+
}
|
|
376
|
+
function printStep(label) {
|
|
377
|
+
console.log(pc.cyan(`◆ ${label}`));
|
|
378
|
+
console.log("");
|
|
379
|
+
}
|
|
380
|
+
function relativeFromCwd(targetDir) {
|
|
381
|
+
const relativeTarget = relative(process.cwd(), targetDir);
|
|
382
|
+
if (!relativeTarget) {
|
|
383
|
+
return ".";
|
|
384
|
+
}
|
|
385
|
+
return relativeTarget;
|
|
386
|
+
}
|
|
387
|
+
function formatTargetDir(targetDir) {
|
|
388
|
+
const relativeTarget = relativeFromCwd(targetDir);
|
|
389
|
+
if (relativeTarget === ".") {
|
|
390
|
+
return ".";
|
|
391
|
+
}
|
|
392
|
+
if (relativeTarget.startsWith("..")) {
|
|
393
|
+
return targetDir;
|
|
394
|
+
}
|
|
395
|
+
return relativeTarget;
|
|
396
|
+
}
|
|
397
|
+
function getErrorMessage(error) {
|
|
398
|
+
if (error instanceof Error) {
|
|
399
|
+
return error.message;
|
|
400
|
+
}
|
|
401
|
+
return String(error);
|
|
402
|
+
}
|
|
403
|
+
function cancel() {
|
|
404
|
+
console.log("");
|
|
405
|
+
console.log(pc.yellow("已取消"));
|
|
406
|
+
console.log("");
|
|
407
|
+
process.exit(0);
|
|
408
|
+
}
|
|
409
|
+
function fail(message) {
|
|
410
|
+
console.error("");
|
|
411
|
+
console.error(pc.red(message));
|
|
412
|
+
console.error("");
|
|
413
|
+
process.exit(1);
|
|
414
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-komorebi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-komorebi": "./dist/cli.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "tsc -p tsconfig.json",
|
|
10
|
+
"prepack": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"template",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"keywords": [
|
|
18
|
+
"astro",
|
|
19
|
+
"blog",
|
|
20
|
+
"create",
|
|
21
|
+
"komorebi",
|
|
22
|
+
"starter"
|
|
23
|
+
],
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"picocolors": "^1.1.1",
|
|
29
|
+
"prompts": "^2.4.2"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^25.5.0",
|
|
33
|
+
"@types/prompts": "^2.4.9",
|
|
34
|
+
"typescript": "^5.9.2"
|
|
35
|
+
},
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=18.20.8"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
|
|
2
|
+
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
|
|
3
|
+
<style>
|
|
4
|
+
path { fill: #000; }
|
|
5
|
+
@media (prefers-color-scheme: dark) {
|
|
6
|
+
path { fill: #FFF; }
|
|
7
|
+
}
|
|
8
|
+
</style>
|
|
9
|
+
</svg>
|