@guanghechen/mini-copy
Version:
Access system clipboard (also support to share clipboard in wsl with windows).
134 lines (125 loc) • 4.98 kB
JavaScript
;
var node_child_process = require('node:child_process');
var fs$1 = require('@guanghechen/fs');
var invariant = require('@guanghechen/invariant');
var node_fs = require('node:fs');
var fs = require('node:fs/promises');
var exec = require('@guanghechen/exec');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var invariant__default = /*#__PURE__*/_interopDefault(invariant);
var fs__default = /*#__PURE__*/_interopDefault(fs);
const DEFAULT_LINE_END = process.platform === 'win32' ? '\r\n' : '\n';
async function copy(content, options = {}) {
const { copyCommandPath, copyCommandArgs = [], fakeClipboard, reporter } = options;
try {
reporter?.debug('[copy] try: clipboardy');
const clipboardy = await import('clipboardy').then(md => md.default);
await clipboardy.write(content);
return;
}
catch (error) {
reporter?.debug('[copy] Failed to write clipboard through clipboardy:', error);
}
if (copyCommandPath != null) {
reporter?.debug(`[copy] try: ${copyCommandPath} ${copyCommandArgs.join(' ')}`);
try {
await new Promise((resolve, reject) => {
const command = node_child_process.spawn(copyCommandPath);
command.stdin.write(content);
command.stdin.end();
command.on('close', code => {
if (code === 0)
resolve();
else
reject('[paste] Failed to copy content to clipboard');
});
});
return;
}
catch (error) {
reporter?.debug(`[copy] Failed to call ${copyCommandPath}`, error);
}
}
if (fakeClipboard != null) {
reporter?.debug('[copy] try: fake clipboard {}.', fakeClipboard.filepath);
await fakeClipboard.write(content);
return;
}
throw '[copy] Cannot find available clipboard or fake-clipboard.';
}
class FakeClipboard {
filepath;
encoding;
reporter = null;
isInitialized = false;
constructor(props) {
const { filepath, encoding, reporter } = props;
this.reporter = reporter ?? null;
this.encoding = encoding ?? 'utf8';
this.filepath = filepath;
}
async read(_options = {}) {
await this.init();
return await fs__default.default.readFile(this.filepath, this.encoding);
}
async write(content, _options = {}) {
await this.init();
invariant__default.default(this.filepath != null, '[FakeClipboard.write] filepath is null/undefined.');
await fs$1.writeFile(this.filepath, content, this.encoding);
}
async init() {
if (this.isInitialized)
return;
const { filepath, reporter } = this;
if (node_fs.existsSync(filepath)) {
invariant__default.default(node_fs.statSync(filepath).isFile(), () => `[FakeClipboard] ${filepath} is not a file`);
return;
}
reporter?.verbose(`[FakeClipboard] init fake-clipboard (${filepath}).`);
fs$1.mkdirsIfNotExists(filepath, false);
await fs__default.default.writeFile(filepath, '', this.encoding);
this.isInitialized = true;
}
}
async function paste(options = {}) {
const { pasteCommandPath, pasteCommandArgs = [], fakeClipboard, reporter, lineEnd = DEFAULT_LINE_END, } = options;
try {
reporter?.debug('[paste] try: clipboardy');
const clipboardy = await import('clipboardy').then(md => md.default);
const content = await clipboardy.read();
return normalizeOutput(content, lineEnd);
}
catch (error) {
reporter?.debug('[paste] Failed to read clipboard through clipboardy:', error);
}
if (pasteCommandPath != null) {
reporter?.debug(`[paste] try: ${pasteCommandPath} ${pasteCommandArgs.join(' ')}`);
try {
const { stdout } = await exec.safeExec({
from: 'paste',
cmd: pasteCommandPath,
args: pasteCommandArgs,
});
let content = stdout.toString();
if (/powershell/.test(pasteCommandPath)) {
content = content.replace(/^([^]*?)(?:\r\n|\n\r|[\n\r])$/, '$1');
}
return normalizeOutput(content, lineEnd);
}
catch (error) {
reporter?.debug(`[paste] Failed to call ${pasteCommandPath}:`, error);
}
}
if (fakeClipboard != null) {
reporter?.debug('[paste] try: fake clipboard {}.', fakeClipboard.filepath);
return await fakeClipboard.read();
}
throw '[paste] Cannot find available clipboard or fake-clipboard.';
}
function normalizeOutput(output, lineEnd) {
return output ? output.replace(/\r\n|\r|\n/g, lineEnd) : '';
}
exports.DEFAULT_LINE_END = DEFAULT_LINE_END;
exports.FakeClipboard = FakeClipboard;
exports.copy = copy;
exports.paste = paste;