First I found this great post by @MadProgrammer which seems to work on MacOS but not on my setup (Windows 11). The following solution is based on reverse engineering the clipboard metadata.
You don't need to import JLink
, just run the following code (assuming you have version 12.3 or higher):
javaCopyLink=ExternalFunction["Java","
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public static void CopyLink(String htmlText,String plainText){
HtmlSelection htmlSelection = new HtmlSelection(htmlText, plainText);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(htmlSelection, null);
}
public class HtmlSelection implements Transferable {
private static List<DataFlavor> htmlFlavors = new ArrayList<>(3);
static {
try {
htmlFlavors.add(DataFlavor.stringFlavor);
htmlFlavors.add(DataFlavor.allHtmlFlavor);
htmlFlavors.add(DataFlavor.fragmentHtmlFlavor);
} catch (Exception ex) {
}
}
private String html;
private String plainText;
private float version= 0.9f;
private String sourceURL = \"\";
private int startHTML = 109 + sourceURL.length();
private int endHTML;
private int startFragment = 123 + sourceURL.length();
private int endFragment;
public HtmlSelection(String html, String plainText) {
this.html = html;
this.plainText = plainText;
this.endHTML = this.startHTML + 28 + html.length();
this.endFragment = this.startFragment + html.length() + 18;
}
public DataFlavor[] getTransferDataFlavors() {
return (DataFlavor[]) htmlFlavors.toArray(new DataFlavor[htmlFlavors.size()]);
}
public boolean isDataFlavorSupported(DataFlavor flavor) {
return htmlFlavors.contains(flavor);
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException {
if (flavor == DataFlavor.stringFlavor) {
return plainText;
} else if (flavor == DataFlavor.allHtmlFlavor || flavor == DataFlavor.fragmentHtmlFlavor) {
return String.format(\"Version:%1.1f\\r\\nStartHTML:%08d\\r\\nEndHTML:%08d\\r\\nStartFragment:%08d\\r\\nEndFragment:%08d\\r\\nSourceURL:%s\\r\\n<html><body>\\r\\n<!--StartFragment-->%s<!--EndFragment-->\\r\\n</body></html>\", this.version,this.startHTML,this.endHTML,this.startFragment,this.endFragment,this.sourceURL,this.html);
}
throw new UnsupportedFlavorException(flavor);
}
}
"]
Which would give you an external function that accepts two inputs:
- HTML text which contains a link
- Plain text for places where pasting link is not possible (like a simple text editor).
Result
javaCopyLink["<a href=\"http://example.com\">link</a>", "plain text"]
![enter image description here](https://cdn.statically.io/img/i.sstatic.net/PPzqZ.gif)