UNPKG

@guanghechen/mini-copy

Version:

Access system clipboard (also support to share clipboard in wsl with windows).

134 lines (125 loc) 4.98 kB
'use strict'; 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;