Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SImplify "astro add" by removing confusing multi-select #3715

Merged
merged 8 commits into from
Jun 27, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lucky-apes-yell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Update "astro add" output to remove confusing multi-select prompt.
5 changes: 5 additions & 0 deletions .changeset/perfect-drinks-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Update the help output to improve formatting
natemoo-re marked this conversation as resolved.
Show resolved Hide resolved
39 changes: 20 additions & 19 deletions packages/astro/src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,27 @@ type CLICommand =
function printAstroHelp() {
printHelp({
commandName: 'astro',
usage: '[command] [...flags]',
headline: 'Futuristic web development tool.',
commands: [
['add', 'Add an integration to your configuration.'],
['docs', "Launch Astro's Doc site directly from the terminal. "],
['dev', 'Run Astro in development mode.'],
['build', 'Build a pre-compiled production-ready site.'],
['preview', 'Preview your build locally before deploying.'],
['check', 'Check your project for errors.'],
['telemetry', 'Enable/disable anonymous data collection.'],
['--version', 'Show the version number and exit.'],
['--help', 'Show this help message.'],
],
flags: [
['--host [optional IP]', 'Expose server on network'],
['--config <path>', 'Specify the path to the Astro config file.'],
['--root <path>', 'Specify the path to the project root folder.'],
['--drafts', 'Include markdown draft pages in the build.'],
['--verbose', 'Enable verbose logging'],
['--silent', 'Disable logging'],
],
tables: {
Commands: [
['add', 'Add an integration.'],
['build', 'Build your project and write it to disk.'],
['check', 'Check your project for errors.'],
['dev', 'Start the development server.'],
['docs', "Open documentation in your web browser."],
['preview', 'Preview your build locally.'],
['telemetry', 'Configure telemetry settings.'],
],
'Global Flags': [
['--config <path>', 'Specify your config file.'],
['--root <path>', 'Specify your project root folder.'],
['--verbose', 'Enable verbose logging.'],
['--silent', 'Disable all logging.'],
['--version', 'Show the version number and exit.'],
['--help', 'Show this help message.'],
],
},
});
}

