From 0834edc2f9bad3be07d687e0a5a1131ffd5eaa06 Mon Sep 17 00:00:00 2001 From: Matteo Gratton Date: Thu, 5 May 2022 13:44:11 +0100 Subject: [PATCH] Add theme management. Add stettings js. Update the plugin version --- .../Contents/Sketch/color-functions.js | 60 ++- .../Contents/Sketch/create-color-scale.js | 4 +- .../Sketch/create-typography-scale.js | 376 +++++++++--------- .../Contents/Sketch/manifest.json | 2 +- .../Contents/Sketch/settings.js | 49 +++ DS-Core.sketchplugin/Contents/appcast.xml | 4 +- 6 files changed, 290 insertions(+), 205 deletions(-) create mode 100644 DS-Core.sketchplugin/Contents/Sketch/settings.js diff --git a/DS-Core.sketchplugin/Contents/Sketch/color-functions.js b/DS-Core.sketchplugin/Contents/Sketch/color-functions.js index b5731af..3ed11de 100644 --- a/DS-Core.sketchplugin/Contents/Sketch/color-functions.js +++ b/DS-Core.sketchplugin/Contents/Sketch/color-functions.js @@ -1,11 +1,12 @@ -function increase_brightness(hex, percent) { - // strip the leading # if it's there - hex = hex.replace(/^\s*#|\s*$/g, ""); +// ********************************************************** +// General color functions for all the scripts +// import via @import(@import "color-functions.js") at the very +// beginning of your script (after the var onRun() statement) +// ********************************************************** - // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF` - if (hex.length == 3) { - hex = hex.replace(/(.)/g, "$1$1"); - } +/// Brightness management for color scales +function increase_brightness(hex, percent) { + hex = standardizeHex(hex); let r = parseInt(hex.substr(0, 2), 16); let g = parseInt(hex.substr(2, 2), 16); @@ -38,6 +39,22 @@ function increase_brightness(hex, percent) { return RGBToHex(r, g, b); } +/// Invert Colors +function invertColor(hex) { + hex = standardizeHex(hex); + + if (hex.length !== 6 && hex.length !== 8) { + throw new Error("Invalid HEX color."); + } + // invert color components + var r = 255 - parseInt(hex.slice(0, 2), 16); + var g = 255 - parseInt(hex.slice(2, 4), 16); + var b = 255 - parseInt(hex.slice(4, 6), 16); + var a = hex.slice(6, 8); + + return RGBToHex(r, g, b) + a; +} + /// RGBToHex function RGBToHex(r, g, b) { r = r.toString(16); @@ -140,6 +157,16 @@ function HSLToRGB(h, s, l) { return [r, g, b]; } +/// Standardize HEX +function standardizeHex(hex) { + hex = hex.replace(/^\s*#|\s*$/g, ""); + // convert 3 char codes --> 6, e.g. `E0F` --> `EE00FF` + if (hex.length == 3 || hex.lenght == 4) { + hex = hex.replace(/(.)/g, "$1$1"); + } + return hex; +} + // Update Color Variables function updateLayerWithColorVariables(context) { // When you open an existing document in Sketch 69, the color assets in the document will be migrated to Color Swatches. However, layers using those colors will not be changed to use the new swatches. This plugin takes care of this @@ -194,4 +221,23 @@ function matchingSwatchForColor(color, name) { function colorVariableFromColor(color) { let swatch = matchingSwatchForColor(color); return swatch.referencingColor; +} + +function createColorVariable(colorName, color) { + const documentColors = sketch.getSelectedDocument().colors; + // Generate the Color Variable, if not existent + if (sketchversion >= 69) { + var arrayColorVarNames = document.swatches.map((Swatch) => Swatch["name"]); + const Swatch = sketch.Swatch; + var newSwatch = Swatch.from({ name: colorName, color: color }); + + if (arrayColorVarNames.indexOf(colorName) === -1) { + document.swatches.push(newSwatch); + } + } else { + var arrayColorAssetsNames = documentColors.map((ColorAsset) => ColorAsset["name"]); + if (arrayColorAssetsNames.indexOf(colorName) === -1) { + documentColors.push({ type: "ColorAsset", name: colorName, color: color }); + } + } } \ No newline at end of file diff --git a/DS-Core.sketchplugin/Contents/Sketch/create-color-scale.js b/DS-Core.sketchplugin/Contents/Sketch/create-color-scale.js index ff2ccae..59b02a8 100644 --- a/DS-Core.sketchplugin/Contents/Sketch/create-color-scale.js +++ b/DS-Core.sketchplugin/Contents/Sketch/create-color-scale.js @@ -45,7 +45,7 @@ var onRun = function(context) { return; } else { // sketch.UI.message(value); - sketch.UI.message("🌈: Yay! " + value.replace("Steps","Color steps created! 👏 🚀")); + sketch.UI.message("🌈: Yay! " + value.replace("Steps", "Color steps created! 👏 🚀")); let result = colorVariations[labels.indexOf(value)]; @@ -122,4 +122,4 @@ var onRun = function(context) { } else { sketch.UI.message("☝️ Please select at least one layer."); } -}; +}; \ No newline at end of file diff --git a/DS-Core.sketchplugin/Contents/Sketch/create-typography-scale.js b/DS-Core.sketchplugin/Contents/Sketch/create-typography-scale.js index 65c5311..2482f40 100644 --- a/DS-Core.sketchplugin/Contents/Sketch/create-typography-scale.js +++ b/DS-Core.sketchplugin/Contents/Sketch/create-typography-scale.js @@ -8,6 +8,7 @@ var HotSpot = require("sketch/dom").HotSpot; var Flow = require("sketch/dom").Flow; var document = sketch.getSelectedDocument(); +@import "settings.js" @import "functions.js" var onRun = function(context) { @@ -29,6 +30,7 @@ var onRun = function(context) { sketch.UI.message("🌈: Please select a Text layer to use as your base font reference. 😅"); } else { var selection = document.selectedLayers.layers[0]; + var originalSelection = selection; var currentPage = selection.getParentPage(); var currentArtboard = selection.getParentArtboard(); @@ -52,37 +54,36 @@ var onRun = function(context) { var layerStyles = document.sharedLayerStyles; var textStyles = document.sharedTextStyles; - // Default margins - var margin = 24; - var moveby = 0; + // var lineHeightMultiplier = 1.5; var lineHeightMultiplier = baseLineHeight / baseFontSize; // Color management const documentColors = sketch.getSelectedDocument().colors; - var arrayColorAssetsNames = documentColors.map((ColorAsset) => ColorAsset["name"]); + // var arrayColorAssetsNames = documentColors.map((ColorAsset) => ColorAsset["name"]); - if (sketchversion >= 69) { - var arrayColorVarNames = document.swatches.map((Swatch) => Swatch["name"]); - } + // if (sketchversion >= 69) { + // var arrayColorVarNames = document.swatches.map((Swatch) => Swatch["name"]); + // } var color = selection.style.textColor; var colorname = selection.name; // Generate the Color Variable, if not existent - if (sketchversion >= 69) { - const Swatch = sketch.Swatch; - var newSwatch = Swatch.from({ name: colorname, color: color }); - - if (arrayColorVarNames.indexOf(colorname) === -1) { - document.swatches.push(newSwatch); - } else {} - - } else { - if (arrayColorAssetsNames.indexOf(colorname) === -1) { - documentColors.push({ type: "ColorAsset", name: colorname, color: color }); - } else {} - } + // createColorVariable(colorname, color); + // if (sketchversion >= 69) { + // const Swatch = sketch.Swatch; + // var newSwatch = Swatch.from({ name: colorname, color: color }); + + // if (arrayColorVarNames.indexOf(colorname) === -1) { + // document.swatches.push(newSwatch); + // } else {} + + // } else { + // if (arrayColorAssetsNames.indexOf(colorname) === -1) { + // documentColors.push({ type: "ColorAsset", name: colorname, color: color }); + // } else {} + // } //// Get user input var result; //= [] + [doc askForUserInput:instructionalTextForInput initialValue:""]; var instructionalTextForInput = "The selected text layer will be used as your base for" @@ -90,34 +91,12 @@ var onRun = function(context) { instructionalTextForInput += "\n\n"; instructionalTextForInput += "Please select a Scale from the list below:"; - let typographyScaleVariations = [ - "1.067", - "1.125", - "1.2", - "1.25", - "1.333", - "1.414", - "1.5", - "1.618", - ]; - - let labels = [ - "1.067 - Minor Second", - "1.125 - Major Second", - "1.200 - Minor Third", - "1.250 - Major Third", - "1.333 - Perfect Fourth", - "1.414 - Augmented Fourth", - "1.500 - Perfect Fifth", - "1.618 - Golden Ratio", - ]; - // Plugin interactive window ui.getInputFromUser( "Choose a Typography Scale", { description: instructionalTextForInput, type: ui.INPUT_TYPE.selection, - possibleValues: labels, + possibleValues: typographyLabels, }, (err, value) => { if (err) { @@ -126,168 +105,198 @@ var onRun = function(context) { } return; } else { - result = typographyScaleVariations[labels.indexOf(value)]; + result = typographyScaleVariations[typographyLabels.indexOf(value)]; } } ); if (result) { - var scaleFactor = result; - - // Styles management - // Array oranization: - // 0 = Folder Name - // 1 = Style Name - // 2 = Default font size (no multiplier in use) - // 3 = Scale factor multiplier - var StylesArray = [ - ["Headline 1", "H1", false, 5], - ["Headline 2", "H2", false, 4], - ["Headline 3", "H3", false, 3], - ["Headline 4", "H4", false, 2], - ["Headline 5", "H5", false, 1], - ["Paragraph", "Paragraph", true, 1], - ["Small", "Small", false, 0.75], - ["Label", "Label", true, 1] - ]; - var StylesArraySizes = []; - - for (s = 0; s < StylesArray.length; s++) { - - } - - var StylesArrayAlignments = ["left", "center", "right"]; - - var counter = 0 - - // Generate Typography and Styles from selected text layers and docuemnt colors + let counter = 0; + let themeName = "" + // Generate Typography and Styles from selected text layers and docuemnt colors let typographyStyleGroups = []; let textsGroupWidth = 0; let textGroupHeight = 0; let newArtboardWidth = 0; let newArtboardHeight = 0; - // margin = Math.round(margin * 2 * scaleFactor); - margin = margin * 2; - - for (a = 0; a < StylesArrayAlignments.length; ++a) { - let newAlign = StylesArrayAlignments[a]; - let alignmentGroup = createGroup(currentArtboard, [], "Text styles - align " + newAlign); - typographyStyleGroups.push(alignmentGroup); - textsGroupWidth = 0; - textGroupHeight = 0; - for (s = 0; s < StylesArray.length; ++s) { - let scaleMuliplier = StylesArray[s][3] - - let StyleArraySizeValue = 0 - // Default size - if (StylesArray[s][2] === true) { - StyleArraySizeValue = baseFontSize; - } else { - if (scaleMuliplier >= 1) { - StyleArraySizeValue = Math.round(baseFontSize * Math.pow(scaleFactor, StylesArray[s][3])); - } else { - StyleArraySizeValue = Math.round(baseFontSize / Math.pow(scaleFactor, StylesArray[s][3])); - } + let groupPosX = 0; + + // Manage settings and more themes + if (typographyThemes) { + // When more themes are in use, we should create as many Artboards as the number of themes + currentArtboard.remove() + for (tt = 0; tt < typographyThemesArray.length; tt++) { + themeName = typographyThemesArray[tt][0]; + if (typographyThemesArray[tt][1] === "Inverted") { + baseTextColor = invertColor(baseTextColor); + colorname += "-inverted"; + } else if (typographyThemesArray[tt][1] !== "Default") { + // NOTE: this part need work, as we can check for primary/seondary colors etc in Color Variables + baseTextColor = "#000000"; } - // console.log("Style: " + StylesArray[s][0] + " - Multiplier: " + scaleMuliplier + " - Value: " + StyleArraySizeValue) - let newFolder = StylesArray[s][0]; - let newName = StylesArray[s][1]; - let styleName = newFolder + " - " + newAlign; - let layerName = newFolder + "/" + newName + " - " + newAlign; - let newFontFamily = selection.style.fontFamily; - let newFontSize = StyleArraySizeValue; - let newTextAlign = newAlign; + // Generate the Themed Artboard + currentArtboard = createArtboard( + currentPage, + selectionX, + selectionY, + selection.frame.width, + selection.frame.height, + "Typography - " + themeName + ); + currentArtboard.background.color = invertColor(baseTextColor); + currentArtboard.background.enabled = true; + currentArtboard.background.includedInExport = false; + + // Generate the Typography scale + createScale(themeName); + + // Set parameters for the next iteration + let currentArtboardWidth = currentArtboard.frame.width; + selectionX += currentArtboardWidth + margin * 2; + selection = originalSelection; + typographyStyleGroups = []; + groupPosX = 0 + textGroupHeight = 0; + newArtboardWidth = 0; + newArtboardHeight = 0; - let newLineHeight = Math.round(newFontSize * lineHeightMultiplier); + } + } else { + createScale(); + } - let colorName = selection.style.textColor; + function createScale(themeName = "") { + var scaleFactor = result; - if (documentColors.length > 0) { - colorName = documentColors[c].name || documentColors[c].color; - } + var StylesArraySizes = []; - let newFrameY = 0; + let internalMargin = margin * 2; - if (s > 0) { - newFrameY += textGroupHeight + margin * s; // * Math.round(scaleFactor / 100) * 100; - } - textGroupHeight += newLineHeight; - - // Create the Text Layer - let newText = createTextNoStyle( - alignmentGroup, - layerName, - styleName, - 0, - newFrameY, - colorName, - newTextAlign, - newFontFamily, - newFontSize, - newLineHeight - ); + for (a = 0; a < typographyStylesArrayAlignments.length; a++) { + let newAlign = typographyStylesArrayAlignments[a]; + let alignmentGroup = createGroup(currentArtboard, [], "Text styles - align " + newAlign); + typographyStyleGroups.push(alignmentGroup); + textsGroupWidth = 0; + textGroupHeight = 0; + for (s = 0; s < typographyStylesArray.length; ++s) { + let scaleMuliplier = typographyStylesArray[s][3] - counter++; + let StyleArraySizeValue = 0 + // Default size + if (typographyStylesArray[s][2] === true) { + StyleArraySizeValue = baseFontSize; + } else { + if (scaleMuliplier >= 1) { + StyleArraySizeValue = Math.round(baseFontSize * Math.pow(scaleFactor, typographyStylesArray[s][3])); + } else { + StyleArraySizeValue = Math.round(baseFontSize / Math.pow(scaleFactor, typographyStylesArray[s][3])); + } + } - // Se the Color Variable - if (sketchversion >= 69) { - var currentSwatch = matchingSwatchForColor(colorName); + let newFolder = typographyStylesArray[s][0]; + if (themeName !== "") { + newFolder += "/" + themeName; + } + let newName = typographyStylesArray[s][1]; + let styleName = newFolder + " - " + newAlign; + let layerName = newFolder + "/" + newName + " - " + newAlign; - var myColor = currentSwatch.referencingColor; + let newFontFamily = selection.style.fontFamily; + let newFontSize = StyleArraySizeValue; + let newTextAlign = newAlign; - newText.style.textColor = myColor; - // /// Update all the layers using the Swatches/Color Vars - swatchContainer = document.sketchObject.documentData().sharedSwatches(); - swatchContainer.updateReferencesToSwatch(currentSwatch.sketchObject); - } + let newLineHeight = Math.round(newFontSize * lineHeightMultiplier); - // Create (if needed) and Apply text styles - createNewTextStyle(newText, layerName, true, false); - } + let colorName = baseTextColor; + if (documentColors.length > 0) { + colorName = documentColors[c].name || documentColors[c].color; + } - newArtboardWidth += margin + alignmentGroup.frame.width; - newArtboardHeight = margin + alignmentGroup.frame.height; - } + let newFrameY = 0; - // Handle the Group and Layer re-position inside the Artboard - let groupPosX = 0; - for (i = 0; i < typographyStyleGroups.length; i++) { - typographyStyleGroups[i].frame.x = groupPosX + margin * (i + 1); - typographyStyleGroups[i].frame.y = Math.round(typographyStyleGroups[i].frame.y) + margin; - groupPosX += Math.round(typographyStyleGroups[i].frame.width); - - // align center - if (i === 1) { - typographyStyleGroups[i].layers.forEach((layer) => { - layer.frame.x = Math.round((typographyStyleGroups[i].frame.width - layer.frame.width) / 2); - }); - } - // align right - if (i === 2) { - typographyStyleGroups[i].layers.forEach((layer) => { - layer.frame.x = Math.round(typographyStyleGroups[i].frame.width - layer.frame.width); - }); - } + if (s > 0) { + newFrameY += textGroupHeight + internalMargin * s; // * Math.round(scaleFactor / 100) * 100; + } + textGroupHeight += newLineHeight; + + // Create the Text Layer + let newText = createTextNoStyle( + alignmentGroup, + layerName, + styleName, + 0, + newFrameY, + colorName, + newTextAlign, + newFontFamily, + newFontSize, + newLineHeight + ); + + counter++; + + // Create a new color variable if it doesn't exist + createColorVariable(colorname, baseTextColor); + + // Set the Color Variable + if (sketchversion >= 69) { + var currentSwatch = matchingSwatchForColor(colorName); + + var myColor = currentSwatch.referencingColor; + + newText.style.textColor = myColor; + // /// Update all the layers using the Swatches/Color Vars + swatchContainer = document.sketchObject.documentData().sharedSwatches(); + swatchContainer.updateReferencesToSwatch(currentSwatch.sketchObject); + } + + // Create (if needed) and Apply text styles + createNewTextStyle(newText, layerName, true, false); + } - // Adjust group sizes to their contents and position the last group correctly - typographyStyleGroups[i].adjustToFit(); - typographyStyleGroups[2].frame.x = (typographyStyleGroups[1].frame.x + typographyStyleGroups[1].frame.width) + (typographyStyleGroups[1].frame.x - (typographyStyleGroups[0].frame.x + typographyStyleGroups[0].frame.width)) - } - // Size Typography Artboard - newArtboardWidth = typographyStyleGroups[2].frame.x + typographyStyleGroups[2].frame.width + margin; - newArtboardHeight += margin; + newArtboardWidth += internalMargin + alignmentGroup.frame.width; + newArtboardHeight = internalMargin + alignmentGroup.frame.height; + } - currentArtboard.frame.width = newArtboardWidth; - currentArtboard.frame.height = newArtboardHeight; + // Handle the Group and Layer re-position inside the Artboard + groupPosX = 0; + for (i = 0; i < typographyStyleGroups.length; i++) { + typographyStyleGroups[i].frame.x = groupPosX + internalMargin * (i + 1); + typographyStyleGroups[i].frame.y = Math.round(typographyStyleGroups[i].frame.y) + internalMargin; + groupPosX += Math.round(typographyStyleGroups[i].frame.width); + + // align center + if (i === 1) { + typographyStyleGroups[i].layers.forEach((layer) => { + layer.frame.x = Math.round((typographyStyleGroups[i].frame.width - layer.frame.width) / 2); + }); + } + // align right + if (i === 2) { + typographyStyleGroups[i].layers.forEach((layer) => { + layer.frame.x = Math.round(typographyStyleGroups[i].frame.width - layer.frame.width); + }); + } + // Adjust group sizes to their contents and position the last group correctly + typographyStyleGroups[i].adjustToFit(); + typographyStyleGroups[2].frame.x = (typographyStyleGroups[1].frame.x + typographyStyleGroups[1].frame.width) + (typographyStyleGroups[1].frame.x - (typographyStyleGroups[0].frame.x + typographyStyleGroups[0].frame.width)) + } + // Size Typography Artboard + newArtboardWidth = typographyStyleGroups[2].frame.x + typographyStyleGroups[2].frame.width + internalMargin; + newArtboardHeight += internalMargin; - selection.remove(); + currentArtboard.frame.width = newArtboardWidth; + currentArtboard.frame.height = newArtboardHeight; - ui.message("🌈: Yay! Done generating typography scale with " + counter + " text styles! 👏 🚀"); + selection.remove(); + + ui.message("🌈: Yay! Done generating typography scale with " + counter + " text styles! 👏 🚀"); + } } else { ui.message("🌈: Please select a Text layer to use as your base font reference. 😅"); } @@ -422,23 +431,4 @@ var onRun = function(context) { return styleID; } } - - -}; - -function sortFunction(a, b) { - if (a[0] === b[0]) { - return 0; - } else { - return a[0] < b[0] ? -1 : 1; - } -} - -function roundAndEvenNumber(value) { - return 2 * Math.round(value / 2); -} - -function roundToClosestGridModuleNumber(value) { - /// Assumes common 8 pixel grid - return Math.round(value / 8) * 8; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/DS-Core.sketchplugin/Contents/Sketch/manifest.json b/DS-Core.sketchplugin/Contents/Sketch/manifest.json index 0ae2e5f..7261b49 100644 --- a/DS-Core.sketchplugin/Contents/Sketch/manifest.json +++ b/DS-Core.sketchplugin/Contents/Sketch/manifest.json @@ -1,7 +1,7 @@ { "name": "DS Core", "description": "Batch create Typography, Color Scales and Components really fast.", - "version": "1.5.3", + "version": "1.5.4", "author": "Francesco Bertocci & Matteo Gratton", "authorEmail": "fbmore@gmail.com", "appcast": "https://raw.githubusercontent.com/fbmore/DS-Core-Sketch-Plugin/main/appcast.xml", diff --git a/DS-Core.sketchplugin/Contents/Sketch/settings.js b/DS-Core.sketchplugin/Contents/Sketch/settings.js new file mode 100644 index 0000000..67d12cc --- /dev/null +++ b/DS-Core.sketchplugin/Contents/Sketch/settings.js @@ -0,0 +1,49 @@ +// ********************************************************** +// General settings for all the scripts +// import via @import(@import "settings.js") at the very +// beginning of your script +// ********************************************************** + +// Margins +var margin = 24; +var moveby = 0; + +// Typography +// Scale Variations +// 1. Available scales multipliers +var typographyScaleVariations = ["1.067", "1.125", "1.2", "1.25", "1.333", "1.414", "1.5", "1.618"]; +// 2. UI Labels for selection +var typographyLabels = [ + "1.067 - Minor Second", + "1.125 - Major Second", + "1.200 - Minor Third", + "1.250 - Major Third", + "1.333 - Perfect Fourth", + "1.414 - Augmented Fourth", + "1.500 - Perfect Fifth", + "1.618 - Golden Ratio", +]; +// 3. Style names and multiplier factors +// Array oranization: +// 0 = Folder Name +// 1 = Style Name +// 2 = Default font size (no multiplier in use) +// 3 = Scale factor multiplier +var typographyStylesArray = [ + ["Headline 1", "H1", false, 5], + ["Headline 2", "H2", false, 4], + ["Headline 3", "H3", false, 3], + ["Headline 4", "H4", false, 2], + ["Headline 5", "H5", false, 1], + ["Paragraph", "Paragraph", true, 1], + ["Small", "Small", false, 0.75], + ["Label", "Label", true, 1], +]; +// 4. Styles alignments +var typographyStylesArrayAlignments = ["left", "center", "right"]; +// 5. Themes +var typographyThemes = true; +var typographyThemesArray = [ + ["Dark", "Default"], + ["Light", "Inverted"], +]; \ No newline at end of file diff --git a/DS-Core.sketchplugin/Contents/appcast.xml b/DS-Core.sketchplugin/Contents/appcast.xml index 3c2ec05..b862578 100644 --- a/DS-Core.sketchplugin/Contents/appcast.xml +++ b/DS-Core.sketchplugin/Contents/appcast.xml @@ -5,7 +5,7 @@ Batch create Typography, Color Scales and Components really fast. en - Version 1.5.3 + Version 1.5.4 @@ -13,7 +13,7 @@ ]]> - +