From 4dc7f9f7c4be24f6ce5d179934fedbbc9b5cc7c4 Mon Sep 17 00:00:00 2001 From: Yigitcan Yurtsever Date: Fri, 24 May 2019 11:36:15 -0700 Subject: [PATCH 1/3] Implement actions for exporting colors and text styles --- .../Contents/Sketch/export.cocoascript | 194 +++++++++++++----- .../Contents/Sketch/manifest.json | 20 +- 2 files changed, 155 insertions(+), 59 deletions(-) diff --git a/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript b/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript index dedc93f..089e70b 100644 --- a/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript +++ b/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript @@ -1,30 +1,10 @@ var onRun = function (context) { var doc = context.document; - if (![doc fileURL] || [doc isDraft]) { - [NSApp displayDialog:@"Please save the document before exporting to Zeplin." withTitle:@"Document not saved"]; + if (!documentExportable(context)) { return; } - if ([doc isDocumentEdited]) { - var alert = [NSAlert alertWithMessageText:@"Document not saved" defaultButton:@"Save and Continue" alternateButton:@"Cancel" otherButton:@"Continue" informativeTextWithFormat:@"To capture the latest changes in this Sketch document, Zeplin needs to save it first.\n\n☝️ This might take a bit, depending on the document size."]; - - var response = [alert runModal]; - if (response == NSAlertDefaultReturn) { - [doc showMessage:@"Saving document…"]; - - [doc saveDocument:nil]; - while ([doc isDocumentEdited]) { - [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; - } - } else if (response == NSAlertAlternateReturn) { - return; - } - - response = nil; - alert = nil; - } - var foreignSymbolsUpToDate = true; // `MSBadgeController` is defined on Sketch 44, `activeWindowBadgingActions` is defined on Sketch 46. try { @@ -120,6 +100,120 @@ var onRun = function (context) { artboards = nil; + var artboardNamesByIdentifier = {}; + var allArtboardsLoop = [[doc valueForKeyPath:@"pages.@distinctUnionOfArrays.artboards"] objectEnumerator]; + var artboard = nil; + while (artboard = [allArtboardsLoop nextObject]) { + artboardNamesByIdentifier[artboard.objectID()] = artboard.name(); + } + + artboard = nil; + allArtboardsLoop = nil; + + var path = temporaryPath(); + var directives = defaultDirectives(context, path); + [directives setObject:@"artboards" forKey:@"type"]; + [directives setObject:artboardIds forKey:@"artboardIds"]; + [directives setObject:pageIds forKey:@"pageIds"]; + [directives setObject:uniqueArtboardSizes forKey:@"artboardSizes"]; + [directives setObject:artboardNamesByIdentifier forKey:@"artboardNames"]; + [directives setObject:containsArtboard forKey:@"containsArtboard"]; + + artboardIds = nil; + pageIds = nil; + uniqueArtboardSizes = nil; + artboardNamesByIdentifier = nil; + + writeDirectives(directives, path); + + directives = nil; + + launchZeplin(context, path); + + path = nil; +} + +var exportColors = function (context) { + if (!documentExportable(context)) { + return; + } + + var path = temporaryPath(); + var directives = defaultDirectives(context, path); + [directives setObject:@"colors" forKey:@"type"]; + + writeDirectives(directives, path); + + directives = nil; + + launchZeplin(context, path); + + path = nil; +} + +var exportTextStyles = function (context) { + if (!documentExportable(context)) { + return; + } + + var path = temporaryPath(); + var directives = defaultDirectives(context, path); + [directives setObject:@"textStyles" forKey:@"type"]; + + writeDirectives(directives, path); + + directives = nil; + + launchZeplin(context, path); + + path = nil; +} + +var documentExportable = function (context) { + var doc = context.document; + + if (![doc fileURL] || [doc isDraft]) { + [NSApp displayDialog:@"Please save the document before exporting to Zeplin." withTitle:@"Document not saved"]; + + return false; + } + + if ([doc isDocumentEdited]) { + var alert = [NSAlert alertWithMessageText:@"Document not saved" defaultButton:@"Save and Continue" alternateButton:@"Cancel" otherButton:@"Continue" informativeTextWithFormat:@"To capture the latest changes in this Sketch document, Zeplin needs to save it first.\n\n☝️ This might take a bit, depending on the document size."]; + + var response = [alert runModal]; + if (response == NSAlertDefaultReturn) { + [doc showMessage:@"Saving document…"]; + + [doc saveDocument:nil]; + while ([doc isDocumentEdited]) { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; + } + } else if (response == NSAlertAlternateReturn) { + return false; + } + + response = nil; + alert = nil; + } + + return true; +} + +var temporaryPath = function() { + var name = [[[NSUUID UUID] UUIDString] stringByAppendingPathExtension:@"zpl"]; + var temporaryDirectory = NSTemporaryDirectory(); + var path = [temporaryDirectory stringByAppendingPathComponent:name]; + + temporaryDirectory = nil; + name = nil; + + return path; +} + +var defaultDirectives = function(context, path) { + var doc = context.document; + var format = @"json"; var readerClass = NSClassFromString(@"MSDocumentReader"); var jsonReaderClass = NSClassFromString(@"MSDocumentZippedJSONReader"); @@ -129,8 +223,8 @@ var onRun = function (context) { jsonReaderClass = nil; readerClass = nil; - - var assetLibraries = []; + + var assetLibraries = []; // `MSAssetLibraryController` defined on Sketch 47. try { var assetLibrariesLoop = [[[[AppController sharedInstance] librariesController] libraries] objectEnumerator]; @@ -161,37 +255,15 @@ var onRun = function (context) { } catch (error) { log("Asset library paths by identifier failed with error “" + error + "”."); } - - var artboardNamesByIdentifier = {}; - var allArtboardsLoop = [[doc valueForKeyPath:@"pages.@distinctUnionOfArrays.artboards"] objectEnumerator]; - var artboard = nil; - while (artboard = [allArtboardsLoop nextObject]) { - artboardNamesByIdentifier[artboard.objectID()] = artboard.name(); - } - artboard = nil; - allArtboardsLoop = nil; - - var name = [[[NSUUID UUID] UUIDString] stringByAppendingPathExtension:@"zpl"]; - var temporaryDirectory = NSTemporaryDirectory(); - var path = [temporaryDirectory stringByAppendingPathComponent:name]; - - temporaryDirectory = nil; - name = nil; - var version = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; var sketchtoolPath = [[NSBundle mainBundle] pathForResource:@"sketchtool" ofType:nil inDirectory:@"sketchtool/bin"]; var sketchmigratePath = [[NSBundle mainBundle] pathForResource:@"sketchmigrate" ofType:nil inDirectory:@"sketchtool/bin"]; - + var directives = [NSMutableDictionary dictionary]; [directives setObject:[[doc fileURL] path] forKey:@"path"]; - [directives setObject:artboardIds forKey:@"artboardIds"]; - [directives setObject:pageIds forKey:@"pageIds"]; [directives setObject:format forKey:@"format"]; - [directives setObject:uniqueArtboardSizes forKey:@"artboardSizes"]; [directives setObject:assetLibraries forKey:@"assetLibraries"]; - [directives setObject:artboardNamesByIdentifier forKey:@"artboardNames"]; - [directives setObject:containsArtboard forKey:@"containsArtboard"]; if (version) { [directives setObject:version forKey:@"version"]; } @@ -201,35 +273,43 @@ var onRun = function (context) { if (sketchmigratePath) { [directives setObject:sketchmigratePath forKey:@"sketchmigratePath"]; } - + + format = nil; version = nil; sketchmigratePath = nil; sketchtoolPath = nil; - artboardNames = nil; assetLibraries = nil; - format = nil; - uniqueArtboardSizes = nil; - pageIds = nil; - artboardIds = nil; - + + return directives +} + +var writeDirectives = function (directives, path) { + if (!path) { + return nil; + } + [directives writeToFile:path atomically:false]; - directives = nil; - + + return path; +} + +var launchZeplin = function (context, path) { + var doc = context.document; var workspace = [NSWorkspace sharedWorkspace]; var applicationPath = [workspace absolutePathForAppBundleWithIdentifier:@"io.zeplin.osx"]; if (!applicationPath) { [NSApp displayDialog:@"Please make sure that you installed and launched it: https://zpl.io/download" withTitle:"Could not find Zeplin"]; + return; } [doc showMessage:@"Launching Zeplin!"]; [workspace openFile:path withApplication:applicationPath andDeactivate:true]; - + workspace = nil; applicationPath = nil; - path = nil; } var shortcutHelp = function (context) { diff --git a/Zeplin.sketchplugin/Contents/Sketch/manifest.json b/Zeplin.sketchplugin/Contents/Sketch/manifest.json index 48ae143..06420bd 100644 --- a/Zeplin.sketchplugin/Contents/Sketch/manifest.json +++ b/Zeplin.sketchplugin/Contents/Sketch/manifest.json @@ -1,6 +1,6 @@ { "name": "Zeplin", - "description": "Export artboards and symbols to a Zeplin project. 🚀", + "description": "Export artboards, symbols, colors and text styles to Zeplin. 🚀", "author": "Zeplin, Inc.", "authorEmail": "dev@zeplin.io", "homepage": "https://zeplin.io", @@ -13,7 +13,21 @@ "shortcut": "cmd ctrl e", "script": "export.cocoascript", "icon": "Icons/icZeplinRunner.png", - "description": "Export selected artboards and symbols to a Zeplin project. 🚀" + "description": "Export selected artboards and symbols to Zeplin." + }, { + "name": "Export Colors…", + "identifier": "exportColors", + "script": "export.cocoascript", + "handler": "exportColors", + "icon": "Icons/icZeplinRunner.png", + "description": "Export colors to Zeplin." + }, { + "name": "Export Text Styles…", + "identifier": "exportTextStyles", + "script": "export.cocoascript", + "handler": "exportTextStyles", + "icon": "Icons/icZeplinRunner.png", + "description": "Export text styles to Zeplin. 🚀" }, { "name": "Exclude Sublayers", "identifier": "exclude-sublayers", @@ -42,6 +56,8 @@ "menu": { "items": [ "export", + "exportColors", + "exportTextStyles", { "title": "Utilities", "items": [ From e5af71f1a44fd2548ed29ec38d5158320cf0fc5b Mon Sep 17 00:00:00 2001 From: Yigitcan Yurtsever Date: Sat, 8 Jun 2019 11:14:07 -0700 Subject: [PATCH 2/3] Address review comments --- Zeplin.sketchplugin/Contents/Sketch/export.cocoascript | 4 ++-- Zeplin.sketchplugin/Contents/Sketch/manifest.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript b/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript index 089e70b..1a4503b 100644 --- a/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript +++ b/Zeplin.sketchplugin/Contents/Sketch/export.cocoascript @@ -224,7 +224,7 @@ var defaultDirectives = function(context, path) { jsonReaderClass = nil; readerClass = nil; - var assetLibraries = []; + var assetLibraries = []; // `MSAssetLibraryController` defined on Sketch 47. try { var assetLibrariesLoop = [[[[AppController sharedInstance] librariesController] libraries] objectEnumerator]; @@ -280,7 +280,7 @@ var defaultDirectives = function(context, path) { sketchtoolPath = nil; assetLibraries = nil; - return directives + return directives; } var writeDirectives = function (directives, path) { diff --git a/Zeplin.sketchplugin/Contents/Sketch/manifest.json b/Zeplin.sketchplugin/Contents/Sketch/manifest.json index 06420bd..28dcf04 100644 --- a/Zeplin.sketchplugin/Contents/Sketch/manifest.json +++ b/Zeplin.sketchplugin/Contents/Sketch/manifest.json @@ -27,7 +27,7 @@ "script": "export.cocoascript", "handler": "exportTextStyles", "icon": "Icons/icZeplinRunner.png", - "description": "Export text styles to Zeplin. 🚀" + "description": "Export text styles to Zeplin." }, { "name": "Exclude Sublayers", "identifier": "exclude-sublayers", From e3f7311372ff35db9ca7aeac03a916805a2346f2 Mon Sep 17 00:00:00 2001 From: Emmar Kardeslik Date: Wed, 19 Jun 2019 17:28:10 +0300 Subject: [PATCH 3/3] Bump version --- Zeplin.sketchplugin/Contents/Sketch/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zeplin.sketchplugin/Contents/Sketch/manifest.json b/Zeplin.sketchplugin/Contents/Sketch/manifest.json index 28dcf04..ff4de2d 100644 --- a/Zeplin.sketchplugin/Contents/Sketch/manifest.json +++ b/Zeplin.sketchplugin/Contents/Sketch/manifest.json @@ -4,7 +4,7 @@ "author": "Zeplin, Inc.", "authorEmail": "dev@zeplin.io", "homepage": "https://zeplin.io", - "version": "1.7", + "version": "1.8", "identifier": "io.zeplin.sketch-plugin", "icon": "Icons/icZeplin.png", "commands": [{