Skip to content

Commit

Permalink
added readme, changed interface
Browse files Browse the repository at this point in the history
  • Loading branch information
udarrr committed Nov 19, 2022
1 parent eb8358d commit d22cdbd
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 41 deletions.
65 changes: 65 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# sys-clipboard

> Access the system clipboard (copy/paste text, images, files)
Cross-platform!

Supports:

- Windows(text, images, files)
- Linux (text,images,files) *should be installed xclip (`sudo apt install xclip`))*
- MacOS (text, images),

## Install

```
npm install sys-clipboard
```

## Usage

```typescript
import sysClipboard from 'sysClipboard';

async function readWriteText() {
await sysClipboard.writeText('some text');
console.log('text from clipboard:', await sysClipboard.readText());
}
readWriteText();

async function readWriteImage() {
await sysClipboard.writeImage('./source.png');
await sysClipboard.writeImage(fs.readFileSync('./source.png')); //buffer

await sysClipboard.readImage('./destination.png');
await sysClipboard.readImage(); //buffer
}
readWriteImage();

async function copyPasteFiles() {
await sysClipboard.pasteFiles('Copy', './', './source1.png', './source2.png');
await sysClipboard.pasteFiles('Cut', './', './source1.png', './source2.png');
}
copyPasteFiles();

//For windows
await sysClipboard.writeFiles('./source.png', './some.png'); // only windows
console.log(await sysClipboard.readFiles()); // only windows
```

## API
```typescript
export interface SysClipboard {
readText(): Promise<string>;
writeText: (text: string) => Promise<void>;
readImage(file?: string): Promise<Buffer>;
writeImage(file: string | Buffer): Promise<void>;
readFiles(): Promise<Array<string>>;
pasteFiles(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void>;
writeFiles(...files: Array<string>): Promise<boolean>;
}
```

#### Contribution

Opened for contribution https://github.com/udarrr/sys-clipboard
14 changes: 7 additions & 7 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import LinuxClipboard from './src/platform/linux';
import WindowsClipboard from './src/platform/windows';

