library-symbol-replacer
library-symbol-replacer copied to clipboard
offer to merge local symbols that don't match names
The plugin works great for the case of cross document copy-pasted symbols, but it would be great to complete the symbol upgrading process by providing a list of the local symbols that don't name match and offer to replace all of their instances with existing library symbols.
Thanks for FR 😄 What's the use-case for symbols that don't name-match? How were the libraries constructed? And picking a symbol-symbol mapping manually for all non-matching symbols sounds a bit cumbersome
The use case are:
- when we change the name of a library symbol and need to retrofit local symbols that haven't been updated in the meantime.
- Sometimes you need to change the structure of a symbol (like splitting it up into different versions), and you need to replace old instances by a a new one.
I guess I'm simply asking for a way to select a local symbol and replace all its instances by another symbol (synced or not).
Sounds like @sonburn's new plugin might be just what you need
https://www.facebook.com/groups/sketchformac/permalink/1941422106109938 https://github.com/sonburn/symbol-swapper
no, that one requires that the names match.
Damn, true, sorry!
I don't have time to make a full plugin, but here's the code to replace a selected symbol with a symbol from a library. Change the LIB_NAME
and SYMBOL_NAME
as necessary.
You can run it by pressing Control+Shift+K, pasting it in, and pressing Run
var libraryName = 'LIB_NAME';
var symbolName = 'SYMBOL_NAME';
var localSymbol = context.selection.firstObject();
var controller = AppController.sharedInstance().librariesController();
var libraries = controller.userLibraries();
var library = null;
for (var i = 0; i < libraries.length; i++) {
if (!libraries[i] || !libraries[i].document()) { continue; }
if(String(libraries[i].name()) === String(libraryName)) {
library = libraries[i];
break;
}
}
if(!library){
log('Library not found');
return;
}
var symbol = null;
var librarySymbols = library.document().documentData().localSymbols();
for(var i = 0 ; i < librarySymbols.length ; ++i){
var librarySymbol = librarySymbols[i];
var librarySymbolName = String(librarySymbol.name());
if(librarySymbolName === String(symbolName)){
symbol = librarySymbol;
}
}
if(!symbol){
log('Symbol not found in Library');
return;
}
var documentData = context.document.documentData();
var importedSymbol = controller.importForeignSymbol_fromLibrary_intoDocument_(
symbol, library, documentData);
var instances = localSymbol.allInstances();
for(var j = 0 ; j < instances.length ; ++j){
instances[j].changeInstanceToSymbol(importedSymbol.symbolMaster());
}
var idmap = {};
var localId = String(localSymbol.symbolID());
idmap[localId] = String(importedSymbol.symbolMaster().symbolID());
var predicate = NSPredicate.predicateWithFormat("className == %@", "MSSymbolInstance");
var filteredArray = NSArray.array()
var loopPages = context.document.pages().objectEnumerator()
var page = null;
var scope = null;
while (page = loopPages.nextObject()) {
scope = page.children();
filteredArray = filteredArray.arrayByAddingObjectsFromArray(
scope.filteredArrayUsingPredicate(predicate))
}
for(var i = 0 ; i < filteredArray.length ; ++i){
MSLayerPaster.updateOverridesOnInstance_withIDMap_(filteredArray[i], idmap);
}
context.document.reloadInspector();
and here it is in action https://cl.ly/1D0C0R1v1e3X
THX!
Just FYI, I added my own take on this functionality in Symbol Swapper v0.3 (https://github.com/sonburn/symbol-swapper) - Added ability to choose a symbol of a different name, and to only swap selected instance (not siblings).
@sonburn thx!