Skip to content

Commit

Permalink
Merge pull request #13 from DWilliames/develop
Browse files Browse the repository at this point in the history
Added a bunch of features
  • Loading branch information
DWilliames authored Nov 23, 2017
2 parents 1500a18 + 0237e3f commit 8aaf3a9
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 58 deletions.
14 changes: 14 additions & 0 deletions .appcast.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,19 @@
</description>
<enclosure url="https://github.com/DWilliames/Google-sheets-content-sync-sketch-plugin/releases/download/v1.1.2/Google.sheets.content.sync.sketchplugin.zip" sparkle:version="1.1.2" />
</item>
<item>
<title>Version 1.1.2</title>
<description>
<![CDATA[
<ul>
<li>Now it should save your Sheets URL specific to each document</li>
<li>Added support for symbols in Sketch 48</li>
<li>Now you can use image URLs (even for symbols)</li>
<li>Added ability to randomise the item number/li>
</ul>
]]>
</description>
<enclosure url="https://github.com/DWilliames/Google-sheets-content-sync-sketch-plugin/releases/download/v1.2/Google_sheets_content_sync.sketchplugin.zip" sparkle:version="1.2" />
</item>
</channel>
</rss>
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

This file was deleted.

189 changes: 164 additions & 25 deletions Google sheets content sync.sketchplugin/Contents/Sketch/main.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
@import 'defaults.js'
@import 'utilities.js'

var selection, doc, scriptPath, scriptFolder, app
var iconImage, sheetValues

// Saving and receiving document URL
var docData, command, pluginIdentifier, url

var appVersion, plugin

// Setup variables based on the context
function setup(context) {
selection = context.selection
doc = context.document
scriptPath = context.scriptPath
scriptFolder = scriptPath.stringByDeletingLastPathComponent()
app = NSApplication.sharedApplication()
plugin = context.plugin

iconImage = NSImage.alloc().initByReferencingFile(context.plugin.urlForResourceNamed("icon.png").path())

fetchDefaults(doc.hash())
appVersion = MSApplicationMetadata.metadata().appVersion

docData = context.document.documentData()
command = context.command;

pluginIdentifier = context.plugin.identifier()

url = command.valueForKey_onLayer_forPluginIdentifier('docURL', docData, pluginIdentifier)
if (!url) {
url = ''
}

}

// ****************************
Expand Down Expand Up @@ -50,7 +66,8 @@ function updateSheetURL() {
// Fetch the content from the Sheets URL
// Update the values accordingly
function syncContent() {
print('Importing content from: ' + defaultsURL)

print('Importing content from: ' + url)

// If the user didn't enter a valid URL, tell them, then exit
var sheetId = validateURL()
Expand Down Expand Up @@ -97,11 +114,26 @@ function syncContent() {
// Store new overrides that need to be made
var overrides = {}


child.symbolMaster().children().forEach(function(symbolLayer) {
// Ignore layers that are not text layers
// Ignore layers that are not text layers or shapes
// Only include layers that have a '#' in the name
if (!symbolLayer.isMemberOfClass(MSTextLayer) || symbolLayer.name().indexOf('#') < 0)
if (!(symbolLayer.isMemberOfClass(MSTextLayer) || symbolLayer.isMemberOfClass(MSShapeGroup)) || symbolLayer.name().indexOf('#') < 0) {
return
}


var objectID = symbolLayer.objectID().toString()
var existingOverrides = child.overrides()
if (existingOverrides == null) {
// no overrides exist, add one
child.overrides = { objectID : "overrideText"}
existingOverrides = child.overrides()
}

// get the existing overrides and create a mutable copy
var mutableOverrides = NSMutableDictionary.dictionaryWithDictionary(existingOverrides)
mutableOverrides.setObject_forKey(NSMutableDictionary.dictionaryWithDictionary(existingOverrides.objectForKey(0)),0)

var nameFormat = formatName(symbolLayer.name())
var childName = nameFormat.lookupName
Expand All @@ -114,42 +146,82 @@ function syncContent() {
nameFormat.index = instanceIndex
}

var index = nameFormat.index.toString()
if (index.toLowerCase() === 'n' || index.toLowerCase() === 'x') {
index = Math.floor(Math.random() * values.length) + 1
} else {
index = parseInt(index)
}

// If there's no value associated, skip it
if (!values || values.length < 1) {
return
}

// Set the value of the text layer accordingly
// Based on if it was given an index, otherwise return the first one
if (values && values.length > 0) {
var value = (values.length >= nameFormat.index) ? values[nameFormat.index - 1] : 'N/A'
overrides[symbolLayer.objectID()] = value == '' ? 'N/A' : value
} else {
overrides[symbolLayer.objectID()] = 'N/A'
var value = (values.length >= index) ? values[index - 1] : ''
var textValue = (value == '' ? 'N/A' : value)

if (symbolLayer.isMemberOfClass(MSTextLayer)) {
mutableOverrides.setObject_forKey(textValue, objectID)

} else if (symbolLayer.isMemberOfClass(MSShapeGroup)) {
var imageURL = imageURLFromValue(value)
if (imageURL) {
var imageData = getImageDataFromURL(imageURL)
mutableOverrides.setObject_forKey(imageData, objectID)
}

}
})

// Apply the new overrides
child.addOverrides_ancestorIDs(overrides, nil)
child.overrides = mutableOverrides

})
}

// Only check text layers
// Only check text layers or shape layers
// Only include layers that have a '#' in the name
if (!child.isMemberOfClass(MSTextLayer) || child.name().indexOf('#') < 0)
if (!(child.isMemberOfClass(MSTextLayer) || child.isMemberOfClass(MSShapeGroup)) || child.name().indexOf('#') < 0)
return


var nameFormat = formatName(child.name())
var childName = nameFormat.lookupName
var values = pageValues[childName]

// If there's no value associated, skip it
if (!values || values.length < 1) {
return
}

var index = nameFormat.index.toString()
if (index.toLowerCase() === 'n' || index.toLowerCase() === 'x') {
index = Math.floor(Math.random() * values.length) + 1
} else {
index = parseInt(index)
}

// Set the value of the text layer accordingly
// Based on if it was given an index, otherwise return the first one
if (values && values.length > 0) {
var value = (values.length >= nameFormat.index) ? values[nameFormat.index - 1] : 'N/A'
child.setStringValue(value == '' ? 'N/A' : value)
} else {
child.setStringValue('N/A')
var value = (values.length >= index) ? values[index - 1] : ''
var textValue = (value == '' ? 'N/A' : value)

if (child.isMemberOfClass(MSTextLayer)) {
child.setStringValue(textValue)
} else if (child.isMemberOfClass(MSShapeGroup)) {
// Get an image URL for the shape
var imageURL = imageURLFromValue(value)
if (imageURL) {
var imageData = getImageDataFromURL(imageURL)
fillLayerWithImageData(child, imageData)
}
}
})
})

