create-bearminion 0.0.0-stage → 1.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/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +65 -2
- package/dist/cli.mjs +1369 -0
- package/package.json +53 -3
- package/template/.storybook/main.ts +14 -0
- package/template/.storybook/preview.css +8 -0
- package/template/.storybook/preview.ts +17 -0
- package/template/README.md +251 -0
- package/template/_gitignore +21 -0
- package/template/astro.config.ts +46 -0
- package/template/content/pages/404.json +36 -0
- package/template/content/pages/about.json +101 -0
- package/template/content/pages/index.json +463 -0
- package/template/content/pages/preview.json +40 -0
- package/template/content/site.json +117 -0
- package/template/package.json +37 -0
- package/template/src/assets/uploads/favicon.png +0 -0
- package/template/src/assets/uploads/hero.png +0 -0
- package/template/src/assets/uploads/logo.png +0 -0
- package/template/src/assets/uploads/og.png +0 -0
- package/template/src/components/atoms/Button.astro +64 -0
- package/template/src/components/atoms/Button.stories.ts +42 -0
- package/template/src/components/atoms/Emphasis.astro +24 -0
- package/template/src/components/atoms/Emphasis.stories.ts +25 -0
- package/template/src/components/atoms/Image.astro +78 -0
- package/template/src/components/atoms/Image.stories.ts +35 -0
- package/template/src/components/atoms/LogoMark.astro +53 -0
- package/template/src/components/atoms/LogoMark.stories.ts +25 -0
- package/template/src/components/atoms/Typography.astro +50 -0
- package/template/src/components/atoms/Typography.stories.ts +20 -0
- package/template/src/components/atoms/button.ts +31 -0
- package/template/src/components/atoms/image.ts +34 -0
- package/template/src/components/atoms/options.ts +39 -0
- package/template/src/components/atoms/typography.ts +63 -0
- package/template/src/components/molecules/MediaFrame.astro +71 -0
- package/template/src/components/molecules/MediaFrame.stories.ts +14 -0
- package/template/src/components/molecules/Pill.astro +24 -0
- package/template/src/components/molecules/Pill.stories.ts +12 -0
- package/template/src/components/molecules/SectionHeader.astro +63 -0
- package/template/src/components/molecules/SectionHeader.stories.ts +15 -0
- package/template/src/components/molecules/SectionShell.astro +33 -0
- package/template/src/components/molecules/SectionShell.stories.ts +25 -0
- package/template/src/components/organisms/Footer.astro +133 -0
- package/template/src/components/organisms/Footer.stories.ts +16 -0
- package/template/src/components/organisms/FooterLinks.astro +32 -0
- package/template/src/components/organisms/Header.astro +94 -0
- package/template/src/components/organisms/Header.stories.ts +27 -0
- package/template/src/components/organisms/MobileBranch.astro +52 -0
- package/template/src/components/organisms/MobileMenu.astro +110 -0
- package/template/src/components/organisms/MobileMenu.stories.ts +30 -0
- package/template/src/components/organisms/NavBranch.astro +61 -0
- package/template/src/components/organisms/Navigation.astro +32 -0
- package/template/src/components/organisms/Navigation.stories.ts +25 -0
- package/template/src/components/organisms/site-definition.ts +28 -0
- package/template/src/components/sections/SectionList.astro +53 -0
- package/template/src/components/sections/contact/Contact.astro +227 -0
- package/template/src/components/sections/contact/Contact.stories.ts +16 -0
- package/template/src/components/sections/contact/definition.ts +50 -0
- package/template/src/components/sections/contact/wireframe.ts +15 -0
- package/template/src/components/sections/cta/Cta.astro +181 -0
- package/template/src/components/sections/cta/Cta.stories.ts +19 -0
- package/template/src/components/sections/cta/definition.ts +35 -0
- package/template/src/components/sections/cta/wireframe.ts +9 -0
- package/template/src/components/sections/definitions.ts +54 -0
- package/template/src/components/sections/faq/Faq.astro +131 -0
- package/template/src/components/sections/faq/Faq.stories.ts +16 -0
- package/template/src/components/sections/faq/definition.ts +51 -0
- package/template/src/components/sections/faq/wireframe.ts +19 -0
- package/template/src/components/sections/features/Features.astro +121 -0
- package/template/src/components/sections/features/Features.stories.ts +19 -0
- package/template/src/components/sections/features/definition.ts +64 -0
- package/template/src/components/sections/features/wireframe.ts +19 -0
- package/template/src/components/sections/hero/Hero.astro +155 -0
- package/template/src/components/sections/hero/Hero.stories.ts +28 -0
- package/template/src/components/sections/hero/definition.ts +36 -0
- package/template/src/components/sections/hero/wireframe.ts +12 -0
- package/template/src/components/sections/logo-strip/LogoStrip.astro +107 -0
- package/template/src/components/sections/logo-strip/LogoStrip.stories.ts +20 -0
- package/template/src/components/sections/logo-strip/definition.ts +30 -0
- package/template/src/components/sections/logo-strip/wireframe.ts +11 -0
- package/template/src/components/sections/pricing/Pricing.astro +210 -0
- package/template/src/components/sections/pricing/Pricing.stories.ts +16 -0
- package/template/src/components/sections/pricing/definition.ts +62 -0
- package/template/src/components/sections/pricing/wireframe.ts +18 -0
- package/template/src/components/sections/registry.ts +25 -0
- package/template/src/components/sections/shared.ts +13 -0
- package/template/src/components/sections/stats/Stats.astro +110 -0
- package/template/src/components/sections/stats/Stats.stories.ts +16 -0
- package/template/src/components/sections/stats/definition.ts +41 -0
- package/template/src/components/sections/stats/wireframe.ts +15 -0
- package/template/src/components/sections/testimonials/Testimonials.astro +172 -0
- package/template/src/components/sections/testimonials/Testimonials.stories.ts +19 -0
- package/template/src/components/sections/testimonials/definition.ts +42 -0
- package/template/src/components/sections/testimonials/wireframe.ts +21 -0
- package/template/src/components/sections/text-image/TextImage.astro +109 -0
- package/template/src/components/sections/text-image/TextImage.stories.ts +19 -0
- package/template/src/components/sections/text-image/definition.ts +38 -0
- package/template/src/components/sections/text-image/wireframe.ts +12 -0
- package/template/src/components/seo/Seo.astro +63 -0
- package/template/src/content.config.ts +19 -0
- package/template/src/dev/style-guide.astro +124 -0
- package/template/src/dev/variants.astro +117 -0
- package/template/src/env.d.ts +1 -0
- package/template/src/layouts/Base.astro +74 -0
- package/template/src/lib/assets.ts +13 -0
- package/template/src/lib/cn.ts +6 -0
- package/template/src/lib/content-dir.ts +8 -0
- package/template/src/lib/content-model.ts +25 -0
- package/template/src/lib/content.ts +26 -0
- package/template/src/lib/link-attrs.ts +74 -0
- package/template/src/lib/render-preview.ts +29 -0
- package/template/src/lib/sitemap.ts +36 -0
- package/template/src/pages/404.astro +15 -0
- package/template/src/pages/[...slug].astro +32 -0
- package/template/src/pages/robots.txt.ts +10 -0
- package/template/src/stories/args.ts +34 -0
- package/template/src/stories/options.ts +63 -0
- package/template/src/stories/sample.ts +24 -0
- package/template/src/styles/global.css +379 -0
- package/template/tsconfig.json +8 -0
package/dist/cli.mjs
ADDED
|
@@ -0,0 +1,1369 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { parseArgs, styleText } from "node:util";
|
|
6
|
+
import process$1, { stdin, stdout } from "node:process";
|
|
7
|
+
import l__default, * as l from "node:readline";
|
|
8
|
+
import { ReadStream } from "node:tty";
|
|
9
|
+
import { cp, readFile, readdir, rename, writeFile } from "node:fs/promises";
|
|
10
|
+
import { spawn, spawnSync } from "node:child_process";
|
|
11
|
+
//#region \0rolldown/runtime.js
|
|
12
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
15
|
+
const getCodePointsLength = (() => {
|
|
16
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
17
|
+
return (input) => {
|
|
18
|
+
let surrogatePairsNr = 0;
|
|
19
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
20
|
+
while (SURROGATE_PAIR_RE.test(input)) surrogatePairsNr += 1;
|
|
21
|
+
return input.length - surrogatePairsNr;
|
|
22
|
+
};
|
|
23
|
+
})();
|
|
24
|
+
const isFullWidth = (x) => {
|
|
25
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
26
|
+
};
|
|
27
|
+
const isWideNotCJKTNotEmoji = (x) => {
|
|
28
|
+
return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
32
|
+
const ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
33
|
+
const CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
34
|
+
const CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/uy;
|
|
35
|
+
const TAB_RE = /\t{1,1000}/y;
|
|
36
|
+
const EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/uy;
|
|
37
|
+
const LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
38
|
+
const MODIFIER_RE = /\p{M}+/gu;
|
|
39
|
+
const NO_TRUNCATION$1 = {
|
|
40
|
+
limit: Infinity,
|
|
41
|
+
ellipsis: ""
|
|
42
|
+
};
|
|
43
|
+
const getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
44
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
45
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
46
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION$1, widthOptions).width : 0);
|
|
47
|
+
const ANSI_WIDTH = 0;
|
|
48
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
49
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
50
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
51
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
52
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
53
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
54
|
+
const PARSE_BLOCKS = [
|
|
55
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
56
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
57
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
58
|
+
[TAB_RE, TAB_WIDTH],
|
|
59
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
60
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
61
|
+
];
|
|
62
|
+
let indexPrev = 0;
|
|
63
|
+
let index = 0;
|
|
64
|
+
let length = input.length;
|
|
65
|
+
let lengthExtra = 0;
|
|
66
|
+
let truncationEnabled = false;
|
|
67
|
+
let truncationIndex = length;
|
|
68
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
69
|
+
let unmatchedStart = 0;
|
|
70
|
+
let unmatchedEnd = 0;
|
|
71
|
+
let width = 0;
|
|
72
|
+
let widthExtra = 0;
|
|
73
|
+
outer: while (true) {
|
|
74
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
75
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
76
|
+
lengthExtra = 0;
|
|
77
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
78
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
79
|
+
if (isFullWidth(codePoint)) widthExtra = FULL_WIDTH_WIDTH;
|
|
80
|
+
else if (isWideNotCJKTNotEmoji(codePoint)) widthExtra = WIDE_WIDTH;
|
|
81
|
+
else widthExtra = REGULAR_WIDTH;
|
|
82
|
+
if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
83
|
+
if (width + widthExtra > LIMIT) {
|
|
84
|
+
truncationEnabled = true;
|
|
85
|
+
break outer;
|
|
86
|
+
}
|
|
87
|
+
lengthExtra += char.length;
|
|
88
|
+
width += widthExtra;
|
|
89
|
+
}
|
|
90
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
91
|
+
}
|
|
92
|
+
if (index >= length) break outer;
|
|
93
|
+
for (let i = 0, l = PARSE_BLOCKS.length; i < l; i++) {
|
|
94
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
95
|
+
BLOCK_RE.lastIndex = index;
|
|
96
|
+
if (BLOCK_RE.test(input)) {
|
|
97
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
98
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
99
|
+
if (width + widthExtra > truncationLimit) truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
100
|
+
if (width + widthExtra > LIMIT) {
|
|
101
|
+
truncationEnabled = true;
|
|
102
|
+
break outer;
|
|
103
|
+
}
|
|
104
|
+
width += widthExtra;
|
|
105
|
+
unmatchedStart = indexPrev;
|
|
106
|
+
unmatchedEnd = index;
|
|
107
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
108
|
+
continue outer;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
index += 1;
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
115
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
116
|
+
truncated: truncationEnabled,
|
|
117
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
//#endregion
|
|
121
|
+
//#region ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
122
|
+
const NO_TRUNCATION = {
|
|
123
|
+
limit: Infinity,
|
|
124
|
+
ellipsis: "",
|
|
125
|
+
ellipsisWidth: 0
|
|
126
|
+
};
|
|
127
|
+
const fastStringWidth = (input, options = {}) => {
|
|
128
|
+
return getStringTruncatedWidth(input, NO_TRUNCATION, options).width;
|
|
129
|
+
};
|
|
130
|
+
//#endregion
|
|
131
|
+
//#region ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
|
|
132
|
+
const ESC = "\x1B";
|
|
133
|
+
const CSI = "";
|
|
134
|
+
const END_CODE = 39;
|
|
135
|
+
const ANSI_ESCAPE_BELL = "\x07";
|
|
136
|
+
const ANSI_CSI = "[";
|
|
137
|
+
const ANSI_OSC = "]";
|
|
138
|
+
const ANSI_SGR_TERMINATOR = "m";
|
|
139
|
+
const ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
140
|
+
const GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
141
|
+
const getClosingCode = (openingCode) => {
|
|
142
|
+
if (openingCode >= 30 && openingCode <= 37) return 39;
|
|
143
|
+
if (openingCode >= 90 && openingCode <= 97) return 39;
|
|
144
|
+
if (openingCode >= 40 && openingCode <= 47) return 49;
|
|
145
|
+
if (openingCode >= 100 && openingCode <= 107) return 49;
|
|
146
|
+
if (openingCode === 1 || openingCode === 2) return 22;
|
|
147
|
+
if (openingCode === 3) return 23;
|
|
148
|
+
if (openingCode === 4) return 24;
|
|
149
|
+
if (openingCode === 7) return 27;
|
|
150
|
+
if (openingCode === 8) return 28;
|
|
151
|
+
if (openingCode === 9) return 29;
|
|
152
|
+
if (openingCode === 0) return 0;
|
|
153
|
+
};
|
|
154
|
+
const wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
155
|
+
const wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
156
|
+
const wrapWord = (rows, word, columns) => {
|
|
157
|
+
const characters = word[Symbol.iterator]();
|
|
158
|
+
let isInsideEscape = false;
|
|
159
|
+
let isInsideLinkEscape = false;
|
|
160
|
+
let lastRow = rows.at(-1);
|
|
161
|
+
let visible = lastRow === void 0 ? 0 : fastStringWidth(lastRow);
|
|
162
|
+
let currentCharacter = characters.next();
|
|
163
|
+
let nextCharacter = characters.next();
|
|
164
|
+
let rawCharacterIndex = 0;
|
|
165
|
+
while (!currentCharacter.done) {
|
|
166
|
+
const character = currentCharacter.value;
|
|
167
|
+
const characterLength = fastStringWidth(character);
|
|
168
|
+
if (visible + characterLength <= columns) rows[rows.length - 1] += character;
|
|
169
|
+
else {
|
|
170
|
+
rows.push(character);
|
|
171
|
+
visible = 0;
|
|
172
|
+
}
|
|
173
|
+
if (character === ESC || character === CSI) {
|
|
174
|
+
isInsideEscape = true;
|
|
175
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
176
|
+
}
|
|
177
|
+
if (isInsideEscape) {
|
|
178
|
+
if (isInsideLinkEscape) {
|
|
179
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
180
|
+
isInsideEscape = false;
|
|
181
|
+
isInsideLinkEscape = false;
|
|
182
|
+
}
|
|
183
|
+
} else if (character === ANSI_SGR_TERMINATOR) isInsideEscape = false;
|
|
184
|
+
} else {
|
|
185
|
+
visible += characterLength;
|
|
186
|
+
if (visible === columns && !nextCharacter.done) {
|
|
187
|
+
rows.push("");
|
|
188
|
+
visible = 0;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
currentCharacter = nextCharacter;
|
|
192
|
+
nextCharacter = characters.next();
|
|
193
|
+
rawCharacterIndex += character.length;
|
|
194
|
+
}
|
|
195
|
+
lastRow = rows.at(-1);
|
|
196
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows.length > 1) rows[rows.length - 2] += rows.pop();
|
|
197
|
+
};
|
|
198
|
+
const stringVisibleTrimSpacesRight = (string) => {
|
|
199
|
+
const words = string.split(" ");
|
|
200
|
+
let last = words.length;
|
|
201
|
+
while (last) {
|
|
202
|
+
if (fastStringWidth(words[last - 1])) break;
|
|
203
|
+
last--;
|
|
204
|
+
}
|
|
205
|
+
if (last === words.length) return string;
|
|
206
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
207
|
+
};
|
|
208
|
+
const exec = (string, columns, options = {}) => {
|
|
209
|
+
if (options.trim !== false && string.trim() === "") return "";
|
|
210
|
+
let returnValue = "";
|
|
211
|
+
let escapeCode;
|
|
212
|
+
let escapeUrl;
|
|
213
|
+
const words = string.split(" ");
|
|
214
|
+
let rows = [""];
|
|
215
|
+
let rowLength = 0;
|
|
216
|
+
for (let index = 0; index < words.length; index++) {
|
|
217
|
+
const word = words[index];
|
|
218
|
+
if (options.trim !== false) {
|
|
219
|
+
const row = rows.at(-1) ?? "";
|
|
220
|
+
const trimmed = row.trimStart();
|
|
221
|
+
if (row.length !== trimmed.length) {
|
|
222
|
+
rows[rows.length - 1] = trimmed;
|
|
223
|
+
rowLength = fastStringWidth(trimmed);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (index !== 0) {
|
|
227
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
228
|
+
rows.push("");
|
|
229
|
+
rowLength = 0;
|
|
230
|
+
}
|
|
231
|
+
if (rowLength || options.trim === false) {
|
|
232
|
+
rows[rows.length - 1] += " ";
|
|
233
|
+
rowLength++;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const wordLength = fastStringWidth(word);
|
|
237
|
+
if (options.hard && wordLength > columns) {
|
|
238
|
+
const remainingColumns = columns - rowLength;
|
|
239
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
240
|
+
if (Math.floor((wordLength - 1) / columns) < breaksStartingThisLine) rows.push("");
|
|
241
|
+
wrapWord(rows, word, columns);
|
|
242
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
246
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
247
|
+
wrapWord(rows, word, columns);
|
|
248
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
rows.push("");
|
|
252
|
+
rowLength = 0;
|
|
253
|
+
}
|
|
254
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
255
|
+
wrapWord(rows, word, columns);
|
|
256
|
+
rowLength = fastStringWidth(rows.at(-1) ?? "");
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
rows[rows.length - 1] += word;
|
|
260
|
+
rowLength += wordLength;
|
|
261
|
+
}
|
|
262
|
+
if (options.trim !== false) rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
263
|
+
const preString = rows.join("\n");
|
|
264
|
+
let inSurrogate = false;
|
|
265
|
+
for (let i = 0; i < preString.length; i++) {
|
|
266
|
+
const character = preString[i];
|
|
267
|
+
returnValue += character;
|
|
268
|
+
if (!inSurrogate) {
|
|
269
|
+
inSurrogate = character >= "\ud800" && character <= "\udbff";
|
|
270
|
+
if (inSurrogate) continue;
|
|
271
|
+
} else inSurrogate = false;
|
|
272
|
+
if (character === ESC || character === CSI) {
|
|
273
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
274
|
+
const groups = GROUP_REGEX.exec(preString)?.groups;
|
|
275
|
+
if (groups?.code !== void 0) {
|
|
276
|
+
const code = Number.parseFloat(groups.code);
|
|
277
|
+
escapeCode = code === END_CODE ? void 0 : code;
|
|
278
|
+
} else if (groups?.uri !== void 0) escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
|
|
279
|
+
}
|
|
280
|
+
if (preString[i + 1] === "\n") {
|
|
281
|
+
if (escapeUrl) returnValue += wrapAnsiHyperlink("");
|
|
282
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
|
|
283
|
+
if (escapeCode && closingCode) returnValue += wrapAnsiCode(closingCode);
|
|
284
|
+
} else if (character === "\n") {
|
|
285
|
+
if (escapeCode && getClosingCode(escapeCode)) returnValue += wrapAnsiCode(escapeCode);
|
|
286
|
+
if (escapeUrl) returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return returnValue;
|
|
290
|
+
};
|
|
291
|
+
const CRLF_OR_LF = /\r?\n/;
|
|
292
|
+
function wrapAnsi(string, columns, options) {
|
|
293
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
294
|
+
}
|
|
295
|
+
//#endregion
|
|
296
|
+
//#region ../../node_modules/.pnpm/@clack+core@1.5.1/node_modules/@clack/core/dist/index.mjs
|
|
297
|
+
var import_src = (/* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
298
|
+
const ESC = "\x1B";
|
|
299
|
+
const CSI = `${ESC}[`;
|
|
300
|
+
const beep = "\x07";
|
|
301
|
+
const cursor = {
|
|
302
|
+
to(x, y) {
|
|
303
|
+
if (!y) return `${CSI}${x + 1}G`;
|
|
304
|
+
return `${CSI}${y + 1};${x + 1}H`;
|
|
305
|
+
},
|
|
306
|
+
move(x, y) {
|
|
307
|
+
let ret = "";
|
|
308
|
+
if (x < 0) ret += `${CSI}${-x}D`;
|
|
309
|
+
else if (x > 0) ret += `${CSI}${x}C`;
|
|
310
|
+
if (y < 0) ret += `${CSI}${-y}A`;
|
|
311
|
+
else if (y > 0) ret += `${CSI}${y}B`;
|
|
312
|
+
return ret;
|
|
313
|
+
},
|
|
314
|
+
up: (count = 1) => `${CSI}${count}A`,
|
|
315
|
+
down: (count = 1) => `${CSI}${count}B`,
|
|
316
|
+
forward: (count = 1) => `${CSI}${count}C`,
|
|
317
|
+
backward: (count = 1) => `${CSI}${count}D`,
|
|
318
|
+
nextLine: (count = 1) => `${CSI}E`.repeat(count),
|
|
319
|
+
prevLine: (count = 1) => `${CSI}F`.repeat(count),
|
|
320
|
+
left: `${CSI}G`,
|
|
321
|
+
hide: `${CSI}?25l`,
|
|
322
|
+
show: `${CSI}?25h`,
|
|
323
|
+
save: `${ESC}7`,
|
|
324
|
+
restore: `${ESC}8`
|
|
325
|
+
};
|
|
326
|
+
module.exports = {
|
|
327
|
+
cursor,
|
|
328
|
+
scroll: {
|
|
329
|
+
up: (count = 1) => `${CSI}S`.repeat(count),
|
|
330
|
+
down: (count = 1) => `${CSI}T`.repeat(count)
|
|
331
|
+
},
|
|
332
|
+
erase: {
|
|
333
|
+
screen: `${CSI}2J`,
|
|
334
|
+
up: (count = 1) => `${CSI}1J`.repeat(count),
|
|
335
|
+
down: (count = 1) => `${CSI}J`.repeat(count),
|
|
336
|
+
line: `${CSI}2K`,
|
|
337
|
+
lineEnd: `${CSI}K`,
|
|
338
|
+
lineStart: `${CSI}1K`,
|
|
339
|
+
lines(count) {
|
|
340
|
+
let clear = "";
|
|
341
|
+
for (let i = 0; i < count; i++) clear += this.line + (i < count - 1 ? cursor.up() : "");
|
|
342
|
+
if (count) clear += cursor.left;
|
|
343
|
+
return clear;
|
|
344
|
+
}
|
|
345
|
+
},
|
|
346
|
+
beep
|
|
347
|
+
};
|
|
348
|
+
})))();
|
|
349
|
+
const settings = {
|
|
350
|
+
actions: /* @__PURE__ */ new Set([
|
|
351
|
+
"up",
|
|
352
|
+
"down",
|
|
353
|
+
"left",
|
|
354
|
+
"right",
|
|
355
|
+
"space",
|
|
356
|
+
"enter",
|
|
357
|
+
"cancel"
|
|
358
|
+
]),
|
|
359
|
+
aliases: /* @__PURE__ */ new Map([
|
|
360
|
+
["k", "up"],
|
|
361
|
+
["j", "down"],
|
|
362
|
+
["h", "left"],
|
|
363
|
+
["l", "right"],
|
|
364
|
+
["", "cancel"],
|
|
365
|
+
["escape", "cancel"]
|
|
366
|
+
]),
|
|
367
|
+
messages: {
|
|
368
|
+
cancel: "Canceled",
|
|
369
|
+
error: "Something went wrong"
|
|
370
|
+
},
|
|
371
|
+
withGuide: true,
|
|
372
|
+
accessible: void 0,
|
|
373
|
+
date: {
|
|
374
|
+
monthNames: [...[
|
|
375
|
+
"January",
|
|
376
|
+
"February",
|
|
377
|
+
"March",
|
|
378
|
+
"April",
|
|
379
|
+
"May",
|
|
380
|
+
"June",
|
|
381
|
+
"July",
|
|
382
|
+
"August",
|
|
383
|
+
"September",
|
|
384
|
+
"October",
|
|
385
|
+
"November",
|
|
386
|
+
"December"
|
|
387
|
+
]],
|
|
388
|
+
messages: {
|
|
389
|
+
required: "Please enter a valid date",
|
|
390
|
+
invalidMonth: "There are only 12 months in a year",
|
|
391
|
+
invalidDay: (n, e) => `There are only ${n} days in ${e}`,
|
|
392
|
+
afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
|
|
393
|
+
beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
};
|
|
397
|
+
function isAccessible(n) {
|
|
398
|
+
if (n !== void 0) return n;
|
|
399
|
+
if (settings.accessible !== void 0) return settings.accessible;
|
|
400
|
+
const e = process.env.ACCESSIBLE;
|
|
401
|
+
return e !== void 0 && e !== "" && e !== "0" && e !== "false";
|
|
402
|
+
}
|
|
403
|
+
function isActionKey(n, e) {
|
|
404
|
+
if (typeof n == "string") return settings.aliases.get(n) === e;
|
|
405
|
+
for (const s of n) if (s !== void 0 && isActionKey(s, e)) return true;
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
function diffLines(i, s) {
|
|
409
|
+
if (i === s) return;
|
|
410
|
+
const e = i.split(`
|
|
411
|
+
`), t = s.split(`
|
|
412
|
+
`), r = Math.max(e.length, t.length), f = [];
|
|
413
|
+
for (let n = 0; n < r; n++) e[n] !== t[n] && f.push(n);
|
|
414
|
+
return {
|
|
415
|
+
lines: f,
|
|
416
|
+
numLinesBefore: e.length,
|
|
417
|
+
numLinesAfter: t.length,
|
|
418
|
+
numLines: r
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
const R = globalThis.process.platform.startsWith("win");
|
|
422
|
+
const CANCEL_SYMBOL = Symbol("clack:cancel");
|
|
423
|
+
function setRawMode(e, r) {
|
|
424
|
+
const o = e;
|
|
425
|
+
o.isTTY && o.setRawMode(r);
|
|
426
|
+
}
|
|
427
|
+
function block({ input: e = stdin, output: r = stdout, overwrite: o = true, hideCursor: n = true } = {}) {
|
|
428
|
+
const s = l.createInterface({
|
|
429
|
+
input: e,
|
|
430
|
+
output: r,
|
|
431
|
+
prompt: "",
|
|
432
|
+
tabSize: 1
|
|
433
|
+
});
|
|
434
|
+
l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
|
|
435
|
+
const t = (f, { name: a, sequence: w }) => {
|
|
436
|
+
if (isActionKey([
|
|
437
|
+
String(f),
|
|
438
|
+
a,
|
|
439
|
+
w
|
|
440
|
+
], "cancel")) {
|
|
441
|
+
n && r.write(import_src.cursor.show), process.exit(0);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
if (!o) return;
|
|
445
|
+
const i = a === "return" ? 0 : -1, m = a === "return" ? -1 : 0;
|
|
446
|
+
l.moveCursor(r, i, m, () => {
|
|
447
|
+
l.clearLine(r, 1, () => {
|
|
448
|
+
e.once("keypress", t);
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
};
|
|
452
|
+
return n && r.write(import_src.cursor.hide), e.once("keypress", t), () => {
|
|
453
|
+
e.off("keypress", t), n && r.write(import_src.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
const getColumns = (e) => "columns" in e && typeof e.columns == "number" ? e.columns : 80;
|
|
457
|
+
const getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
|
|
458
|
+
function runValidation(e, a) {
|
|
459
|
+
if ("~standard" in e) {
|
|
460
|
+
const n = e["~standard"].validate(a);
|
|
461
|
+
return n instanceof Promise ? n.then((r) => r.issues?.at(0)?.message) : n.issues?.at(0)?.message;
|
|
462
|
+
}
|
|
463
|
+
return e(a);
|
|
464
|
+
}
|
|
465
|
+
var y = class {
|
|
466
|
+
input;
|
|
467
|
+
output;
|
|
468
|
+
_abortSignal;
|
|
469
|
+
rl;
|
|
470
|
+
opts;
|
|
471
|
+
_render;
|
|
472
|
+
_track = false;
|
|
473
|
+
_prevFrame = "";
|
|
474
|
+
_subscribers = /* @__PURE__ */ new Map();
|
|
475
|
+
_cursor = 0;
|
|
476
|
+
state = "initial";
|
|
477
|
+
error = "";
|
|
478
|
+
value;
|
|
479
|
+
userInput = "";
|
|
480
|
+
/**
|
|
481
|
+
* Whether accessible (static, screen-reader friendly) output is enabled for
|
|
482
|
+
* this prompt, resolved from the `accessible` option, the global setting,
|
|
483
|
+
* and the `ACCESSIBLE` env var.
|
|
484
|
+
*/
|
|
485
|
+
get accessible() {
|
|
486
|
+
return isAccessible(this.opts.accessible);
|
|
487
|
+
}
|
|
488
|
+
constructor(t, e = true) {
|
|
489
|
+
const { input: i = stdin, output: s = stdout, render: r, signal: n, ...o } = t;
|
|
490
|
+
this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = r.bind(this), this._track = e, this._abortSignal = n, this.input = i, this.output = s;
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Unsubscribe all listeners
|
|
494
|
+
*/
|
|
495
|
+
unsubscribe() {
|
|
496
|
+
this._subscribers.clear();
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Set a subscriber with opts
|
|
500
|
+
* @param event - The event name
|
|
501
|
+
*/
|
|
502
|
+
setSubscriber(t, e) {
|
|
503
|
+
const i = this._subscribers.get(t) ?? [];
|
|
504
|
+
i.push(e), this._subscribers.set(t, i);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Subscribe to an event
|
|
508
|
+
* @param event - The event name
|
|
509
|
+
* @param cb - The callback
|
|
510
|
+
*/
|
|
511
|
+
on(t, e) {
|
|
512
|
+
this.setSubscriber(t, { cb: e });
|
|
513
|
+
}
|
|
514
|
+
/**
|
|
515
|
+
* Subscribe to an event once
|
|
516
|
+
* @param event - The event name
|
|
517
|
+
* @param cb - The callback
|
|
518
|
+
*/
|
|
519
|
+
once(t, e) {
|
|
520
|
+
this.setSubscriber(t, {
|
|
521
|
+
cb: e,
|
|
522
|
+
once: true
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* Emit an event with data
|
|
527
|
+
* @param event - The event name
|
|
528
|
+
* @param data - The data to pass to the callback
|
|
529
|
+
*/
|
|
530
|
+
emit(t, ...e) {
|
|
531
|
+
const i = this._subscribers.get(t) ?? [], s = [];
|
|
532
|
+
for (const r of i) r.cb(...e), r.once && s.push(() => i.splice(i.indexOf(r), 1));
|
|
533
|
+
for (const r of s) r();
|
|
534
|
+
}
|
|
535
|
+
prompt() {
|
|
536
|
+
return new Promise((t) => {
|
|
537
|
+
if (this._abortSignal) {
|
|
538
|
+
if (this._abortSignal.aborted) return this.state = "cancel", this.close(), t(CANCEL_SYMBOL);
|
|
539
|
+
this._abortSignal.addEventListener("abort", () => {
|
|
540
|
+
this.state = "cancel", this.close();
|
|
541
|
+
}, { once: true });
|
|
542
|
+
}
|
|
543
|
+
this.rl = l__default.createInterface({
|
|
544
|
+
input: this.input,
|
|
545
|
+
tabSize: 2,
|
|
546
|
+
prompt: "",
|
|
547
|
+
escapeCodeTimeout: 50,
|
|
548
|
+
terminal: true
|
|
549
|
+
}), this.rl.prompt(), this.opts.initialUserInput !== void 0 && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
|
|
550
|
+
this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(this.value);
|
|
551
|
+
}), this.once("cancel", () => {
|
|
552
|
+
this.output.write(import_src.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(CANCEL_SYMBOL);
|
|
553
|
+
});
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
_isActionKey(t, e) {
|
|
557
|
+
return t === " ";
|
|
558
|
+
}
|
|
559
|
+
_shouldSubmit(t, e) {
|
|
560
|
+
return true;
|
|
561
|
+
}
|
|
562
|
+
_setValue(t) {
|
|
563
|
+
this.value = t, this.emit("value", this.value);
|
|
564
|
+
}
|
|
565
|
+
_setUserInput(t, e) {
|
|
566
|
+
this.userInput = t ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
|
|
567
|
+
}
|
|
568
|
+
_clearUserInput() {
|
|
569
|
+
this.rl?.write(null, {
|
|
570
|
+
ctrl: true,
|
|
571
|
+
name: "u"
|
|
572
|
+
}), this._setUserInput("");
|
|
573
|
+
}
|
|
574
|
+
async onKeypress(t, e) {
|
|
575
|
+
if (this.state !== "validating") {
|
|
576
|
+
if (this._track && e.name !== "return" && (e.name && this._isActionKey(t, e) && this.rl?.write(null, {
|
|
577
|
+
ctrl: true,
|
|
578
|
+
name: "h"
|
|
579
|
+
}), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t && (t.toLowerCase() === "y" || t.toLowerCase() === "n") && this.emit("confirm", t.toLowerCase() === "y"), this.emit("key", t, e), e?.name === "return" && this._shouldSubmit(t, e)) {
|
|
580
|
+
if (this.opts.validate) {
|
|
581
|
+
const i = runValidation(this.opts.validate, this.value);
|
|
582
|
+
let s;
|
|
583
|
+
i instanceof Promise ? (this.state = "validating", this.render(), s = await i) : s = i, s && (this.error = s instanceof Error ? s.message : s, this.state = "error", this.rl?.write(this.userInput));
|
|
584
|
+
}
|
|
585
|
+
this.state !== "error" && (this.state = "submit");
|
|
586
|
+
}
|
|
587
|
+
isActionKey([
|
|
588
|
+
t,
|
|
589
|
+
e?.name,
|
|
590
|
+
e?.sequence
|
|
591
|
+
], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
close() {
|
|
595
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
596
|
+
`), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
597
|
+
}
|
|
598
|
+
restoreCursor() {
|
|
599
|
+
const t = wrapAnsi(this._prevFrame, process.stdout.columns, {
|
|
600
|
+
hard: true,
|
|
601
|
+
trim: false
|
|
602
|
+
}).split(`
|
|
603
|
+
`).length - 1;
|
|
604
|
+
this.output.write(import_src.cursor.move(-999, t * -1));
|
|
605
|
+
}
|
|
606
|
+
render() {
|
|
607
|
+
const t = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
|
|
608
|
+
hard: true,
|
|
609
|
+
trim: false
|
|
610
|
+
});
|
|
611
|
+
if (t !== this._prevFrame) {
|
|
612
|
+
if (this.state === "initial") this.output.write(import_src.cursor.hide);
|
|
613
|
+
else {
|
|
614
|
+
const e = diffLines(this._prevFrame, t), i = getRows(this.output);
|
|
615
|
+
if (this.restoreCursor(), e) {
|
|
616
|
+
const s = Math.max(0, e.numLinesAfter - i), r = Math.max(0, e.numLinesBefore - i);
|
|
617
|
+
let n = e.lines.find((o) => o >= s);
|
|
618
|
+
if (n === void 0) {
|
|
619
|
+
this._prevFrame = t;
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
if (e.lines.length === 1) {
|
|
623
|
+
this.output.write(import_src.cursor.move(0, n - r)), this.output.write(import_src.erase.lines(1));
|
|
624
|
+
const o = t.split(`
|
|
625
|
+
`);
|
|
626
|
+
this.output.write(o[n]), this._prevFrame = t, this.output.write(import_src.cursor.move(0, o.length - n - 1));
|
|
627
|
+
return;
|
|
628
|
+
} else if (e.lines.length > 1) {
|
|
629
|
+
if (s < r) n = s;
|
|
630
|
+
else {
|
|
631
|
+
const h = n - r;
|
|
632
|
+
h > 0 && this.output.write(import_src.cursor.move(0, h));
|
|
633
|
+
}
|
|
634
|
+
this.output.write(import_src.erase.down());
|
|
635
|
+
const f = t.split(`
|
|
636
|
+
`).slice(n);
|
|
637
|
+
this.output.write(f.join(`
|
|
638
|
+
`)), this._prevFrame = t;
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
this.output.write(import_src.erase.down());
|
|
643
|
+
}
|
|
644
|
+
this.output.write(t), this.state === "initial" && (this.state = "active"), this._prevFrame = t;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
var n = class extends y {
|
|
649
|
+
get userInputWithCursor() {
|
|
650
|
+
if (this.state === "submit") return this.userInput;
|
|
651
|
+
const t = this.userInput;
|
|
652
|
+
if (this.cursor >= t.length) return `${this.userInput}\u2588`;
|
|
653
|
+
const r = t.slice(0, this.cursor), s = t.slice(this.cursor, this.cursor + 1), e = t.slice(this.cursor + 1);
|
|
654
|
+
return `${r}${styleText("inverse", s)}${e}`;
|
|
655
|
+
}
|
|
656
|
+
get cursor() {
|
|
657
|
+
return this._cursor;
|
|
658
|
+
}
|
|
659
|
+
constructor(t) {
|
|
660
|
+
super({
|
|
661
|
+
...t,
|
|
662
|
+
initialUserInput: t.initialUserInput ?? t.initialValue
|
|
663
|
+
}), this.on("userInput", (r) => {
|
|
664
|
+
this._setValue(r);
|
|
665
|
+
}), this.on("finalize", () => {
|
|
666
|
+
this.value || (this.value = t.defaultValue), this.value === void 0 && (this.value = "");
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
};
|
|
670
|
+
//#endregion
|
|
671
|
+
//#region ../../node_modules/.pnpm/@clack+prompts@1.8.1/node_modules/@clack/prompts/dist/index.mjs
|
|
672
|
+
function isUnicodeSupported() {
|
|
673
|
+
if (process$1.platform !== "win32") return process$1.env.TERM !== "linux";
|
|
674
|
+
return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
|
|
675
|
+
}
|
|
676
|
+
const unicode = isUnicodeSupported();
|
|
677
|
+
const isCI = () => process.env.CI === "true";
|
|
678
|
+
const unicodeOr = (o, e) => unicode ? o : e;
|
|
679
|
+
const S_STEP_ACTIVE = unicodeOr("◆", "*");
|
|
680
|
+
const S_STEP_CANCEL = unicodeOr("■", "x");
|
|
681
|
+
const S_STEP_ERROR = unicodeOr("▲", "x");
|
|
682
|
+
const S_STEP_SUBMIT = unicodeOr("◇", "o");
|
|
683
|
+
const S_BAR_START = unicodeOr("┌", "T");
|
|
684
|
+
const S_BAR = unicodeOr("│", "|");
|
|
685
|
+
const S_BAR_END = unicodeOr("└", "—");
|
|
686
|
+
const S_BAR_H = unicodeOr("─", "-");
|
|
687
|
+
const S_CORNER_TOP_RIGHT = unicodeOr("╮", "+");
|
|
688
|
+
const S_CONNECT_LEFT = unicodeOr("├", "+");
|
|
689
|
+
const S_CORNER_BOTTOM_RIGHT = unicodeOr("╯", "+");
|
|
690
|
+
const S_CORNER_BOTTOM_LEFT = unicodeOr("╰", "+");
|
|
691
|
+
const S_INFO = unicodeOr("●", "•");
|
|
692
|
+
const S_SUCCESS = unicodeOr("◆", "*");
|
|
693
|
+
const S_WARN = unicodeOr("▲", "!");
|
|
694
|
+
const S_ERROR = unicodeOr("■", "x");
|
|
695
|
+
const symbol = (o) => {
|
|
696
|
+
switch (o) {
|
|
697
|
+
case "initial":
|
|
698
|
+
case "active": return styleText("cyan", S_STEP_ACTIVE);
|
|
699
|
+
case "cancel": return styleText("red", S_STEP_CANCEL);
|
|
700
|
+
case "error": return styleText("yellow", S_STEP_ERROR);
|
|
701
|
+
case "submit": return styleText("green", S_STEP_SUBMIT);
|
|
702
|
+
case "validating": return styleText("dim", S_STEP_ACTIVE);
|
|
703
|
+
}
|
|
704
|
+
};
|
|
705
|
+
`${styleText("dim", "↑/↓")}`, `${styleText("dim", "Space:")}`, `${styleText("dim", "Enter:")}`;
|
|
706
|
+
const log = {
|
|
707
|
+
message: (s = [], { symbol: e = styleText("gray", S_BAR), secondarySymbol: r = styleText("gray", S_BAR), output: m = process.stdout, spacing: l = 1, withGuide: c } = {}) => {
|
|
708
|
+
const t = [], o = c ?? settings.withGuide, f = o ? r : "", O = o ? `${e} ` : "", u = o ? `${r} ` : "";
|
|
709
|
+
for (let i = 0; i < l; i++) t.push(f);
|
|
710
|
+
const g = Array.isArray(s) ? s : s.split(`
|
|
711
|
+
`);
|
|
712
|
+
if (g.length > 0) {
|
|
713
|
+
const [i, ...y] = g;
|
|
714
|
+
i.length > 0 ? t.push(`${O}${i}`) : t.push(o ? e : "");
|
|
715
|
+
for (const p of y) p.length > 0 ? t.push(`${u}${p}`) : t.push(o ? r : "");
|
|
716
|
+
}
|
|
717
|
+
m.write(`${t.join(`
|
|
718
|
+
`)}
|
|
719
|
+
`);
|
|
720
|
+
},
|
|
721
|
+
info: (s, e) => {
|
|
722
|
+
log.message(s, {
|
|
723
|
+
...e,
|
|
724
|
+
symbol: styleText("blue", S_INFO)
|
|
725
|
+
});
|
|
726
|
+
},
|
|
727
|
+
success: (s, e) => {
|
|
728
|
+
log.message(s, {
|
|
729
|
+
...e,
|
|
730
|
+
symbol: styleText("green", S_SUCCESS)
|
|
731
|
+
});
|
|
732
|
+
},
|
|
733
|
+
step: (s, e) => {
|
|
734
|
+
log.message(s, {
|
|
735
|
+
...e,
|
|
736
|
+
symbol: styleText("green", S_STEP_SUBMIT)
|
|
737
|
+
});
|
|
738
|
+
},
|
|
739
|
+
warn: (s, e) => {
|
|
740
|
+
log.message(s, {
|
|
741
|
+
...e,
|
|
742
|
+
symbol: styleText("yellow", S_WARN)
|
|
743
|
+
});
|
|
744
|
+
},
|
|
745
|
+
/** alias for `log.warn()`. */
|
|
746
|
+
warning: (s, e) => {
|
|
747
|
+
log.warn(s, e);
|
|
748
|
+
},
|
|
749
|
+
error: (s, e) => {
|
|
750
|
+
log.message(s, {
|
|
751
|
+
...e,
|
|
752
|
+
symbol: styleText("red", S_ERROR)
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
};
|
|
756
|
+
const cancel = (o = "", t) => {
|
|
757
|
+
const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_END)} ` : "";
|
|
758
|
+
i.write(`${e}${styleText("red", o)}
|
|
759
|
+
|
|
760
|
+
`);
|
|
761
|
+
};
|
|
762
|
+
const intro = (o = "", t) => {
|
|
763
|
+
const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_START)} ` : "";
|
|
764
|
+
i.write(`${e}${o}
|
|
765
|
+
`);
|
|
766
|
+
};
|
|
767
|
+
const outro = (o = "", t) => {
|
|
768
|
+
const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR)}
|
|
769
|
+
${styleText("gray", S_BAR_END)} ` : "";
|
|
770
|
+
i.write(`${e}${o}
|
|
771
|
+
|
|
772
|
+
`);
|
|
773
|
+
};
|
|
774
|
+
const W$1 = (o) => o;
|
|
775
|
+
const C = (o, e, s) => {
|
|
776
|
+
const a = {
|
|
777
|
+
hard: true,
|
|
778
|
+
trim: false
|
|
779
|
+
}, i = wrapAnsi(o, e, a).split(`
|
|
780
|
+
`), c = i.reduce((n, t) => Math.max(fastStringWidth(t), n), 0);
|
|
781
|
+
return wrapAnsi(o, e - (i.map(s).reduce((n, t) => Math.max(fastStringWidth(t), n), 0) - c), a);
|
|
782
|
+
};
|
|
783
|
+
const note = (o = "", e = "", s) => {
|
|
784
|
+
const a = s?.output ?? process$1.stdout, i = s?.withGuide ?? settings.withGuide, c = s?.format ?? W$1, g = [
|
|
785
|
+
"",
|
|
786
|
+
...C(o, getColumns(a) - 6, c).split(`
|
|
787
|
+
`).map(c),
|
|
788
|
+
""
|
|
789
|
+
], n = fastStringWidth(e), t = Math.max(g.reduce((m, F) => {
|
|
790
|
+
const O = fastStringWidth(F);
|
|
791
|
+
return O > m ? O : m;
|
|
792
|
+
}, 0), n) + 2, h = g.map((m) => `${styleText("gray", S_BAR)} ${m}${" ".repeat(t - fastStringWidth(m))}${styleText("gray", S_BAR)}`).join(`
|
|
793
|
+
`), T = i ? `${styleText("gray", S_BAR)}
|
|
794
|
+
` : "", l$1 = i ? S_CONNECT_LEFT : S_CORNER_BOTTOM_LEFT;
|
|
795
|
+
a.write(`${T}${styleText("green", S_STEP_SUBMIT)} ${styleText("reset", e)} ${styleText("gray", S_BAR_H.repeat(Math.max(t - n - 1, 1)) + S_CORNER_TOP_RIGHT)}
|
|
796
|
+
${h}
|
|
797
|
+
${styleText("gray", l$1 + S_BAR_H.repeat(t + 2) + S_CORNER_BOTTOM_RIGHT)}
|
|
798
|
+
`);
|
|
799
|
+
};
|
|
800
|
+
const W = (l) => styleText("magenta", l);
|
|
801
|
+
const spinner = ({ indicator: l = "dots", onCancel: h, output: n = process.stdout, cancelMessage: G, errorMessage: O, frames: E = unicode ? [
|
|
802
|
+
"◒",
|
|
803
|
+
"◐",
|
|
804
|
+
"◓",
|
|
805
|
+
"◑"
|
|
806
|
+
] : [
|
|
807
|
+
"•",
|
|
808
|
+
"o",
|
|
809
|
+
"O",
|
|
810
|
+
"0"
|
|
811
|
+
], delay: F = unicode ? 80 : 120, signal: m, ...I } = {}) => {
|
|
812
|
+
const u = isCI();
|
|
813
|
+
let M, T, d = false, S = false, s = "", p, w = performance.now();
|
|
814
|
+
const x = getColumns(n), k = I?.styleFrame ?? W, g = (e) => {
|
|
815
|
+
const r = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
|
|
816
|
+
S = e === 1, d && (a(r, e), S && typeof h == "function" && h());
|
|
817
|
+
}, f = () => g(2), i = () => g(1), A = () => {
|
|
818
|
+
process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i), process.on("SIGTERM", i), process.on("exit", g), m && m.addEventListener("abort", i);
|
|
819
|
+
}, H = () => {
|
|
820
|
+
process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i), process.removeListener("SIGTERM", i), process.removeListener("exit", g), m && m.removeEventListener("abort", i);
|
|
821
|
+
}, y = () => {
|
|
822
|
+
if (p === void 0) return;
|
|
823
|
+
u && n.write(`
|
|
824
|
+
`);
|
|
825
|
+
const r = wrapAnsi(p, x, {
|
|
826
|
+
hard: true,
|
|
827
|
+
trim: false
|
|
828
|
+
}).split(`
|
|
829
|
+
`);
|
|
830
|
+
r.length > 1 && n.write(import_src.cursor.up(r.length - 1)), n.write(import_src.cursor.to(0)), n.write(import_src.erase.down());
|
|
831
|
+
}, C = (e) => e.replace(/\.+$/, ""), _ = (e) => {
|
|
832
|
+
const r = (performance.now() - e) / 1e3, t = Math.floor(r / 60), o = Math.floor(r % 60);
|
|
833
|
+
return t > 0 ? `[${t}m ${o}s]` : `[${o}s]`;
|
|
834
|
+
}, N = I.withGuide ?? settings.withGuide, P = (e = "") => {
|
|
835
|
+
d = true, M = block({ output: n }), s = C(e), w = performance.now(), N && n.write(`${styleText("gray", S_BAR)}
|
|
836
|
+
`);
|
|
837
|
+
let r = 0, t = 0;
|
|
838
|
+
A(), T = setInterval(() => {
|
|
839
|
+
if (u && s === p) return;
|
|
840
|
+
y(), p = s;
|
|
841
|
+
const o = k(E[r]);
|
|
842
|
+
let v;
|
|
843
|
+
if (u) v = `${o} ${s}...`;
|
|
844
|
+
else if (l === "timer") v = `${o} ${s} ${_(w)}`;
|
|
845
|
+
else {
|
|
846
|
+
const B = ".".repeat(Math.floor(t)).slice(0, 3);
|
|
847
|
+
v = `${o} ${s}${B}`;
|
|
848
|
+
}
|
|
849
|
+
const j = wrapAnsi(v, x, {
|
|
850
|
+
hard: true,
|
|
851
|
+
trim: false
|
|
852
|
+
});
|
|
853
|
+
n.write(j), r = r + 1 < E.length ? r + 1 : 0, t = t < 4 ? t + .125 : 0;
|
|
854
|
+
}, F);
|
|
855
|
+
}, a = (e = "", r = 0, t = false) => {
|
|
856
|
+
if (!d) return;
|
|
857
|
+
d = false, clearInterval(T), y();
|
|
858
|
+
const o = r === 0 ? styleText("green", S_STEP_SUBMIT) : r === 1 ? styleText("red", S_STEP_CANCEL) : styleText("red", S_STEP_ERROR);
|
|
859
|
+
s = e ?? s, t || (l === "timer" ? n.write(`${o} ${s} ${_(w)}
|
|
860
|
+
`) : n.write(`${o} ${s}
|
|
861
|
+
`)), H(), M();
|
|
862
|
+
};
|
|
863
|
+
return {
|
|
864
|
+
start: P,
|
|
865
|
+
stop: (e = "") => a(e, 0),
|
|
866
|
+
message: (e = "") => {
|
|
867
|
+
s = C(e ?? s);
|
|
868
|
+
},
|
|
869
|
+
cancel: (e = "") => a(e, 1),
|
|
870
|
+
error: (e = "") => a(e, 2),
|
|
871
|
+
clear: () => a("", 0, true),
|
|
872
|
+
get isCancelled() {
|
|
873
|
+
return S;
|
|
874
|
+
}
|
|
875
|
+
};
|
|
876
|
+
};
|
|
877
|
+
`${styleText("dim", "↑/↓")}`, `${styleText("dim", "Enter:")}`;
|
|
878
|
+
`${styleText("gray", S_BAR)}`;
|
|
879
|
+
const text = (t) => new n({
|
|
880
|
+
validate: t.validate,
|
|
881
|
+
placeholder: t.placeholder,
|
|
882
|
+
defaultValue: t.defaultValue,
|
|
883
|
+
initialValue: t.initialValue,
|
|
884
|
+
output: t.output,
|
|
885
|
+
signal: t.signal,
|
|
886
|
+
input: t.input,
|
|
887
|
+
render() {
|
|
888
|
+
const r = t?.withGuide ?? settings.withGuide, l = `${`${r ? `${styleText("gray", S_BAR)}
|
|
889
|
+
` : ""}${symbol(this.state)} `}${t.message}
|
|
890
|
+
`, d = t.placeholder && t.placeholder.length > 0 ? styleText("inverse", t.placeholder[0]) + styleText("dim", t.placeholder.slice(1)) : styleText(["inverse", "hidden"], "_"), o = this.userInput ? this.userInputWithCursor : d, s = this.value ?? "";
|
|
891
|
+
switch (this.state) {
|
|
892
|
+
case "validating": {
|
|
893
|
+
const n = r ? `${styleText("cyan", S_BAR)} ` : "", i = r ? styleText("cyan", S_BAR_END) : "";
|
|
894
|
+
return `${l}${n}${styleText("dim", o)}
|
|
895
|
+
${i} ${styleText("dim", "Validating...")}
|
|
896
|
+
`;
|
|
897
|
+
}
|
|
898
|
+
case "error": {
|
|
899
|
+
const n = this.error ? ` ${styleText("yellow", this.error)}` : "", i = r ? `${styleText("yellow", S_BAR)} ` : "", c = r ? styleText("yellow", S_BAR_END) : "";
|
|
900
|
+
return `${l.trim()}
|
|
901
|
+
${i}${o}
|
|
902
|
+
${c}${n}
|
|
903
|
+
`;
|
|
904
|
+
}
|
|
905
|
+
case "submit": {
|
|
906
|
+
const n = s ? `${r ? " " : ""}${styleText("dim", s)}` : "";
|
|
907
|
+
return `${l}${r ? styleText("gray", S_BAR) : ""}${n}`;
|
|
908
|
+
}
|
|
909
|
+
case "cancel": {
|
|
910
|
+
const n = s ? ` ${styleText(["strikethrough", "dim"], s)}` : "", i = r ? styleText("gray", S_BAR) : "";
|
|
911
|
+
return `${l}${i}${n}${s.trim() ? `
|
|
912
|
+
${i}` : ""}`;
|
|
913
|
+
}
|
|
914
|
+
default: return `${l}${r ? `${styleText("cyan", S_BAR)} ` : ""}${o}
|
|
915
|
+
${r ? styleText("cyan", S_BAR_END) : ""}
|
|
916
|
+
`;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}).prompt();
|
|
920
|
+
//#endregion
|
|
921
|
+
//#region src/package-manager.ts
|
|
922
|
+
const PACKAGE_MANAGERS = [
|
|
923
|
+
"npm",
|
|
924
|
+
"pnpm",
|
|
925
|
+
"yarn",
|
|
926
|
+
"bun"
|
|
927
|
+
];
|
|
928
|
+
function isPackageManager(value) {
|
|
929
|
+
return PACKAGE_MANAGERS.includes(value);
|
|
930
|
+
}
|
|
931
|
+
/**
|
|
932
|
+
* The package manager that ran `create`: `npm create`, `pnpm create`, `yarn create` and `bun create` each set
|
|
933
|
+
* `npm_config_user_agent` (`pnpm/12.14.0 npm/? node/v22…`). npm when it is missing or unknown.
|
|
934
|
+
*/
|
|
935
|
+
function detectPackageManager(userAgent) {
|
|
936
|
+
const name = userAgent?.split("/")[0]?.trim() ?? "";
|
|
937
|
+
return isPackageManager(name) ? name : "npm";
|
|
938
|
+
}
|
|
939
|
+
/** The command a person types to run a package script, as each package manager spells it. */
|
|
940
|
+
function runCommand(pm, script) {
|
|
941
|
+
return pm === "npm" || pm === "bun" ? `${pm} run ${script}` : `${pm} ${script}`;
|
|
942
|
+
}
|
|
943
|
+
//#endregion
|
|
944
|
+
//#region src/args.ts
|
|
945
|
+
var UsageError = class extends Error {};
|
|
946
|
+
const HELP = `Create a BearMinion site: an Astro website you edit by clicking on it.
|
|
947
|
+
|
|
948
|
+
Usage
|
|
949
|
+
npm create bearminion@latest [directory] -- [options]
|
|
950
|
+
|
|
951
|
+
Options
|
|
952
|
+
--name <name> Site name (default: from the directory)
|
|
953
|
+
--url <address> Public address, such as https://example.com (you can set it later in the editor)
|
|
954
|
+
--storybook Include Storybook, a workshop for the theme's components
|
|
955
|
+
--pm <manager> Package manager to install with: ${PACKAGE_MANAGERS.join(", ")} (default: the one you ran)
|
|
956
|
+
--no-install Do not install dependencies
|
|
957
|
+
--no-git Do not create a git repository
|
|
958
|
+
-y, --yes Ask nothing; use the defaults for anything not given
|
|
959
|
+
-h, --help Show this help
|
|
960
|
+
-v, --version Show the version
|
|
961
|
+
`;
|
|
962
|
+
/** Parses the arguments after the command. Unknown options and a bad `--pm` throw `UsageError`. */
|
|
963
|
+
function parseCliArgs(argv) {
|
|
964
|
+
let parsed;
|
|
965
|
+
try {
|
|
966
|
+
parsed = parse(argv);
|
|
967
|
+
} catch (error) {
|
|
968
|
+
throw new UsageError(error instanceof Error ? error.message : String(error));
|
|
969
|
+
}
|
|
970
|
+
const { values, positionals } = parsed;
|
|
971
|
+
if (positionals.length > 1) throw new UsageError(`Expected one directory, got ${positionals.length}: ${positionals.join(" ")}`);
|
|
972
|
+
const pm = values.pm;
|
|
973
|
+
if (pm !== void 0 && !isPackageManager(pm)) throw new UsageError(`Unknown package manager "${pm}". Use one of: ${PACKAGE_MANAGERS.join(", ")}.`);
|
|
974
|
+
return {
|
|
975
|
+
...positionals[0] !== void 0 ? { directory: positionals[0] } : {},
|
|
976
|
+
...values.name !== void 0 ? { name: values.name } : {},
|
|
977
|
+
...values.url !== void 0 ? { url: values.url } : {},
|
|
978
|
+
...pm !== void 0 ? { packageManager: pm } : {},
|
|
979
|
+
install: values.install,
|
|
980
|
+
git: values.git,
|
|
981
|
+
storybook: values.storybook,
|
|
982
|
+
yes: values.yes,
|
|
983
|
+
help: values.help,
|
|
984
|
+
version: values.version
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
function parse(argv) {
|
|
988
|
+
return parseArgs({
|
|
989
|
+
args: argv,
|
|
990
|
+
allowPositionals: true,
|
|
991
|
+
allowNegative: true,
|
|
992
|
+
strict: true,
|
|
993
|
+
options: {
|
|
994
|
+
name: { type: "string" },
|
|
995
|
+
url: { type: "string" },
|
|
996
|
+
pm: { type: "string" },
|
|
997
|
+
install: {
|
|
998
|
+
type: "boolean",
|
|
999
|
+
default: true
|
|
1000
|
+
},
|
|
1001
|
+
git: {
|
|
1002
|
+
type: "boolean",
|
|
1003
|
+
default: true
|
|
1004
|
+
},
|
|
1005
|
+
storybook: {
|
|
1006
|
+
type: "boolean",
|
|
1007
|
+
default: false
|
|
1008
|
+
},
|
|
1009
|
+
yes: {
|
|
1010
|
+
type: "boolean",
|
|
1011
|
+
short: "y",
|
|
1012
|
+
default: false
|
|
1013
|
+
},
|
|
1014
|
+
help: {
|
|
1015
|
+
type: "boolean",
|
|
1016
|
+
short: "h",
|
|
1017
|
+
default: false
|
|
1018
|
+
},
|
|
1019
|
+
version: {
|
|
1020
|
+
type: "boolean",
|
|
1021
|
+
short: "v",
|
|
1022
|
+
default: false
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
//#endregion
|
|
1028
|
+
//#region src/names.ts
|
|
1029
|
+
const FALLBACK_PACKAGE = "my-site";
|
|
1030
|
+
/** An npm package name for the site from its folder: lowercase, `-` for anything npm does not allow. */
|
|
1031
|
+
function toPackageName(directory) {
|
|
1032
|
+
const name = path.basename(path.resolve(directory)).toLowerCase().replace(/[^a-z0-9._~-]+/g, "-").replace(/^[._-]+/, "").replace(/-+$/, "").replace(/-{2,}/g, "-");
|
|
1033
|
+
return name.length > 0 && name.length <= 214 ? name : FALLBACK_PACKAGE;
|
|
1034
|
+
}
|
|
1035
|
+
/** A readable site name from the folder: `my-coffee-shop` becomes `My Coffee Shop`. */
|
|
1036
|
+
function toSiteName(directory) {
|
|
1037
|
+
const words = path.basename(path.resolve(directory)).split(/[-_\s.]+/).filter(Boolean);
|
|
1038
|
+
if (words.length === 0) return "My Site";
|
|
1039
|
+
return words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
1040
|
+
}
|
|
1041
|
+
/**
|
|
1042
|
+
* The site's public address as `site.json` stores it, or `null` when it is not a usable http(s) address.
|
|
1043
|
+
* A bare domain gets `https://`; a trailing slash is dropped.
|
|
1044
|
+
*/
|
|
1045
|
+
function normalizeUrl(input) {
|
|
1046
|
+
const trimmed = input.trim();
|
|
1047
|
+
if (trimmed === "") return null;
|
|
1048
|
+
const withScheme = /^[a-z][a-z0-9+.-]*:\/\//i.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
1049
|
+
let url;
|
|
1050
|
+
try {
|
|
1051
|
+
url = new URL(withScheme);
|
|
1052
|
+
} catch {
|
|
1053
|
+
return null;
|
|
1054
|
+
}
|
|
1055
|
+
if (url.protocol !== "https:" && url.protocol !== "http:") return null;
|
|
1056
|
+
if (!url.hostname.includes(".") && url.hostname !== "localhost") return null;
|
|
1057
|
+
if (url.search || url.hash || url.username || url.password) return null;
|
|
1058
|
+
const pathname = url.pathname.replace(/\/+$/, "");
|
|
1059
|
+
return `${url.origin}${pathname}`;
|
|
1060
|
+
}
|
|
1061
|
+
//#endregion
|
|
1062
|
+
//#region src/template.ts
|
|
1063
|
+
/**
|
|
1064
|
+
* npm leaves `.gitignore` and `.npmrc` out of published packages, so the bundled template stores them under these
|
|
1065
|
+
* names and `scaffold()` renames them back.
|
|
1066
|
+
*/
|
|
1067
|
+
const DOTFILE_RENAMES = {
|
|
1068
|
+
_gitignore: ".gitignore",
|
|
1069
|
+
_npmrc: ".npmrc"
|
|
1070
|
+
};
|
|
1071
|
+
//#endregion
|
|
1072
|
+
//#region src/scaffold.ts
|
|
1073
|
+
/** Storybook's files in the template. Left out unless the site is created with `--storybook`. */
|
|
1074
|
+
function isStorybookPath(relative) {
|
|
1075
|
+
const posix = relative.split(path.sep).join("/");
|
|
1076
|
+
return posix === ".storybook" || posix.startsWith(".storybook/") || posix === "src/stories" || posix.startsWith("src/stories/") || posix.endsWith(".stories.ts");
|
|
1077
|
+
}
|
|
1078
|
+
const STORYBOOK_DEPENDENCIES = [
|
|
1079
|
+
"storybook",
|
|
1080
|
+
"@storybook/builder-vite",
|
|
1081
|
+
"@storybook-astro/framework"
|
|
1082
|
+
];
|
|
1083
|
+
const STORYBOOK_SCRIPTS = ["storybook", "build-storybook"];
|
|
1084
|
+
/** The site's own `package.json`: its name, version 0.0.0, private, and Storybook only when asked for. */
|
|
1085
|
+
function transformPackageJson(pkg, options) {
|
|
1086
|
+
const next = {
|
|
1087
|
+
...pkg,
|
|
1088
|
+
name: options.name,
|
|
1089
|
+
version: "0.0.0",
|
|
1090
|
+
private: true
|
|
1091
|
+
};
|
|
1092
|
+
if (!options.storybook) {
|
|
1093
|
+
if (pkg.scripts) next.scripts = omit(pkg.scripts, STORYBOOK_SCRIPTS);
|
|
1094
|
+
if (pkg.devDependencies) next.devDependencies = omit(pkg.devDependencies, STORYBOOK_DEPENDENCIES);
|
|
1095
|
+
if (pkg.dependencies) next.dependencies = omit(pkg.dependencies, STORYBOOK_DEPENDENCIES);
|
|
1096
|
+
}
|
|
1097
|
+
return next;
|
|
1098
|
+
}
|
|
1099
|
+
/**
|
|
1100
|
+
* `content/site.json` for the new site. The template's name marks style ranges of "BearMinion" and its brand logo is
|
|
1101
|
+
* the BearMinion logo, so both go: the header shows the new name until the owner picks a logo or styles it.
|
|
1102
|
+
*/
|
|
1103
|
+
function transformSiteJson(site, options) {
|
|
1104
|
+
const { nameMarks: _marks, brandLogo: _logo, ...rest } = site;
|
|
1105
|
+
return {
|
|
1106
|
+
...rest,
|
|
1107
|
+
name: options.name,
|
|
1108
|
+
...options.url ? { url: options.url } : {},
|
|
1109
|
+
seo: {
|
|
1110
|
+
...site.seo,
|
|
1111
|
+
titleTemplate: `%s · ${options.name}`
|
|
1112
|
+
}
|
|
1113
|
+
};
|
|
1114
|
+
}
|
|
1115
|
+
/** Removes every `<!-- storybook:start -->` … `<!-- storybook:end -->` block, markers included. */
|
|
1116
|
+
function stripStorybookBlocks(markdown) {
|
|
1117
|
+
return markdown.replace(/\n?<!-- storybook:start -->[\s\S]*?<!-- storybook:end -->\n?/g, "\n").replace(/\n{3,}/g, "\n\n");
|
|
1118
|
+
}
|
|
1119
|
+
/** Entries that do not count against an "empty" target, such as a fresh `git init` or Finder's metadata. */
|
|
1120
|
+
const HARMLESS = /* @__PURE__ */ new Set([
|
|
1121
|
+
".git",
|
|
1122
|
+
".DS_Store",
|
|
1123
|
+
"Thumbs.db"
|
|
1124
|
+
]);
|
|
1125
|
+
/** The target's entries that would be overwritten or mixed in with the site. Empty when the target can be used. */
|
|
1126
|
+
async function blockingEntries(targetDir) {
|
|
1127
|
+
if (!existsSync(targetDir)) return [];
|
|
1128
|
+
return (await readdir(targetDir)).filter((entry) => !HARMLESS.has(entry)).sort();
|
|
1129
|
+
}
|
|
1130
|
+
async function scaffold(options) {
|
|
1131
|
+
const { templateDir, targetDir } = options;
|
|
1132
|
+
await cp(templateDir, targetDir, {
|
|
1133
|
+
recursive: true,
|
|
1134
|
+
filter: (file) => options.storybook || !isStorybookPath(path.relative(templateDir, file))
|
|
1135
|
+
});
|
|
1136
|
+
for (const [stored, real] of Object.entries(DOTFILE_RENAMES)) {
|
|
1137
|
+
const file = path.join(targetDir, stored);
|
|
1138
|
+
if (existsSync(file)) await rename(file, path.join(targetDir, real));
|
|
1139
|
+
}
|
|
1140
|
+
const pkgPath = path.join(targetDir, "package.json");
|
|
1141
|
+
const pkg = JSON.parse(await readFile(pkgPath, "utf8"));
|
|
1142
|
+
await writeFile(pkgPath, `${JSON.stringify(transformPackageJson(pkg, {
|
|
1143
|
+
name: options.packageName,
|
|
1144
|
+
storybook: options.storybook
|
|
1145
|
+
}), null, 2)}\n`);
|
|
1146
|
+
const sitePath = path.join(targetDir, "content", "site.json");
|
|
1147
|
+
const site = JSON.parse(await readFile(sitePath, "utf8"));
|
|
1148
|
+
const siteOptions = options.url ? {
|
|
1149
|
+
name: options.siteName,
|
|
1150
|
+
url: options.url
|
|
1151
|
+
} : { name: options.siteName };
|
|
1152
|
+
await writeFile(sitePath, `${stableStringify(transformSiteJson(site, siteOptions))}\n`);
|
|
1153
|
+
if (!options.storybook) {
|
|
1154
|
+
const readmePath = path.join(targetDir, "README.md");
|
|
1155
|
+
if (existsSync(readmePath)) await writeFile(readmePath, stripStorybookBlocks(await readFile(readmePath, "utf8")));
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
function omit(record, keys) {
|
|
1159
|
+
return Object.fromEntries(Object.entries(record).filter(([key]) => !keys.includes(key)));
|
|
1160
|
+
}
|
|
1161
|
+
/** 2-space JSON with object keys sorted, the layout the editor writes content files in. */
|
|
1162
|
+
function stableStringify(value) {
|
|
1163
|
+
return JSON.stringify(sortKeys(value), null, 2);
|
|
1164
|
+
}
|
|
1165
|
+
function sortKeys(value) {
|
|
1166
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
1167
|
+
if (value && typeof value === "object") return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortKeys(value[key])]));
|
|
1168
|
+
return value;
|
|
1169
|
+
}
|
|
1170
|
+
//#endregion
|
|
1171
|
+
//#region src/steps.ts
|
|
1172
|
+
/** Installs the site's dependencies. Output is captured so the spinner stays readable; a failure shows its tail. */
|
|
1173
|
+
function install(pm, cwd) {
|
|
1174
|
+
return new Promise((resolve) => {
|
|
1175
|
+
const child = spawn(pm, ["install"], {
|
|
1176
|
+
cwd,
|
|
1177
|
+
shell: process.platform === "win32",
|
|
1178
|
+
stdio: [
|
|
1179
|
+
"ignore",
|
|
1180
|
+
"pipe",
|
|
1181
|
+
"pipe"
|
|
1182
|
+
]
|
|
1183
|
+
});
|
|
1184
|
+
const chunks = [];
|
|
1185
|
+
const collect = (data) => {
|
|
1186
|
+
chunks.push(data.toString());
|
|
1187
|
+
if (chunks.length > 400) chunks.splice(0, chunks.length - 400);
|
|
1188
|
+
};
|
|
1189
|
+
child.stdout.on("data", collect);
|
|
1190
|
+
child.stderr.on("data", collect);
|
|
1191
|
+
child.on("error", (error) => resolve({
|
|
1192
|
+
ok: false,
|
|
1193
|
+
output: error.message
|
|
1194
|
+
}));
|
|
1195
|
+
child.on("close", (code) => resolve({
|
|
1196
|
+
ok: code === 0,
|
|
1197
|
+
output: tail(chunks.join(""), 20)
|
|
1198
|
+
}));
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
/** True when `cwd` is already inside a git work tree, so the site is part of a larger repository. */
|
|
1202
|
+
function insideGitRepository(cwd) {
|
|
1203
|
+
const result = spawnSync("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
1204
|
+
cwd,
|
|
1205
|
+
encoding: "utf8"
|
|
1206
|
+
});
|
|
1207
|
+
return result.status === 0 && result.stdout.trim() === "true";
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* `git init` on `main` and a first commit. Without a configured git user the commit is skipped and reported, and the
|
|
1211
|
+
* repository is still created.
|
|
1212
|
+
*/
|
|
1213
|
+
function initGit(cwd) {
|
|
1214
|
+
const run = (args) => spawnSync("git", args, {
|
|
1215
|
+
cwd,
|
|
1216
|
+
encoding: "utf8"
|
|
1217
|
+
});
|
|
1218
|
+
const init = run(["init", "--initial-branch=main"]);
|
|
1219
|
+
if (init.error || init.status !== 0) return {
|
|
1220
|
+
initialized: false,
|
|
1221
|
+
committed: false,
|
|
1222
|
+
reason: (init.error?.message ?? init.stderr).trim()
|
|
1223
|
+
};
|
|
1224
|
+
const add = run(["add", "--all"]);
|
|
1225
|
+
if (add.status !== 0) return {
|
|
1226
|
+
initialized: true,
|
|
1227
|
+
committed: false,
|
|
1228
|
+
reason: add.stderr.trim()
|
|
1229
|
+
};
|
|
1230
|
+
const commit = run([
|
|
1231
|
+
"commit",
|
|
1232
|
+
"--quiet",
|
|
1233
|
+
"--no-verify",
|
|
1234
|
+
"--message",
|
|
1235
|
+
"Initial commit from create-bearminion"
|
|
1236
|
+
]);
|
|
1237
|
+
if (commit.status !== 0) return {
|
|
1238
|
+
initialized: true,
|
|
1239
|
+
committed: false,
|
|
1240
|
+
reason: (commit.stderr || commit.stdout).trim()
|
|
1241
|
+
};
|
|
1242
|
+
return {
|
|
1243
|
+
initialized: true,
|
|
1244
|
+
committed: true
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
function tail(text, lines) {
|
|
1248
|
+
return text.trimEnd().split("\n").slice(-lines).join("\n");
|
|
1249
|
+
}
|
|
1250
|
+
//#endregion
|
|
1251
|
+
//#region src/cli.ts
|
|
1252
|
+
const packageRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
1253
|
+
const DEFAULT_DIRECTORY = "my-site";
|
|
1254
|
+
async function main() {
|
|
1255
|
+
let options;
|
|
1256
|
+
try {
|
|
1257
|
+
options = parseCliArgs(process.argv.slice(2));
|
|
1258
|
+
} catch (error) {
|
|
1259
|
+
if (!(error instanceof UsageError)) throw error;
|
|
1260
|
+
console.error(`${error.message}\n\n${HELP}`);
|
|
1261
|
+
return 1;
|
|
1262
|
+
}
|
|
1263
|
+
if (options.help) {
|
|
1264
|
+
console.log(HELP);
|
|
1265
|
+
return 0;
|
|
1266
|
+
}
|
|
1267
|
+
if (options.version) {
|
|
1268
|
+
console.log(JSON.parse(readFileSync(path.join(packageRoot, "package.json"), "utf8")).version);
|
|
1269
|
+
return 0;
|
|
1270
|
+
}
|
|
1271
|
+
const interactive = !options.yes && Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
1272
|
+
intro("BearMinion");
|
|
1273
|
+
const directory = options.directory ?? (interactive ? await ask(text({
|
|
1274
|
+
message: "Where should the site go?",
|
|
1275
|
+
placeholder: `./${DEFAULT_DIRECTORY}`,
|
|
1276
|
+
defaultValue: DEFAULT_DIRECTORY
|
|
1277
|
+
})) : DEFAULT_DIRECTORY);
|
|
1278
|
+
if (directory === void 0) return cancelled();
|
|
1279
|
+
const targetDir = path.resolve(directory);
|
|
1280
|
+
const blocking = await blockingEntries(targetDir);
|
|
1281
|
+
if (blocking.length > 0) {
|
|
1282
|
+
cancel(`${directory} is not empty (${preview(blocking)}). Choose a new or empty folder.`);
|
|
1283
|
+
return 1;
|
|
1284
|
+
}
|
|
1285
|
+
const siteName = options.name ?? (interactive ? await ask(text({
|
|
1286
|
+
message: "What is the site called?",
|
|
1287
|
+
placeholder: toSiteName(directory),
|
|
1288
|
+
defaultValue: toSiteName(directory)
|
|
1289
|
+
})) : toSiteName(directory));
|
|
1290
|
+
if (siteName === void 0) return cancelled();
|
|
1291
|
+
let url;
|
|
1292
|
+
if (options.url !== void 0) {
|
|
1293
|
+
const normalized = normalizeUrl(options.url);
|
|
1294
|
+
if (!normalized) {
|
|
1295
|
+
cancel(`"${options.url}" is not a web address. Use one such as https://example.com.`);
|
|
1296
|
+
return 1;
|
|
1297
|
+
}
|
|
1298
|
+
url = normalized;
|
|
1299
|
+
} else if (interactive) {
|
|
1300
|
+
const answer = await ask(text({
|
|
1301
|
+
message: "What is its web address?",
|
|
1302
|
+
placeholder: "https://example.com (Enter to skip, set it later under Site → URL)",
|
|
1303
|
+
defaultValue: "",
|
|
1304
|
+
validate: (value) => !value || normalizeUrl(value) ? void 0 : "Enter a full address such as https://example.com, or leave it empty."
|
|
1305
|
+
}));
|
|
1306
|
+
if (answer === void 0) return cancelled();
|
|
1307
|
+
url = answer ? normalizeUrl(answer) ?? void 0 : void 0;
|
|
1308
|
+
}
|
|
1309
|
+
const pm = options.packageManager ?? detectPackageManager(process.env.npm_config_user_agent);
|
|
1310
|
+
const spin = spinner();
|
|
1311
|
+
spin.start("Copying the template");
|
|
1312
|
+
await scaffold({
|
|
1313
|
+
templateDir: path.join(packageRoot, "template"),
|
|
1314
|
+
targetDir,
|
|
1315
|
+
packageName: toPackageName(directory),
|
|
1316
|
+
siteName: siteName.trim() || toSiteName(directory),
|
|
1317
|
+
...url ? { url } : {},
|
|
1318
|
+
storybook: options.storybook
|
|
1319
|
+
});
|
|
1320
|
+
spin.stop(`Created ${siteName} in ${path.relative(process.cwd(), targetDir) || "."}${options.storybook ? ", with Storybook" : ""}`);
|
|
1321
|
+
let installed = false;
|
|
1322
|
+
if (options.install) {
|
|
1323
|
+
spin.start(`Installing dependencies with ${pm}`);
|
|
1324
|
+
const result = await install(pm, targetDir);
|
|
1325
|
+
installed = result.ok;
|
|
1326
|
+
if (result.ok) spin.stop("Installed dependencies");
|
|
1327
|
+
else {
|
|
1328
|
+
spin.error(`${pm} install failed`);
|
|
1329
|
+
log.message(result.output);
|
|
1330
|
+
log.warn(`Run ${pm} install in the folder to try again.`);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
if (options.git) {
|
|
1334
|
+
if (insideGitRepository(path.dirname(targetDir))) log.info("Inside an existing git repository, so no new one was created.");
|
|
1335
|
+
else {
|
|
1336
|
+
const git = initGit(targetDir);
|
|
1337
|
+
if (!git.initialized) log.warn(`Could not create a git repository: ${git.reason ?? "git is not available"}`);
|
|
1338
|
+
else if (!git.committed) log.warn("Created a git repository, but the first commit failed. Set your name and email with git config, then commit.");
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
const steps = [
|
|
1342
|
+
`cd ${path.relative(process.cwd(), targetDir) || "."}`,
|
|
1343
|
+
...installed ? [] : [`${pm} install`],
|
|
1344
|
+
runCommand(pm, "dev")
|
|
1345
|
+
];
|
|
1346
|
+
note(`${steps.join("\n")}\n\nOpen the address it prints and press Ctrl+E (Cmd+E on a Mac) to edit.`, "Next steps");
|
|
1347
|
+
outro(url ? `Ready to publish at ${url}.` : "Set your web address under Site → URL before you publish.");
|
|
1348
|
+
return 0;
|
|
1349
|
+
}
|
|
1350
|
+
/** Awaits a prompt; `undefined` when the person pressed Ctrl+C or Esc. */
|
|
1351
|
+
async function ask(prompt) {
|
|
1352
|
+
const value = await prompt;
|
|
1353
|
+
return typeof value === "string" ? value : void 0;
|
|
1354
|
+
}
|
|
1355
|
+
function cancelled() {
|
|
1356
|
+
cancel("Nothing was created.");
|
|
1357
|
+
return 1;
|
|
1358
|
+
}
|
|
1359
|
+
function preview(entries) {
|
|
1360
|
+
return entries.length > 3 ? `${entries.slice(0, 3).join(", ")} and ${entries.length - 3} more` : entries.join(", ");
|
|
1361
|
+
}
|
|
1362
|
+
main().then((code) => {
|
|
1363
|
+
process.exitCode = code;
|
|
1364
|
+
}, (error) => {
|
|
1365
|
+
log.error(error instanceof Error ? error.stack ?? error.message : String(error));
|
|
1366
|
+
process.exitCode = 1;
|
|
1367
|
+
});
|
|
1368
|
+
//#endregion
|
|
1369
|
+
export {};
|