Expand Down
14 changes: 8 additions & 6 deletions packages/astro/src/cli/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ export async function update(subcommand: string, { flags, telemetry }: Telemetry
if (flags.help || !isValid) {
msg.printHelp({
commandName: 'astro telemetry',
usage: '<enable|disable|reset>',
commands: [
['enable', 'Enable anonymous data collection.'],
['disable', 'Disable anonymous data collection.'],
['reset', 'Reset anonymous data collection settings.'],
],
usage: '[command]',
tables: {
Commands: [
['enable', 'Enable anonymous data collection.'],
['disable', 'Disable anonymous data collection.'],
['reset', 'Reset anonymous data collection settings.'],
],
},
});
return;
}
Expand Down
27 changes: 0 additions & 27 deletions packages/astro/src/core/add/consts.ts

This file was deleted.

99 changes: 49 additions & 50 deletions packages/astro/src/core/add/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,13 @@ import prompts from 'prompts';
import { fileURLToPath, pathToFileURL } from 'url';
import type yargs from 'yargs-parser';
import { resolveConfigURL } from '../config.js';
import { debug, error, info, LogOptions } from '../logger/core.js';
import { debug, info, LogOptions } from '../logger/core.js';
import * as msg from '../messages.js';
import { printHelp } from '../messages.js';
import { appendForwardSlash } from '../path.js';
import { apply as applyPolyfill } from '../polyfill.js';
import { parseNpmName } from '../util.js';
import { generate, parse, t, visit } from './babel.js';
import * as CONSTS from './consts.js';
import { ensureImport } from './imports.js';
import { wrapDefaultExport } from './wrapper.js';

Expand All @@ -34,71 +33,71 @@ export interface IntegrationInfo {
packageName: string;
dependencies: [name: string, version: string][];
}
const ALIASES = new Map([
['solid', 'solid-js'],
['tailwindcss', 'tailwind'],
]);
const ASTRO_CONFIG_STUB = `import { defineConfig } from 'astro/config';\n\ndefault defineConfig({});`;
const TAILWIND_CONFIG_STUB = `/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['./src/**/*.{astro,html,js,jsx,md,svelte,ts,tsx,vue}'],
theme: {
extend: {},
},
plugins: [],
}\n`;

export default async function add(names: string[], { cwd, flags, logging, telemetry }: AddOptions) {
if (flags.help) {
if (flags.help || names.length === 0) {
printHelp({
commandName: 'astro add',
usage: '[FLAGS] [INTEGRATIONS...]',
flags: [
['--yes', 'Add the integration without user interaction.'],
['--help', 'Show this help message.'],
],
usage: '[...integrations]',
tables: {
Flags: [
['--yes', 'Accept all prompts.'],
['--help', 'Show this help message.'],
],
'Example: Add a UI Framework': [
['react', 'astro add react'],
['preact', 'astro add preact'],
['vue', 'astro add vue'],
['svelte', 'astro add svelte'],
['solid-js', 'astro add solid-js'],
['lit', 'astro add lit'],
],
'Example: Add an Integration': [
['tailwind', 'astro add tailwind'],
['partytown', 'astro add partytown'],
['sitemap', 'astro add sitemap'],
],
},
description: `Check out the full integration catalog: ${cyan('https://astro.build/integrations')}`,
});
return;
}
let configURL: URL | undefined;
const root = pathToFileURL(cwd ? path.resolve(cwd) : process.cwd());
// TODO: improve error handling for invalid configs
configURL = await resolveConfigURL({ cwd, flags });

if (configURL?.pathname.endsWith('package.json')) {
throw new Error(
`Unable to use astro add with package.json#astro configuration! Try migrating to \`astro.config.mjs\` and try again.`
);
}
applyPolyfill();

// If no integrations were given, prompt the user for some popular ones.
if (names.length === 0) {
const response = await prompts([
{
type: 'multiselect',
name: 'frameworks',
message: 'What frameworks would you like to enable?',
instructions: '\n Space to select. Return to submit',
choices: CONSTS.FIRST_PARTY_FRAMEWORKS,
},
{
type: 'multiselect',
name: 'addons',
message: 'What additional integrations would you like to enable?',
instructions: '\n Space to select. Return to submit',
choices: CONSTS.FIRST_PARTY_ADDONS,
},
]);

names = [...(response.frameworks ?? []), ...(response.addons ?? [])];
}

// If still empty after prompting, exit gracefully.
if (names.length === 0) {
error(logging, null, `No integrations specified.`);
return;
}

// Some packages might have a common alias! We normalize those here.
names = names.map((name) => (CONSTS.ALIASES.has(name) ? CONSTS.ALIASES.get(name)! : name));


if (configURL) {
debug('add', `Found config at ${configURL}`);
} else {
info(logging, 'add', `Unable to locate a config file, generating one for you.`);
configURL = new URL('./astro.config.mjs', appendForwardSlash(root.href));
await fs.writeFile(fileURLToPath(configURL), CONSTS.CONFIG_STUB, { encoding: 'utf-8' });
await fs.writeFile(fileURLToPath(configURL), ASTRO_CONFIG_STUB, { encoding: 'utf-8' });
}

// TODO: improve error handling for invalid configs
if (configURL?.pathname.endsWith('package.json')) {
throw new Error(
`Unable to use "astro add" with package.json configuration. Try migrating to \`astro.config.mjs\` and try again.`
);
}

const integrations = await validateIntegrations(names);
// Some packages might have a common alias! We normalize those here.
const integrationNames = names.map((name) => (ALIASES.has(name) ? ALIASES.get(name)! : name));
const integrations = await validateIntegrations(integrationNames);

let ast: t.File | null = null;
try {
Expand Down Expand Up @@ -194,7 +193,7 @@ export default async function add(names: string[], { cwd, flags, logging, teleme
if (await askToContinue({ flags })) {
await fs.writeFile(
fileURLToPath(new URL('./tailwind.config.cjs', configURL)),
CONSTS.TAILWIND_CONFIG_STUB,
TAILWIND_CONFIG_STUB,
{ encoding: 'utf-8' }
);
debug('add', `Generated default ./tailwind.config.cjs file`);
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/core/logger/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export const logger = {

export function enableVerboseLogging() {
//debugPackage.enable('*,-babel');
console.log('ah!');
FredKSchott marked this conversation as resolved.
Show resolved Hide resolved
debug('cli', '--verbose flag enabled! Enabling: DEBUG="*,-babel"');
debug(
'cli',
Expand Down
46 changes: 24 additions & 22 deletions packages/astro/src/core/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -248,29 +248,28 @@ export function printHelp({
commandName,
headline,
usage,
commands,
flags,
tables,
description,
}: {
commandName: string;
headline?: string;
usage?: string;
commands?: [command: string, help: string][];
flags?: [flag: string, help: string][];
tables?: Record<string, [command: string, help: string][]>;
description?: string,
}) {
const linebreak = () => '';
const title = (label: string) => ` ${bgWhite(black(` ${label} `))}`;
const table = (rows: [string, string][], opts: { padding: number; prefix: string }) => {
const split = rows.some((row) => {
const message = `${opts.prefix}${' '.repeat(opts.padding)}${row[1]}`;
return message.length > process.stdout.columns;
});

const table = (rows: [string, string][], { padding }: { padding: number }) => {
const split = process.stdout.columns < 60;
let raw = '';

for (const row of rows) {
raw += `${opts.prefix}${bold(`${row[0]}`.padStart(opts.padding - opts.prefix.length))}`;
if (split) raw += '\n ';
raw += ' ' + dim(row[1]) + '\n';
if (split) {
raw += ` ${row[0]}\n `;
} else {
raw += `${(`${row[0]}`.padStart(padding))}`;
}
raw += ' ' + dim(row[1]) + '\n';
}

return raw.slice(0, -1); // remove latest \n
Expand All @@ -291,18 +290,21 @@ export function printHelp({
message.push(linebreak(), ` ${green(commandName)} ${bold(usage)}`);
}

if (commands) {
message.push(
linebreak(),
title('Commands'),
table(commands, { padding: 28, prefix: ` ${commandName || 'astro'} ` })
);
if (tables) {
function calculateTablePadding(rows: [string, string][]) {
return rows.reduce((val, [first]) => Math.max(val, first.length), 0) + 2;
};
const tableEntries = Object.entries(tables);
const padding = Math.max(...tableEntries.map(([, rows]) => calculateTablePadding(rows)));
for (const [tableTitle, tableRows] of tableEntries) {
message.push(linebreak(), title(tableTitle), table(tableRows, { padding }));
}
}

if (flags) {
message.push(linebreak(), title('Flags'), table(flags, { padding: 28, prefix: ' ' }));
if (description) {
message.push(linebreak(), `${description}`);
}

// eslint-disable-next-line no-console
console.log(message.join('\n'));
console.log(message.join('\n') + '\n');
}
Loading