export interface SysClipboard {
readTextFrom(): Promise<string>;
writeTextTo: (text: string) => Promise<void>;
readImageFrom(file?: string): Promise<Buffer>;
writeImageTo(file: string | Buffer): Promise<void>;
readFilesFrom(): Promise<Array<string>>;
pasteFilesFrom(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void>;
copyFilesTo(...files: Array<string>): Promise<boolean>;
readText(): Promise<string>;
writeText: (text: string) => Promise<void>;
readImage(file?: string): Promise<Buffer>;
writeImage(file: string | Buffer): Promise<void>;
readFiles(): Promise<Array<string>>;
pasteFiles(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void>;
writeFiles(...files: Array<string>): Promise<boolean>;
}

export const sysClipboard: SysClipboard = (() => {
Expand Down
14 changes: 7 additions & 7 deletions src/platform/darwin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import pathLib from 'path';
import { SysClipboard } from '../..';

export default class DarwinClipboard implements SysClipboard {
readFilesFrom(): Promise<Array<string>> {
readFiles(): Promise<Array<string>> {
throw new Error('Method not implemented.');
}

pasteFilesFrom(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void> {
pasteFiles(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void> {
throw new Error('Method not implemented.');
}

copyFilesTo(...files: string[]): Promise<boolean> {
writeFiles(...files: string[]): Promise<boolean> {
throw new Error('Method not implemented.');
}

async readTextFrom(): Promise<string> {
async readText(): Promise<string> {
const { stdout, stderr } = await execa('pbpaste', {
stripFinalNewline: false,
});
Expand All @@ -27,7 +27,7 @@ export default class DarwinClipboard implements SysClipboard {
return stdout;
}

async writeTextTo(text: string): Promise<void> {
async writeText(text: string): Promise<void> {
const { stderr } = await execa('pbcopy', {
input: text,
env: {
Expand All @@ -40,7 +40,7 @@ export default class DarwinClipboard implements SysClipboard {
}
}

async readImageFrom(file?: string): Promise<Buffer> {
async readImage(file?: string): Promise<Buffer> {
const path = file ? file : `${pathLib.join(process.cwd(), 'temp.png')}`;
await fs.writeFile(path, Buffer.from([]));

Expand All @@ -64,7 +64,7 @@ export default class DarwinClipboard implements SysClipboard {
}
}

async writeImageTo(file: string | Buffer): Promise<void> {
async writeImage(file: string | Buffer): Promise<void> {
const path = typeof file === 'string' ? file : await fs.writeFile(pathLib.join(process.cwd(), 'temp.png'), file);

const { stderr } = execa(`osascript -e set the clipboard to (read "${path}" as TIFF picture)`);
Expand Down
14 changes: 7 additions & 7 deletions src/platform/linux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import pathLib from 'path';
import { SysClipboard } from '../..';

export default class LinuxClipboard implements SysClipboard {
readFilesFrom(): Promise<Array<string>> {
readFiles(): Promise<Array<string>> {
throw new Error('Method not implemented.');
}

async pasteFilesFrom(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void> {
async pasteFiles(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void> {
if(action === 'Copy'){
await execa(`xclip-copyfile ${files.join(' ')}`, {
stdio: 'inherit',
Expand All @@ -26,11 +26,11 @@ export default class LinuxClipboard implements SysClipboard {
});
}

copyFilesTo(...files: string[]): Promise<boolean> {
writeFiles(...files: string[]): Promise<boolean> {
throw new Error('Method not implemented.');
}

async readTextFrom(): Promise<string> {
async readText(): Promise<string> {
const { stdout, stderr } = await execa('xclip -selection clipboard -o', {
shell: true,
stripFinalNewline: false,
Expand All @@ -42,7 +42,7 @@ export default class LinuxClipboard implements SysClipboard {
return stdout;
}

async writeTextTo(text: string): Promise<void> {
async writeText(text: string): Promise<void> {
try {
await execa.sync(`echo -n '${text}' | xclip -r -selection clipboard`, {
stdin: 'inherit',
Expand All @@ -56,7 +56,7 @@ export default class LinuxClipboard implements SysClipboard {
}
}

async readImageFrom(file?: string): Promise<Buffer> {
async readImage(file?: string): Promise<Buffer> {
const { stdout, stderr } = await execa('xclip -selection clipboard -t image/png -o | base64', { shell: true });

if (stderr) {
Expand All @@ -74,7 +74,7 @@ export default class LinuxClipboard implements SysClipboard {
}
}

async writeImageTo(file: string | Buffer): Promise<void> {
async writeImage(file: string | Buffer): Promise<void> {
let path = ''

if (typeof file !== 'string') {
Expand Down
16 changes: 8 additions & 8 deletions src/platform/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import pathLib from 'path';
import { SysClipboard } from '../..';

export default class WindowsClipboard implements SysClipboard {
async readTextFrom(): Promise<string> {
async readText(): Promise<string> {
const { stdout, stderr } = await execa(
`powershell -Command Add-Type -AssemblyName System.Windows.Forms; "if([Windows.Forms.Clipboard]::ContainsText()) {$clip=[Windows.Forms.Clipboard]::GetText(); if ($clip -ne $null) {return $clip }} "`,
{
Expand All @@ -18,15 +18,15 @@ export default class WindowsClipboard implements SysClipboard {
return stdout;
}

async writeTextTo(text: string): Promise<void> {
async writeText(text: string): Promise<void> {
const { stderr } = await execa('powershell -noprofile -command $input|Set-Clipboard', { input: text });

if (stderr) {
throw new Error(`cannot write text due to clipboard error: ${stderr}`);
}
}

async readImageFrom(file?: string): Promise<Buffer> {
async readImage(file?: string): Promise<Buffer> {
const { stdout, stderr } = await execa(
`powershell -Command Add-Type -AssemblyName System.Windows.Forms; "$clip=[Windows.Forms.Clipboard]::GetImage();if ($clip -ne $null) { $converter = New-Object -TypeName System.Drawing.ImageConverter;$byte_vec = $converter.ConvertTo($clip, [byte[]]); $EncodedText =[Convert]::ToBase64String($byte_vec); return $EncodedText }"`,
);
Expand All @@ -45,7 +45,7 @@ export default class WindowsClipboard implements SysClipboard {
}
}

async writeImageTo(file: string | Buffer): Promise<void> {
async writeImage(file: string | Buffer): Promise<void> {
let path = '';

if (typeof file !== 'string') {
Expand Down Expand Up @@ -74,7 +74,7 @@ export default class WindowsClipboard implements SysClipboard {
}
}

async readFilesFrom() {
async readFiles() {
const { stdout, stderr } = await execa(
`powershell -Command Add-Type -AssemblyName System.Windows.Forms; "if ([Windows.Forms.Clipboard]::ContainsFileDropList()) {$files = [Windows.Forms.Clipboard]::GetFileDropList(); return $files"}`,
{
Expand All @@ -96,9 +96,9 @@ export default class WindowsClipboard implements SysClipboard {
}
}

async pasteFilesFrom(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void> {
async pasteFiles(action: 'Copy' | 'Cut', destinationFolder: string, ...files: Array<string>): Promise<void> {
if(files && files.length){
await this.copyFilesTo(...files);
await this.writeFiles(...files);
}
const { stderr } = await execa(
`powershell -Command Add-Type -AssemblyName System.Windows.Forms; "$fileDrop = get-clipboard -Format FileDropList; if($fileDrop -eq $null) { write-host 'No files on the clipboard'; return } foreach($file in $fileDrop) {if (Test-Path $file) {if($file.Mode.StartsWith('d')) { $source = join-path $file.Directory $file.Name; Invoke-Expression '${
Expand All @@ -114,7 +114,7 @@ export default class WindowsClipboard implements SysClipboard {
}
}

async copyFilesTo(...files: Array<string>): Promise<boolean> {
async writeFiles(...files: Array<string>): Promise<boolean> {
const formattedFiles: Array<string> = [];

files.forEach((f) => {
Expand Down
24 changes: 12 additions & 12 deletions tests/specs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ describe('Read text from clipboard', () => {
after(async () => {});

it('Write read text clipboard', async () => {
await sysClipboard.writeTextTo(testText);
const text = await sysClipboard.readTextFrom();
await sysClipboard.writeText(testText);
const text = await sysClipboard.readText();

expect(text).to.be.equal(testText);
});
Expand All @@ -30,8 +30,8 @@ describe('Read text from clipboard', () => {
const pathToReadPic = path.join(process.cwd(), 'tests', 'data', 'readPic.png');
const sizeTestPic = sizeOfImage(pathToTestPic);

await sysClipboard.writeImageTo(pathToTestPic);
await sysClipboard.readImageFrom(pathToReadPic);
await sysClipboard.writeImage(pathToTestPic);
await sysClipboard.readImage(pathToReadPic);

const sizeReadPic = sizeOfImage(pathToReadPic);

Expand All @@ -51,8 +51,8 @@ describe('Read text from clipboard', () => {
const bufferTempPic = await fs.readFile(pathToTestPic);
const sizeTestPic = sizeOf(bufferTempPic);

await sysClipboard.writeImageTo(bufferTempPic);
const bufferReadPic = await sysClipboard.readImageFrom();
await sysClipboard.writeImage(bufferTempPic);
const bufferReadPic = await sysClipboard.readImage();

const sizeReadPic = sizeOf(bufferReadPic);

Expand All @@ -69,8 +69,8 @@ describe('Read text from clipboard', () => {
it('Read files clipboard', async () => {
const pathToTestFile = path.join(process.cwd(), 'tests', 'data', 'from', 'testFile.txt');

await sysClipboard.copyFilesTo(pathToTestFile, pathToTestFile, pathToTestFile);
const files = await sysClipboard.readFilesFrom();
await sysClipboard.writeFiles(pathToTestFile, pathToTestFile, pathToTestFile);
const files = await sysClipboard.readFiles();

expect(files.every((f) => fs.existsSync(f))).to.be.equal(true);
});
Expand All @@ -83,9 +83,9 @@ describe('Read text from clipboard', () => {
const pathToCopiedFile = path.join(destinationFolder, 'testFile.txt');

if(process.platform === 'win32'){
await sysClipboard.copyFilesTo(pathToTestFile);
await sysClipboard.writeFiles(pathToTestFile);
}
await sysClipboard.pasteFilesFrom('Copy', destinationFolder, pathToTestFile);
await sysClipboard.pasteFiles('Copy', destinationFolder, pathToTestFile);
const isExist = fs.existsSync(pathToCopiedFile);

try {
Expand All @@ -103,9 +103,9 @@ describe('Read text from clipboard', () => {
const pathToCopiedFile = path.join(destinationFolder, 'testFile.txt');

if(process.platform === 'win32'){
await sysClipboard.copyFilesTo(pathToTestFile);
await sysClipboard.writeFiles(pathToTestFile);
}
await sysClipboard.pasteFilesFrom('Cut', destinationFolder, pathToTestFile);
await sysClipboard.pasteFiles('Cut', destinationFolder, pathToTestFile);

const isExistTemp = fs.existsSync(pathToTestFile);
const isExistDestination = fs.existsSync(pathToCopiedFile);
Expand Down

0 comments on commit d22cdbd

Please sign in to comment.