l00
l00

Reputation: 1

How to copy image or file to clipboard using JXA?

I have difficulty using JavaScript in ScriptEditor

AppleScript copy image to clipboard by path like this

set image to POSIX file ("/Users/lll00lll/Library/Documents/temp.jpg")
set the clipboard to image

But how to translate above AppleScript code to JavaScript?

JavaScript like this can copy string to clipboard but not image or file

var app = Application('Script Editor');
app.includeStandardAdditions = true;
app.setTheClipboardTo(str);

or use Objective-C ?but i don't how to edit it to "generalPasteboard.setData"

$.NSPasteboard.generalPasteboard.clearContents;
$.NSPasteboard.generalPasteboard.setStringForType($(str), $.NSPasteboardTypeString);

Upvotes: 0

Views: 700

Answers (2)

Mat Gessel
Mat Gessel

Reputation: 612

Simplifying CJK's answer slightly:

// makes Cocoa NS* classes available under $
ObjC.import('AppKit'); // same as ObjC.import('Cocoa');

// necessary to get correct result, but I'm not sure why
$.NSPasteboard.generalPasteboard.clearContents;

// create a Cocoa URL for the file system item
const nsUrl = $.NSURL.fileURLWithPath('/Users/lll00lll/Library/Documents/temp.jpg');

// set the pasteboard to the URL
// .js unwraps the NSUrl reference for use in Obj-C
$.NSPasteboard.generalPasteboard.writeObjects([nsUrl.js]);

Explaination

In the original question, the AppleScript snippet sets the clipboard to a URL for the file. The JSX snippet sets the clipboard to a UTF string. I tried using the JSX Path() type, but it sets the clipboard to a nonsense flavor.

This answer manually creates a Cocoa URL and sets the pasteboard to that.

The writeObjects() method will also accept NSImage, so you can pass an image in memory (though it's slower than passing a reference to a file):

const nsImage = $.NSImage.alloc.initByReferencingFile('/Users/lll00lll/Library/Documents/temp.jpg');
$.NSPasteboard.generalPasteboard.writeObjects([nsImage.js]);

Upvotes: 1

CJK
CJK

Reputation: 6102

This uses the JS-ObjC bridge to put one or more files onto the clipboard. fsCopy can be passed a single file path or an array of file paths, and returns the number of items on the clipboard after the operation completes (obviously, this should equal the number of file paths).

ObjC.import('AppKit');


function fsCopy(fs) {
    const pb = $.NSPasteboard.generalPasteboard;
    pb.clearContents;

    [].concat(fs).forEach(f => 
        pb.writeObjects([
            ObjC.unwrap($.NSURL
            .fileURLWithPath(f))
        ])
    );

    return pb.pasteboardItems.count * 1;
}

Upvotes: 3

Related Questions