saveDefaults(doc.hash())

command.setValue_forKey_onLayer_forPluginIdentifier(url, 'docURL', docData, pluginIdentifier)

doc.showMessage("Content successfully imported! ⚡️")

Expand All @@ -164,11 +236,59 @@ function syncContent() {
// Validate whether the URL contains a valid sheet ID
// Return the SheetID, or null
function validateURL() {
if (url === '') {
return null
}

var regex = /\/spreadsheets\/d\/([a-zA-Z0-9-_]+)/g
var matches = regex.exec(defaultsURL)
var matches = regex.exec(url)
return (matches && matches.length > 1) ? matches[1] : null
}

// Validate if there's a URL for the image as the value in the sheet
function imageURLFromValue(value) {
if (value === '') {
return null
}

var regex = /(https?:\/\/.*\.(?:png|jpg|jpeg))/i
var matches = regex.exec(value)
return (matches && matches.length > 1) ? matches[1] : null
}

// Downloads an image from a URL and returns it as a NSImageData
function getImageDataFromURL(url) {

var request = NSURLRequest.requestWithURL(NSURL.URLWithString(url))
var data = NSURLConnection.sendSynchronousRequest_returningResponse_error(request, null, null)

var image

if (!data){
print('Error fetching image')
doc.showMessage("Error in fetching image URL.")
image = NSImage.alloc().initByReferencingFile(plugin.urlForResourceNamed("Placeholder.png").path())
} else {
image = NSImage.alloc().initWithData(data)
}


if (isCurrentVersionBefore('47')) {
return MSImageData.alloc().initWithImage_convertColorSpace(image, false)
}

return MSImageData.alloc().initWithImage(image)
}

// Changes the fill of a layer to be the NSImageData passed in
function fillLayerWithImageData(layer, imageData) {
var fill = layer.style().fills().firstObject()

fill.setFillType(4)
fill.setImage(imageData)
fill.setPatternFillType(1)
}

// Show the options to the user - to enter their url
function showOptions() {

Expand All @@ -180,15 +300,15 @@ function showOptions() {
alert.addButtonWithTitle("Cancel")

var input = NSTextField.alloc().initWithFrame(NSMakeRect(0, 0, 300, 54))
input.setStringValue(defaultsURL)
input.setStringValue(url)
input.setPlaceholderString('Google Sheets publish URL')

alert.setAccessoryView(input)
var response = alert.runModal()

input.validateEditing()

defaultsURL = input.stringValue()
url = input.stringValue()

return response
}
Expand All @@ -212,7 +332,7 @@ function formatName(name) {

split = split[1].split('.')
if (split.length > 1) {
format.index = parseInt(split[1])
format.index = split[1]
}
format.lookupName = split[0]

Expand Down Expand Up @@ -312,3 +432,22 @@ function parseData(data) {
values: values
}
}


function compareVersion(a, b) {
var i, cmp, len, re = /(\.0)+[^\.]*$/;
a = (a + '').replace(re, '').split('.');
b = (b + '').replace(re, '').split('.');
len = Math.min(a.length, b.length);
for( i = 0; i < len; i++ ) {
cmp = parseInt(a[i], 10) - parseInt(b[i], 10);
if( cmp !== 0 ) {
return cmp;
}
}
return a.length - b.length;
}

function isCurrentVersionBefore(version) {
return compareVersion(appVersion, version) < 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Sync content within a Google Sheets document, to text layers — based on their names",
"author": "David Williames",
"homepage": "https://github.com/DWilliames/Google-sheets-content-sync-sketch-plugin",
"version": "1.1.2",
"version": "1.2",
"identifier": "com.davidwilliames.sketch-plugins.google-sheets-content-sync",
"compatibleVersion": 39,
"bundleVersion": 1,
Expand Down

0 comments on commit 8aaf3a9

Please sign in to comment.