├── assets └── icon.png ├── .gitignore ├── .sketchpacks.json ├── src ├── manifest.json └── library-unlinker.js ├── package.json ├── LICENSE ├── .appcast.xml └── README.md /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/perrysmotors/sketch-library-unlinker/HEAD/assets/icon.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # build artifacts 2 | LibraryUnlinker.sketchplugin 3 | 4 | # npm 5 | node_modules 6 | .npm 7 | npm-debug.log 8 | 9 | # mac 10 | .DS_Store 11 | 12 | # WebStorm 13 | .idea 14 | -------------------------------------------------------------------------------- /.sketchpacks.json: -------------------------------------------------------------------------------- 1 | { 2 | "schema_version": "1.0.0", 3 | "manifest_path": "src/manifest.json", 4 | "appcast_path": "https://raw.githubusercontent.com/perrysmotors/sketch-library-unlinker/master/.appcast.xml" 5 | } 6 | -------------------------------------------------------------------------------- /src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "compatibleVersion": 49, 3 | "bundleVersion": 1, 4 | "icon": "icon.png", 5 | "commands": [ 6 | { 7 | "name": "Unlink Library", 8 | "identifier": "library-unlinker.unlinkLibrary", 9 | "script": "./library-unlinker.js" 10 | }, 11 | { 12 | "name": "Unlink Symbols Missing From Libraries", 13 | "identifier": "library-unlinker.unlinkMissingSymbols", 14 | "script": "./library-unlinker.js", 15 | "handler": "onUnlinkMissingSymbols" 16 | } 17 | ], 18 | "menu": { 19 | "title": "Library Unlinker", 20 | "items": [ 21 | "library-unlinker.unlinkLibrary", 22 | "library-unlinker.unlinkMissingSymbols" 23 | ] 24 | } 25 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sketch-library-unlinker", 3 | "description": "Unlink symbols linked to a specific library, or unlink symbols that have been deleted in their libraries.", 4 | "author": "Giles Perry (http://gilesperry.info/)", 5 | "version": "3.0.3", 6 | "engines": { 7 | "sketch": ">=3.0" 8 | }, 9 | "skpm": { 10 | "name": "Sketch Library Unlinker", 11 | "manifest": "src/manifest.json", 12 | "identifier": "com.gilesperry.sketch-library-unlinker", 13 | "main": "LibraryUnlinker.sketchplugin", 14 | "assets": [ 15 | "assets/**/*" 16 | ] 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.7.5" 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/perrysmotors/sketch-library-unlinker.git" 30 | }, 31 | "license": "MIT" 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Giles Perry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Library Unlinker plugin for Sketch 2 | [![Download from Sketchpacks.com](https://badges.sketchpacks.com/plugins/com.gilesperry.sketch-library-unlinker/version.svg)](https://api.sketchpacks.com/v1/plugins/com.gilesperry.sketch-library-unlinker/download) [![Compatible Sketch Version](https://badges.sketchpacks.com/plugins/com.gilesperry.sketch-library-unlinker/compatibility.svg)](https://sketchpacks.com/perrysmotors/sketch-library-unlinker) 3 | 4 | A Sketch plugin that can unlink symbols linked to a specific library, or unlink symbols that have been deleted in their libraries. 5 | 6 | _This plugin was created using `skpm`. For a detailed explanation on how things work, checkout the [skpm Readme](https://github.com/skpm/skpm/blob/master/README.md)._ 7 | 8 | ## Features 9 | - Select a library to unlink all its symbols that are linked to the current document. 10 | - ***New in Version 3*** – Unlink any symbols that are missing from their libraries. 11 | 12 | If library symbol is used in a document and later it is deleted from the library it remains in the document but cannot be updated. This plugin will unlink all such symbols adding their symbol masters to the document. 13 | 14 | ## Installation 15 | 16 | * [Download](../../releases/latest/download/LibraryUnlinker.sketchplugin.zip) the latest release of the plugin 17 | * Un-zip 18 | * Double-click on `LibraryUnlinker.sketchplugin` 19 | 20 | or... 21 | 22 | [![Install Sketch Library Unlinker with Sketchpacks](http://sketchpacks-com.s3.amazonaws.com/assets/badges/sketchpacks-badge-install.png "Install Sketch Library Unlinker with Sketchpacks")](https://sketchpacks.com/perrysmotors/sketch-library-unlinker/install) 23 | 24 | --- 25 | 26 | **If you are using this plugin, please 'star' the project**. It's a simple way to help me see how many people are using it. 27 | 28 | If you ***love*** this plugin, why not shout me a coffee ☕️ via [PayPal](https://www.paypal.me/perrysmotors/2) to share the love! 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/library-unlinker.js: -------------------------------------------------------------------------------- 1 | var UI = require("sketch/ui"), 2 | DOM = require("sketch/dom"), 3 | SymbolMaster = DOM.SymbolMaster, 4 | Page = DOM.Page; 5 | 6 | export default function() { 7 | var document = DOM.getSelectedDocument(), 8 | documentData = document.sketchObject.documentData(), 9 | foreignSymbolList = documentData.foreignSymbols(), 10 | foreignLibraryNames = [], 11 | foreignLibraryIDs = []; 12 | 13 | if (foreignSymbolList.length > 0) { 14 | foreignSymbolList.forEach(foreignSymbol => { 15 | let libraryName = String(foreignSymbol.sourceLibraryName()), 16 | libraryID = String(foreignSymbol.libraryID()); 17 | 18 | if (!foreignLibraryIDs.includes(libraryID)) { 19 | foreignLibraryIDs.push(libraryID); 20 | foreignLibraryNames.push(libraryName); 21 | } 22 | }); 23 | 24 | UI.getInputFromUser( 25 | "Select a library to unlink?", 26 | { 27 | type: UI.INPUT_TYPE.selection, 28 | possibleValues: foreignLibraryNames 29 | }, 30 | (err, value) => { 31 | if (err) { 32 | // most likely the user canceled the input 33 | return; 34 | } else { 35 | let index = foreignLibraryNames.findIndex(name => name === value); 36 | let selectedLibraryID = foreignLibraryIDs[index]; 37 | 38 | let page = new Page({ 39 | name: "Symbols from " + value, 40 | parent: document, 41 | selected: true 42 | }); 43 | 44 | let count = unlinkLibrary(page, foreignSymbolList, selectedLibraryID); 45 | 46 | if (count == 1) { 47 | UI.message("1 symbol was unlinked from " + value); 48 | } else { 49 | UI.message(count + " symbols were unlinked from " + value); 50 | } 51 | return; 52 | } 53 | } 54 | ); 55 | } else { 56 | UI.message("This file is not linked to any libraries"); 57 | } 58 | } 59 | 60 | export function onUnlinkMissingSymbols() { 61 | var document = DOM.getSelectedDocument(), 62 | documentData = document.sketchObject.documentData(), 63 | foreignSymbolList = documentData.foreignSymbols(); 64 | 65 | let notFoundList = []; 66 | 67 | if (foreignSymbolList.length > 0) { 68 | foreignSymbolList.forEach(foreignSymbol => { 69 | let assetLibraryController = AppController.sharedInstance().librariesController(); 70 | let libraryForSymbol = assetLibraryController.libraryForShareableObject( 71 | foreignSymbol.symbolMaster() 72 | ); 73 | 74 | let masterFromLibrary = foreignSymbol.masterFromLibrary(libraryForSymbol); 75 | 76 | if (!masterFromLibrary) { 77 | notFoundList.push(foreignSymbol); 78 | } 79 | }); 80 | 81 | if (notFoundList.length > 0) { 82 | let page = new Page({ 83 | name: "Symbols missing from libraries", 84 | parent: document, 85 | selected: true 86 | }); 87 | 88 | let count = unlinkSymbols(page, notFoundList); 89 | 90 | if (count == 1) { 91 | UI.message("1 symbol was unlinked"); 92 | } else { 93 | UI.message(count + " symbols were unlinked"); 94 | } 95 | } else { 96 | UI.message("This document does not contain any symbols that are missing from their libraries"); 97 | } 98 | } else { 99 | UI.message("This file is not linked to any libraries"); 100 | } 101 | } 102 | 103 | //////////////////////////////////////////////////////////////////////////////// 104 | 105 | function unlinkLibrary(page, foreignSymbolList, libraryID) { 106 | let symbols = foreignSymbolList 107 | .slice(0) 108 | .filter(symbol => symbol.libraryID() == libraryID); 109 | 110 | return unlinkSymbols(page, symbols); 111 | } 112 | 113 | function unlinkSymbols(page, symbols) { 114 | let x = 0; 115 | 116 | symbols.forEach(symbol => { 117 | symbol.unlinkFromRemote(); 118 | let master = SymbolMaster.fromNative(symbol.symbolMaster()); 119 | master.parent = page; 120 | master.frame = master.frame.offset(x, 0); 121 | x = x + master.frame.width + 100; 122 | }); 123 | 124 | return symbols.length; 125 | } 126 | --------------------------------------------------------------------------------