├── .appcast.xml ├── .gitignore ├── README.md ├── assets └── icon.png ├── data-from-clipboard.sketchplugin.zip ├── démo data from clipboard.gif ├── package-lock.json ├── package.json └── src ├── manifest.json └── my-command.js /.appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build artefacts 2 | *.sketchplugin 3 | 4 | # npm 5 | node_modules 6 | .npm 7 | npm-debug.log 8 | 9 | # mac 10 | .DS_Store 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Copy data from the clipboard (look Ma, no file) 2 | 3 | [The latest release is here](https://github.com/Saint-loup/data-from-clipboard/releases/latest/download/data-from-clipboard.sketchplugin.zip). Download, unzip and double-click on the .sketchplugin file. Bug reports and feedbacks are welcome. 4 | 5 | 6 | ### How it works 7 | 8 | Copy a list of text in your clipboard, paste it into text layers or symbols overrides. That's it. There's also a command to shuffle the order. 9 | 10 | ![](https://github.com/baptiste-roullin/data-from-clipboard/blob/38384e59bb37dfb6aaa1dc0e114a4acae9742f91/d%C3%A9mo%20data%20from%20clipboard.gif) 11 | 12 | Some of the code is adapted from [Automate-Sketch](https://github.com/Ashung/Automate-Sketch/blob/master/automate-sketch.sketchplugin/Contents/Sketch/Data/Supply_Data.js) 13 | -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baptiste-roullin/data-from-clipboard/fd415b794e59dd93a53849ea7a57186489d3814b/assets/icon.png -------------------------------------------------------------------------------- /data-from-clipboard.sketchplugin.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baptiste-roullin/data-from-clipboard/fd415b794e59dd93a53849ea7a57186489d3814b/data-from-clipboard.sketchplugin.zip -------------------------------------------------------------------------------- /démo data from clipboard.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/baptiste-roullin/data-from-clipboard/fd415b794e59dd93a53849ea7a57186489d3814b/démo data from clipboard.gif -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "data-from-clipboard", 3 | "repository": "https://github.com/baptiste-roullin/data-from-clipboard", 4 | "description": "Populate a bunch of layers from a list of text in the clipboard", 5 | "version": "0.6.1", 6 | "engines": { 7 | "sketch": ">=49.0" 8 | }, 9 | "skpm": { 10 | "name": "data-from-clipboard", 11 | "manifest": "src/manifest.json", 12 | "main": "data-from-clipboard.sketchplugin", 13 | "assets": [ 14 | "assets/**/*" 15 | ], 16 | "sketch-assets-file": "sketch-assets/icons.sketch" 17 | }, 18 | "scripts": { 19 | "build": "skpm-build", 20 | "watch": "skpm-build --watch", 21 | "start": "skpm-build --watch --run", 22 | "postinstall": "npm run build && skpm-link" 23 | }, 24 | "devDependencies": { 25 | "@skpm/builder": "^0.8.0", 26 | "sketch-utils": "^0.2.10" 27 | }, 28 | "author": "Baptiste " 29 | } -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/sketch-hq/SketchAPI/develop/docs/sketch-plugin-manifest-schema.json", 3 | "name": "Data from clipboard", 4 | "compatibleVersion": "94.1", 5 | "version": "0.6.1", 6 | "author": "Baptiste Roullin", 7 | "authorEmail": "baptiste@roullin.net", 8 | "homepage": "https://github.com/baptiste-roullin/data-from-clipboard", 9 | "suppliesData": true, 10 | "icon": "icon.png", 11 | "commands": [ 12 | { 13 | "script": "my-command.js", 14 | "identifier": "supply-data-from-clipboard", 15 | "handlers": { 16 | "actions": { 17 | "Startup": "onStartup", 18 | "Shutdown": "onShutdown", 19 | "SupplyTextFromClipboard": "onSupplyTextFromClipboard", 20 | "SupplyRandomTextFromClipboard": "onSupplyRandomTextFromClipboard" 21 | } 22 | } 23 | } 24 | ], 25 | "menu": { 26 | "isRoot": false, 27 | "title": "Data from clipboard", 28 | "items": [ 29 | "SupplyRandomTextFromClipboard", 30 | "SupplyTextFromClipboard" 31 | ] 32 | } 33 | } -------------------------------------------------------------------------------- /src/my-command.js: -------------------------------------------------------------------------------- 1 | // documentation: https://developer.sketchapp.com/reference/api/ 2 | 3 | 4 | //import { log } from 'console' 5 | const sketch = require('sketch') 6 | const { DataSupplier } = sketch 7 | const UI = require('sketch/ui') 8 | const util = require('util') 9 | var utils = require('sketch-utils') 10 | 11 | export function onStartup() { 12 | DataSupplier.registerDataSupplier("public.text", "Text from clipboard", "SupplyTextFromClipboard") 13 | DataSupplier.registerDataSupplier("public.text", "Random text from clipboard", "SupplyRandomTextFromClipboard") 14 | 15 | } 16 | 17 | export function onShutdown() { 18 | // Deregister the plugin 19 | DataSupplier.deregisterDataSuppliers() 20 | } 21 | 22 | function shuffleArray(array) { 23 | for (let i = array.length - 1; i > 0; i--) { 24 | const j = Math.floor(Math.random() * i) 25 | const temp = array[i] 26 | array[i] = array[j] 27 | array[j] = temp 28 | } 29 | return array 30 | } 31 | 32 | export function onSupplyTextFromClipboard(context) { 33 | supplyOrderedData(context, getPasteBoardData(context)) 34 | }; 35 | 36 | export function onSupplyRandomTextFromClipboard(context) { 37 | supplyRandomData(context, getPasteBoardData(context)) 38 | }; 39 | 40 | function getPasteBoardData(context) { 41 | let pasteboard = NSPasteboard.generalPasteboard() 42 | let supportedPasteboardTypes = [ 43 | "public.rtf", 44 | "public.string", 45 | "public.plain-text", 46 | "public.utf8-plain-text", 47 | "public.multipleTextSelection", 48 | "public.html", 49 | "com.apple.traditional-mac-plain-text", 50 | "org.mozilla.custom-clipdata", 51 | "org.chromium.web-custom-data", 52 | "NSStringPboardType", 53 | "public.utf16-external-plain-text", 54 | "public.utf16-plain-text", 55 | "com.apple.iWork.TSPNativeData", 56 | "public.text", 57 | "com.apple.webarchive", 58 | "com.adobe.pdf", 59 | "com.microsoft.word.doc", 60 | "com.microsoft.excel.xls", 61 | "com.microsoft.powerpoint.ppt" 62 | ] 63 | 64 | // test wether pasteboard not empty 65 | if (pasteboard.pasteboardItems().count() > 0) { 66 | let pasteboardType = pasteboard.pasteboardItems().firstObject().types().firstObject() 67 | //console.log(pasteboardType, supportedPasteboardTypes.indexOf(String(pasteboardType))) 68 | 69 | // test wether content is text 70 | if (supportedPasteboardTypes.indexOf(String(pasteboardType)) > -1) { 71 | 72 | let clipboardString = pasteboard.pasteboardItems().firstObject().stringForType(NSPasteboardTypeString) 73 | //console.log(/\n\n/.test(clipboardString)); 74 | let clipboardArray = clipboardString.replace(/\n+/, "\n").split(/\n/g) 75 | return clipboardArray 76 | } 77 | else { 78 | UI.message("Content in clipboard is not text") 79 | //console.log(pasteboard.pasteboardItems().firstObject().stringForType(NSPasteboardTypeString)) 80 | return false 81 | } 82 | } 83 | else { 84 | UI.message("Clipboard is empty") 85 | return false 86 | } 87 | } 88 | 89 | function replaceSelection(context, newData, mode) { 90 | for (var i = 0; i < context.data.requestedCount; i++) { 91 | console.log(utils.prepareValue(context.data.items[0]).type) 92 | if (utils.prepareValue(context.data.items[i]).type == 'MSSelectionItem' && mode != 'random') { 93 | UI.message("Please select a text layer.") 94 | } 95 | else { 96 | DataSupplier.supplyData(context.data.key, newData) 97 | } 98 | } 99 | } 100 | 101 | function supplyOrderedData(context, newData) { 102 | if (!newData) { 103 | return 104 | } 105 | replaceSelection(context, newData) 106 | } 107 | 108 | function supplyRandomData(context, newData) { 109 | if (!newData) { 110 | return 111 | } 112 | let shufflednewData = shuffleArray(newData) 113 | replaceSelection(context, shufflednewData, "random") 114 | } --------------------------------------------------------------------------------