mirror of
https://github.com/withastro/astro.git
synced 2025-01-20 22:12:38 -05:00
Adds automatic, seasonally appropriate messages from Houston (#9476)
* feat: allow Houston to wear Scarfs * refactor: allow 1 object to be passed instead of separate * set messages back to original state / add ties * refactor to getClothes method * refactor: add clothes per season * refactor: add messages with timing too * refactor to new file * refactor: use `hat` & `tie` instead of `clothes` * refactor: use `getSeasonalHouston` only once * chore: upgrade dependencies * fix mistake in date * feat(create-astro): refactor seasonal logic * chore: remove unused entrypoint * refactor: simplify seasonal data * chore: add changeset --------- Co-authored-by: Nate Moore <nate@astro.build> Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
This commit is contained in:
parent
75084b49d0
commit
651f45b401
8 changed files with 136 additions and 43 deletions
5
.changeset/afraid-ligers-add.md
Normal file
5
.changeset/afraid-ligers-add.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
"create-astro": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Improves seasonal message handling by automatically detecting the local date
|
|
@ -31,7 +31,7 @@
|
||||||
"//a": "MOST PACKAGES SHOULD GO IN DEV_DEPENDENCIES! THEY WILL BE BUNDLED.",
|
"//a": "MOST PACKAGES SHOULD GO IN DEV_DEPENDENCIES! THEY WILL BE BUNDLED.",
|
||||||
"//b": "DEPENDENCIES IS FOR UNBUNDLED PACKAGES",
|
"//b": "DEPENDENCIES IS FOR UNBUNDLED PACKAGES",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/cli-kit": "^0.4.0",
|
"@astrojs/cli-kit": "^0.4.1",
|
||||||
"giget": "1.1.3"
|
"giget": "1.1.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import arg from 'arg';
|
||||||
import os from 'node:os';
|
import os from 'node:os';
|
||||||
|
|
||||||
import { getName, getVersion } from '../messages.js';
|
import { getName, getVersion } from '../messages.js';
|
||||||
|
import getSeasonalData from '../data/seasonal.js';
|
||||||
|
|
||||||
export interface Context {
|
export interface Context {
|
||||||
help: boolean;
|
help: boolean;
|
||||||
|
@ -25,7 +26,9 @@ export interface Context {
|
||||||
stdin?: typeof process.stdin;
|
stdin?: typeof process.stdin;
|
||||||
stdout?: typeof process.stdout;
|
stdout?: typeof process.stdout;
|
||||||
exit(code: number): never;
|
exit(code: number): never;
|
||||||
|
welcome?: string;
|
||||||
hat?: string;
|
hat?: string;
|
||||||
|
tie?: string;
|
||||||
tasks: Task[];
|
tasks: Task[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,6 +86,8 @@ export async function getContext(argv: string[]): Promise<Context> {
|
||||||
((os.platform() === 'win32' && !fancy) || skipHouston) ??
|
((os.platform() === 'win32' && !fancy) || skipHouston) ??
|
||||||
[yes, no, install, git, typescript].some((v) => v !== undefined);
|
[yes, no, install, git, typescript].some((v) => v !== undefined);
|
||||||
|
|
||||||
|
const { messages, hats, ties } = getSeasonalData({ fancy });
|
||||||
|
|
||||||
const context: Context = {
|
const context: Context = {
|
||||||
help,
|
help,
|
||||||
prompt,
|
prompt,
|
||||||
|
@ -95,7 +100,9 @@ export async function getContext(argv: string[]): Promise<Context> {
|
||||||
projectName,
|
projectName,
|
||||||
template,
|
template,
|
||||||
ref: ref ?? 'latest',
|
ref: ref ?? 'latest',
|
||||||
hat: random(['❄️', '🎄', '🎁']), // fancy ? random(['🎩', '🎩', '🎩', '🎩', '🎓', '👑', '🧢', '🍦']) : undefined,
|
welcome: random(messages),
|
||||||
|
hat: hats ? random(hats) : undefined,
|
||||||
|
tie: ties ? random(ties) : undefined,
|
||||||
yes,
|
yes,
|
||||||
install: install ?? (noInstall ? false : undefined),
|
install: install ?? (noInstall ? false : undefined),
|
||||||
git: git ?? (noGit ? false : undefined),
|
git: git ?? (noGit ? false : undefined),
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import type { Context } from './context.js';
|
import type { Context } from './context.js';
|
||||||
|
|
||||||
import { color, label } from '@astrojs/cli-kit';
|
import { color, label } from '@astrojs/cli-kit';
|
||||||
import { random } from '@astrojs/cli-kit/utils';
|
import { banner, say } from '../messages.js';
|
||||||
import { banner, say, welcome } from '../messages.js';
|
|
||||||
|
|
||||||
export async function intro(
|
export async function intro(
|
||||||
ctx: Pick<Context, 'hat' | 'skipHouston' | 'version' | 'username' | 'fancy'>
|
ctx: Pick<Context, 'skipHouston' | 'welcome' | 'hat' | 'tie' | 'version' | 'username' | 'fancy'>
|
||||||
) {
|
) {
|
||||||
banner();
|
banner();
|
||||||
|
|
||||||
if (!ctx.skipHouston) {
|
if (!ctx.skipHouston) {
|
||||||
|
const { welcome, hat, tie } = ctx;
|
||||||
await say(
|
await say(
|
||||||
[
|
[
|
||||||
[
|
[
|
||||||
|
@ -21,9 +21,9 @@ export async function intro(
|
||||||
),
|
),
|
||||||
Promise.resolve(ctx.username).then((username) => `${username}!`),
|
Promise.resolve(ctx.username).then((username) => `${username}!`),
|
||||||
],
|
],
|
||||||
random(welcome),
|
welcome ?? 'Let\'s build something awesome!',
|
||||||
],
|
] as string[],
|
||||||
{ clear: true, hat: ctx.hat }
|
{ clear: true, hat, tie }
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import type { Context } from './context.js';
|
||||||
|
|
||||||
import { nextSteps, say } from '../messages.js';
|
import { nextSteps, say } from '../messages.js';
|
||||||
|
|
||||||
export async function next(ctx: Pick<Context, 'hat' | 'cwd' | 'packageManager' | 'skipHouston'>) {
|
export async function next(ctx: Pick<Context, 'hat' | 'tie' | 'cwd' | 'packageManager' | 'skipHouston'>) {
|
||||||
let projectDir = path.relative(process.cwd(), ctx.cwd);
|
let projectDir = path.relative(process.cwd(), ctx.cwd);
|
||||||
|
|
||||||
const commandMap: { [key: string]: string } = {
|
const commandMap: { [key: string]: string } = {
|
||||||
|
@ -17,7 +17,7 @@ export async function next(ctx: Pick<Context, 'hat' | 'cwd' | 'packageManager' |
|
||||||
await nextSteps({ projectDir, devCmd });
|
await nextSteps({ projectDir, devCmd });
|
||||||
|
|
||||||
if (!ctx.skipHouston) {
|
if (!ctx.skipHouston) {
|
||||||
await say(['Good luck out there, astronaut! 🚀'], { hat: ctx.hat });
|
await say(['Good luck out there, astronaut! 🚀'], { hat: ctx.hat, tie: ctx.tie });
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
108
packages/create-astro/src/data/seasonal.ts
Normal file
108
packages/create-astro/src/data/seasonal.ts
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
interface SeasonalHouston {
|
||||||
|
hats?: string[];
|
||||||
|
ties?: string[];
|
||||||
|
messages: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function getSeasonalHouston({ fancy }: { fancy?: boolean }): SeasonalHouston {
|
||||||
|
const season = getSeason();
|
||||||
|
switch (season) {
|
||||||
|
case 'new-year': {
|
||||||
|
const year = new Date().getFullYear();
|
||||||
|
return {
|
||||||
|
hats: rarity(0.5, ['🎩']),
|
||||||
|
ties: rarity(0.25, ['🎊', '🎀', '🎉']),
|
||||||
|
messages: [
|
||||||
|
`New year, new Astro site!`,
|
||||||
|
`Kicking ${year} off with Astro?! What an honor!`,
|
||||||
|
`Happy ${year}! Let's make something cool.`,
|
||||||
|
`${year} is your year! Let's build something awesome.`,
|
||||||
|
`${year} is the year of Astro!`,
|
||||||
|
`${year} is clearly off to a great start!`,
|
||||||
|
`Thanks for starting ${year} with Astro!`
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case 'spooky': return {
|
||||||
|
hats: rarity(0.5, ['🎃', '👻', '☠️', '💀', '🕷️', '🔮']),
|
||||||
|
ties: rarity(0.25, ['🦴', '🍬', '🍫']),
|
||||||
|
messages: [
|
||||||
|
`I'm afraid I can't help you... Just kidding!`,
|
||||||
|
`Boo! Just kidding. Let's make a website!`,
|
||||||
|
`Let's haunt the internet. OooOooOOoo!`,
|
||||||
|
`No tricks here. Seeing you is always treat!`,
|
||||||
|
`Spiders aren't the only ones building the web!`,
|
||||||
|
`Let's conjure up some web magic!`,
|
||||||
|
`Let's harness the power of Astro to build a frightful new site!`,
|
||||||
|
`We're conjuring up a spooktacular website!`,
|
||||||
|
`Prepare for a web of spooky wonders to be woven.`,
|
||||||
|
`Chills and thrills await you on your new project!`,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
case 'holiday': return {
|
||||||
|
hats: rarity(0.75, ['🎁', '🎄', '🌲']),
|
||||||
|
ties: rarity(0.75, ['🧣']),
|
||||||
|
messages: [
|
||||||
|
`'Tis the season to code and create.`,
|
||||||
|
`Jingle all the way through your web creation journey!`,
|
||||||
|
`Bells are ringing, and so are your creative ideas!`,
|
||||||
|
`Let's make the internet our own winter wonderland!`,
|
||||||
|
`It's time to decorate a brand new website!`,
|
||||||
|
`Let's unwrap the magic of the web together!`,
|
||||||
|
`Hope you're enjoying the holiday season!`,
|
||||||
|
`I'm dreaming of a brand new website!`,
|
||||||
|
`No better holiday gift than a new site!`,
|
||||||
|
`Your creativity is the gift that keeps on giving!`,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
default: return {
|
||||||
|
hats: fancy ? ['🎩', '🎩', '🎩', '🎩', '🎓', '👑', '🧢', '🍦'] : undefined,
|
||||||
|
ties: fancy ? rarity(0.33, ['🎀', '🧣']) : undefined,
|
||||||
|
messages: [
|
||||||
|
`Let's claim your corner of the internet.`,
|
||||||
|
`I'll be your assistant today.`,
|
||||||
|
`Let's build something awesome!`,
|
||||||
|
`Let's build something great!`,
|
||||||
|
`Let's build something fast!`,
|
||||||
|
`Let's build the web we want.`,
|
||||||
|
`Let's make the web weird!`,
|
||||||
|
`Let's make the web a better place!`,
|
||||||
|
`Let's create a new project!`,
|
||||||
|
`Let's create something unique!`,
|
||||||
|
`Time to build a new website.`,
|
||||||
|
`Time to build a faster website.`,
|
||||||
|
`Time to build a sweet new website.`,
|
||||||
|
`We're glad to have you on board.`,
|
||||||
|
`Keeping the internet weird since 2021.`,
|
||||||
|
`Initiating launch sequence...`,
|
||||||
|
`Initiating launch sequence... right... now!`,
|
||||||
|
`Awaiting further instructions.`,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Season = 'spooky' | 'holiday' | 'new-year';
|
||||||
|
function getSeason(): Season | undefined {
|
||||||
|
const date = new Date();
|
||||||
|
const month = date.getMonth() + 1;
|
||||||
|
const day = date.getDate() + 1;
|
||||||
|
|
||||||
|
if (month === 1 && day <= 7) {
|
||||||
|
return 'new-year';
|
||||||
|
}
|
||||||
|
if (month === 10 && day > 7) {
|
||||||
|
return 'spooky'
|
||||||
|
}
|
||||||
|
if (month === 12 && day > 7 && day < 25) {
|
||||||
|
return 'holiday'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates an array padded with empty strings to make decorations more rare
|
||||||
|
function rarity(frequency: number, emoji: string[]) {
|
||||||
|
if (frequency === 1) return emoji;
|
||||||
|
if (frequency === 0) return [''];
|
||||||
|
const empty = Array.from({ length: Math.round(emoji.length * frequency) }, () => '')
|
||||||
|
return [...emoji, ...empty];
|
||||||
|
}
|
|
@ -24,8 +24,8 @@ export function setStdout(writable: typeof process.stdout) {
|
||||||
stdout = writable;
|
stdout = writable;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function say(messages: string | string[], { clear = false, hat = '' } = {}) {
|
export async function say(messages: string | string[], { clear = false, hat = '', tie = ''} = {}) {
|
||||||
return houston(messages, { clear, hat, stdout });
|
return houston(messages, { clear, hat, tie, stdout });
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function spinner(args: {
|
export async function spinner(args: {
|
||||||
|
@ -39,33 +39,6 @@ export async function spinner(args: {
|
||||||
|
|
||||||
export const title = (text: string) => align(label(text), 'end', 7) + ' ';
|
export const title = (text: string) => align(label(text), 'end', 7) + ' ';
|
||||||
|
|
||||||
export const welcome = [
|
|
||||||
// `Let's claim your corner of the internet.`,
|
|
||||||
// `I'll be your assistant today.`,
|
|
||||||
// `Let's build something awesome!`,
|
|
||||||
// `Let's build something great!`,
|
|
||||||
// `Let's build something fast!`,
|
|
||||||
// `Let's build the web we want.`,
|
|
||||||
// `Let's make the web weird!`,
|
|
||||||
// `Let's make the web a better place!`,
|
|
||||||
// `Let's create a new project!`,
|
|
||||||
// `Let's create something unique!`,
|
|
||||||
// `Time to build a new website.`,
|
|
||||||
// `Time to build a faster website.`,
|
|
||||||
// `Time to build a sweet new website.`,
|
|
||||||
// `We're glad to have you on board.`,
|
|
||||||
// `Keeping the internet weird since 2021.`,
|
|
||||||
// `Initiating launch sequence...`,
|
|
||||||
// `Initiating launch sequence... right... now!`,
|
|
||||||
// `Awaiting further instructions.`,
|
|
||||||
`Ho, ho, ho! 'Tis the season to code and create.`,
|
|
||||||
`Jingle all the way through your web creation journey!`,
|
|
||||||
`Let's unwrap the magic of the web together!`,
|
|
||||||
`Bells are ringing, and so are your creative ideas!`,
|
|
||||||
`It's starting to look a lot like Christmas on the internet.`,
|
|
||||||
`It's time to decorate the web with your festive ideas!`,
|
|
||||||
];
|
|
||||||
|
|
||||||
export const getName = () =>
|
export const getName = () =>
|
||||||
new Promise<string>((resolve) => {
|
new Promise<string>((resolve) => {
|
||||||
exec('git config user.name', { encoding: 'utf-8' }, (_1, gitName) => {
|
exec('git config user.name', { encoding: 'utf-8' }, (_1, gitName) => {
|
||||||
|
|
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
|
@ -3737,8 +3737,8 @@ importers:
|
||||||
packages/create-astro:
|
packages/create-astro:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@astrojs/cli-kit':
|
'@astrojs/cli-kit':
|
||||||
specifier: ^0.4.0
|
specifier: ^0.4.1
|
||||||
version: 0.4.0
|
version: 0.4.1
|
||||||
giget:
|
giget:
|
||||||
specifier: 1.1.3
|
specifier: 1.1.3
|
||||||
version: 1.1.3
|
version: 1.1.3
|
||||||
|
@ -5280,8 +5280,8 @@ packages:
|
||||||
sisteransi: 1.0.5
|
sisteransi: 1.0.5
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@astrojs/cli-kit@0.4.0:
|
/@astrojs/cli-kit@0.4.1:
|
||||||
resolution: {integrity: sha512-M7R2Af/Gh13pwZ2zjTkTPt87x4IjRw/bSRCmjJGWEGeW3nLNzuEeRY8tleeIGbbfUsm3DJg+UF5rCrQGoviHgQ==}
|
resolution: {integrity: sha512-bVzyKzEpIwqjihBU/aUzt1LQckJuHK0agd3/ITdXhPUYculrc6K1/K7H+XG4rwjXtg+ikT3PM05V1MVYWiIvQw==}
|
||||||
engines: {node: '>=18.14.1'}
|
engines: {node: '>=18.14.1'}
|
||||||
dependencies:
|
dependencies:
|
||||||
chalk: 5.3.0
|
chalk: 5.3.0
|
||||||
|
|
Loading…
Add table
Reference in a new issue