0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-30 22:03:56 -05:00

fix: correctly copy to clipboard in astro info (#12641)

* fix: correctly copy to clipboard on mac

* Add platform-specific clipboard handling for Linux

* Wording

* Update .changeset/angry-pumas-act.md

Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>

* Use console.info

---------

Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
This commit is contained in:
Matt Kane 2024-12-05 13:01:13 +00:00 committed by GitHub
parent 03958d9392
commit 48ca399788
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 102 additions and 30 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixes a bug where `astro info --copy` wasn't working correctly on `macOS` systems.

View file

@ -1,4 +1,4 @@
import { execSync } from 'node:child_process';
import { spawnSync } from 'node:child_process';
import { arch, platform } from 'node:os';
import * as colors from 'kleur/colors';
import prompts from 'prompts';
@ -49,56 +49,63 @@ export async function printInfo({ flags }: InfoOptions) {
applyPolyfill();
const { userConfig } = await resolveConfig(flagsToAstroInlineConfig(flags), 'info');
const output = await getInfoOutput({ userConfig, print: true });
await copyToClipboard(output);
await copyToClipboard(output, flags.copy);
}
async function copyToClipboard(text: string) {
export async function copyToClipboard(text: string, force?: boolean) {
text = text.trim();
const system = platform();
let command = '';
let args: Array<string> = [];
if (system === 'darwin') {
command = 'pbcopy';
} else if (system === 'win32') {
command = 'clip';
} else {
// Unix: check if a supported command is installed
const unixCommands = [
['xclip', '-sel clipboard -l 1'],
['wl-copy', '"$0"'],
const unixCommands: Array<[string, Array<string>]> = [
['xclip', ['-sel', 'clipboard', '-l', '1']],
['wl-copy', []],
];
for (const [unixCommand, args] of unixCommands) {
for (const [unixCommand, unixArgs] of unixCommands) {
try {
const output = execSync(`which ${unixCommand}`, { encoding: 'utf8', stdio: 'pipe' });
if (output[0] !== '/') {
// Did not find a path. Skip!
continue;
const output = spawnSync('which', [unixCommand], { encoding: 'utf8' });
if (output.stdout.trim()) {
command = unixCommand;
args = unixArgs;
break;
}
command = `${unixCommand} ${args}`;
} catch {
// Failed to execute which. Skip!
continue;
}
}
// Did not find supported command. Bail out!
if (!command) return;
}
console.log();
const { shouldCopy } = await prompts({
type: 'confirm',
name: 'shouldCopy',
message: 'Copy to clipboard?',
initial: true,
});
if (!shouldCopy) return;
if (!command) {
console.error(colors.red('\nClipboard command not found!'));
console.info('Please manually copy the text above.');
return;
}
if (!force) {
const { shouldCopy } = await prompts({
type: 'confirm',
name: 'shouldCopy',
message: 'Copy to clipboard?',
initial: true,
});
if (!shouldCopy) return;
}
try {
execSync(command.replaceAll('$0', text), {
stdio: 'ignore',
input: text,
encoding: 'utf8',
});
const result = spawnSync(command, args, { input: text });
if (result.error) {
throw result.error;
}
console.info(colors.green('Copied to clipboard!'));
} catch {
console.error(
colors.red(`\nSorry, something went wrong!`) + ` Please copy the text above manually.`,
@ -106,6 +113,46 @@ async function copyToClipboard(text: string) {
}
}
export function readFromClipboard() {
const system = platform();
let command = '';
let args: Array<string> = [];
if (system === 'darwin') {
command = 'pbpaste';
} else if (system === 'win32') {
command = 'powershell';
args = ['-command', 'Get-Clipboard'];
} else {
const unixCommands: Array<[string, Array<string>]> = [
['xclip', ['-sel', 'clipboard', '-o']],
['wl-paste', []],
];
for (const [unixCommand, unixArgs] of unixCommands) {
try {
const output = spawnSync('which', [unixCommand], { encoding: 'utf8' });
if (output.stdout.trim()) {
command = unixCommand;
args = unixArgs;
break;
}
} catch {
continue;
}
}
}
if (!command) {
throw new Error('Clipboard read command not found!');
}
const result = spawnSync(command, args, { encoding: 'utf8' });
if (result.error) {
throw result.error;
}
return result.stdout.trim();
}
const PLATFORM_TO_OS: Partial<Record<ReturnType<typeof platform>, string>> = {
darwin: 'macOS',
win32: 'Windows',
@ -140,7 +187,7 @@ function printRow(label: string, value: string | string[], print: boolean) {
}
plaintext += '\n';
if (print) {
console.log(richtext);
console.info(richtext);
}
return plaintext;
}

View file

@ -7,6 +7,8 @@ import { describe, it } from 'node:test';
import { fileURLToPath } from 'node:url';
import { stripVTControlCharacters } from 'node:util';
import { cli, cliServerLogSetup, loadFixture, parseCliDevStart } from './test-utils.js';
import { readFromClipboard } from '../dist/cli/info/index.js';
import { platform } from 'node:process';
describe('astro cli', () => {
const cliServerLogSetupWithFixture = (flags, cmd) => {
@ -78,6 +80,24 @@ describe('astro cli', () => {
assert.equal(proc.stdout.includes(pkgVersion), true);
});
it('astro info', async () => {
const proc = await cli('info', '--copy');
const pkgURL = new URL('../package.json', import.meta.url);
const pkgVersion = await fs.readFile(pkgURL, 'utf8').then((data) => JSON.parse(data).version);
assert.ok(proc.stdout.includes(`v${pkgVersion}`));
assert.equal(proc.exitCode, 0);
// On Linux we only check if we have Wayland or x11. In Codespaces it falsely reports that it does have x11
if(platform === 'linux' && ((!process.env.WAYLAND_DISPLAY && !process.env.DISPLAY) || process.env.CODESPACES)) {
assert.ok(proc.stdout.includes('Please manually copy the text above'));
} else {
assert.ok(proc.stdout.includes('Copied to clipboard!'));
const clipboardContent = await readFromClipboard();
assert.ok(clipboardContent.includes(`v${pkgVersion}`));
}
});
it(
'astro check no errors',
{