├── .appcast.xml
├── .gitignore
├── README.md
├── assets
└── icon.png
├── package-lock.json
├── package.json
├── sketch-assets
└── icons.sketch
├── src
├── manifest.json
└── switch_theme.js
└── switch-light-dark.sketchplugin
└── Contents
├── Resources
└── icon.png
└── Sketch
├── manifest.json
└── switch_theme.js
/.appcast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 | -
8 |
9 |
10 | -
11 |
12 |
13 | -
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # build artifacts
2 | plugin.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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Automatically switch designs between Dark-Light modes
2 |
3 | This plugin switches one or multiple artboards between light/dark modes instantly. It can work with symbols, nested symbols, overrides, shapes, layer styles, text styles and colour variables.
4 |
5 |
6 |
7 | ## Usage
8 | Have one or more libraries linked in Sketch for this to work.
9 |
10 | It can switch:
11 | - symbols
12 | - nested symbols
13 | - all override types
14 | - texts
15 | - layer styles
16 | - text styles
17 | - NEW: colour variables
18 |
19 | All of these must have 'dark' or 'light' somewhere in their name, doesn't matter where.
20 | Just double click on the .sketchplugin file in the archive downloaded and you're good to go!
21 |
22 | ## Debugging
23 |
24 | To view the output of your `console.log`, you have a few different options:
25 |
26 | - Use the [`sketch-dev-tools`](https://github.com/skpm/sketch-dev-tools)
27 | - Open `Console.app` and look for the sketch logs
28 | - Look at the `~/Library/Logs/com.bohemiancoding.sketch3/Plugin Output.log` file
29 |
30 | Skpm provides a convenient way to do the latter:
31 |
32 | ```bash
33 | skpm log
34 | ```
35 |
36 | The `-f` option causes `skpm log` to not stop when the end of logs is reached, but rather to wait for additional data to be appended to the input
37 |
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chaos-machine/switch-theme/180588fede36f0940e2cb67f3d5a0772f9c24296/assets/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "switch_theme",
3 | "description": "Switch colour variables, symbols, overrides, layer styles and text styles",
4 | "author": "Tudor Teisanu ",
5 | "version": "2.3.0",
6 | "engines": {
7 | "sketch": ">=3.0"
8 | },
9 | "skpm": {
10 | "name": "Light/Dark Switch",
11 | "manifest": "src/manifest.json",
12 | "main": "switch-light-dark.sketchplugin",
13 | "assets": [
14 | "assets/**/*"
15 | ],
16 | "sketch-assets-file": "sketch-assets/icons.sketch"
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.4.0",
26 | "@skpm/nib-loader": "^0.1.2",
27 | "appkit": "^1.0.1"
28 | },
29 | "dependencies": {
30 | "common-js": "^0.3.8",
31 | "sketch-toolbar-item": "^0.1.4"
32 | },
33 | "repository": {
34 | "type": "git",
35 | "url": "https://github.com/chaos-machine/switch-theme.git"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/sketch-assets/icons.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chaos-machine/switch-theme/180588fede36f0940e2cb67f3d5a0772f9c24296/sketch-assets/icons.sketch
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/sketch-hq/SketchAPI/develop/docs/sketch-plugin-manifest-schema.json",
3 | "icon": "icon.png",
4 | "homepage": "https://github.com/chaos-machine/switch-theme",
5 | "version": "2.3.0",
6 | "identifier": "com.sketchapp.examples.switchtheme",
7 | "bundleVersion": 1,
8 | "commands": [
9 | {
10 | "shortcut": "ctrl shift t",
11 | "script": "switch_theme.js",
12 | "name": "Switch Theme",
13 | "identifier": "switchtheme"
14 |
15 |
16 | }
17 | ],
18 | "menu": {
19 | "isRoot": true,
20 | "items": [
21 | "switchtheme"
22 | ]
23 | }
24 | }
25 |
26 |
--------------------------------------------------------------------------------
/src/switch_theme.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | let sketch = require('sketch')
4 | let Artboard = sketch.Artboard
5 | var Text = require('sketch').Text
6 | var ShapePath = require('sketch/dom').ShapePath
7 | var Group = require('sketch/dom').Group
8 |
9 |
10 | let document = sketch.getSelectedDocument()
11 | let page = document.selectedPage
12 | let docSwatches = document.swatches
13 | let imported_swatches = []
14 |
15 | var selection = context.selection;
16 | var fromTheme, toTheme;
17 | var currentArtboard
18 | var newArtboardName
19 | var instance
20 | var group_name
21 |
22 | var move = 0;
23 | var master_iterator = -1;
24 |
25 | var CreateArtboard = true;
26 | let TextLibrary
27 | let ColourLibrary
28 |
29 | var isGlobalColour = false;
30 | var isGlobalText = false;
31 |
32 | var myArtboard
33 |
34 | var layerstyleReferences
35 | var textstyleReferences
36 | let swatchRefs
37 |
38 |
39 | function removeArtboardNames() {
40 |
41 | //removes current artboard naming
42 |
43 | if (newArtboardName.includes("Dark")) { newArtboardName = newArtboardName.replace('Dark', '') }
44 | else if (newArtboardName.includes("Light")) { newArtboardName = newArtboardName.replace('Light', ''); }
45 |
46 | if (newArtboardName.includes("dark")) { newArtboardName = newArtboardName.replace('dark', '') }
47 | else if (newArtboardName.includes("light")) { newArtboardName = newArtboardName.replace('light', ''); }
48 |
49 | if (newArtboardName.includes("dakr")) { newArtboardName = newArtboardName.replace('dakr', '') }
50 | else if (newArtboardName.includes("lihgt")) { newArtboardName = newArtboardName.replace('lihgt', ''); }
51 | }
52 |
53 | function createArtboatd() {
54 | if (CreateArtboard) {
55 | myArtboard = new Artboard({
56 | parent: page,
57 | name: newArtboardName + ' ' + toTheme,
58 | frame: {
59 | x: currentArtboard.frame.x + currentArtboard.frame.width + move,
60 | y: currentArtboard.frame.y,
61 | width: currentArtboard.frame.width,
62 | height: currentArtboard.frame.height
63 | }
64 | });
65 |
66 | myArtboard.background.enabled = true;
67 |
68 | if (toTheme == "Dark") {
69 | myArtboard.background.color = '#000000ff';
70 | }
71 | CreateArtboard = false
72 | }
73 |
74 | }
75 |
76 |
77 | var libraries = require('sketch/dom').getLibraries()
78 | for (var l = 0; l < Object.keys(libraries).length; l++) {
79 | if (libraries[l].name.includes('Type') || libraries[l].name.includes('Text') || libraries[l].name.includes('Fonts') || libraries[l].name.includes('Fundamentals')) {
80 | isGlobalText = true;
81 | TextLibrary = sketch.getLibraries()[l]
82 | textstyleReferences = TextLibrary.getImportableTextStyleReferencesForDocument(document)
83 |
84 | }
85 |
86 | if (libraries[l].name.includes('Color') || libraries[l].name.includes('Fundamentals') || libraries[l].name.includes('Colours')) {
87 | isGlobalColour = true;
88 | ColourLibrary = sketch.getLibraries()[l]
89 | layerstyleReferences = ColourLibrary.getImportableLayerStyleReferencesForDocument(document)
90 | swatchRefs = ColourLibrary.getImportableSwatchReferencesForDocument(document)
91 |
92 | }
93 | }
94 |
95 |
96 |
97 | //for each layer selected in the document, checking if there are artboards with sublayers
98 |
99 |
100 |
101 | var UI = require('sketch/ui')
102 |
103 |
104 | UI.getInputFromUser(
105 | "Switch to",
106 | {
107 | type: UI.INPUT_TYPE.selection,
108 | possibleValues: ['Light', 'Dark'],
109 | },
110 | (err, value) => {
111 | if (err) {
112 | UI.close();
113 | return
114 | }
115 |
116 | if (value == 'Light') {
117 | fromTheme = 'Dark'
118 | toTheme = 'Light'
119 |
120 | }
121 | if (value == 'Dark') {
122 | fromTheme = 'Light'
123 | toTheme = 'Dark'
124 |
125 | }
126 | }
127 | )
128 |
129 |
130 |
131 | selection.forEach(function (layer) {
132 | if (layer.layers && layer.class() == "MSArtboardGroup") {
133 | master_iterator++; move += 150;
134 | var children = layer.children();
135 | currentArtboard = sketch.getSelectedDocument().selectedLayers.layers[master_iterator]
136 |
137 | //artboard name handling
138 |
139 | newArtboardName = sketch.getSelectedDocument().selectedLayers.layers[master_iterator].name;
140 | removeArtboardNames();
141 |
142 | CreateArtboard = true;
143 | createArtboatd();
144 |
145 |
146 | //////////GETTING ALL LAYERS IN AN ARTBOARD BY NAME, THEN ID
147 |
148 | for (var f = 0; f < children.count(); f++) {
149 | if (children[f].class() != "MSArtboardGroup") {
150 | var extracted_children_id = children[f].toString().split('(').pop().split(')')[0];
151 | var current_layer_in_artboard = document.getLayerWithID(extracted_children_id)
152 |
153 | //////////SYMBOL LAYER
154 |
155 | if (current_layer_in_artboard.type == "SymbolInstance") {
156 |
157 | //I use the extracted ID and found layer to match the correct library & master references
158 |
159 | var library_linked = current_layer_in_artboard.master.getLibrary()
160 | var symbolReferences = library_linked.getImportableSymbolReferencesForDocument(document)
161 | let swatchRefs = library_linked.getImportableSwatchReferencesForDocument(document)
162 |
163 | if (!isGlobalColour){
164 | layerstyleReferences = library_linked.getImportableLayerStyleReferencesForDocument(document)
165 | }
166 | if (!isGlobalText) {
167 | textstyleReferences = library_linked.getImportableTextStyleReferencesForDocument(document)
168 | }
169 |
170 |
171 |
172 | symbolReferences.forEach((ImportableObject) => {
173 | if (ImportableObject.id == current_layer_in_artboard.symbolId) {
174 | var imported_symbol_name = ImportableObject.name.replace(fromTheme, toTheme)
175 | var to_Import = symbolReferences.filter(element => element.name == imported_symbol_name)
176 | var symbolMaster = to_Import[0].import();
177 | instance = symbolMaster.createNewInstance();
178 |
179 | //sizes checked to match symbol to existing instance
180 |
181 | var new_frame = current_layer_in_artboard.frame
182 | var new_x = new_frame.x
183 | var new_y = new_frame.y
184 | var new_width = new_frame.width
185 | var new_height = new_frame.height
186 | var new_rotation = current_layer_in_artboard.transform.rotation
187 | var new_transform = current_layer_in_artboard.transform
188 | var new_instance_name = current_layer_in_artboard.name
189 |
190 | instance.name = new_instance_name
191 | instance.transform = new_transform
192 | instance.transform.rotation = new_rotation;
193 | instance.frame = { x: new_x, y: new_y, width: new_width, height: new_height };
194 | instance.parent = myArtboard;
195 |
196 |
197 | //going through overrides for symbols and texts separately
198 |
199 | for (var w = 0; w < (Object.keys(instance.overrides).length); w++) {
200 |
201 | //only get the override if the value is differnet from the default one, otherwise let the symbol handle it
202 |
203 | //looking at overriding text
204 | if (current_layer_in_artboard.overrides[w].property == 'stringValue' && !(current_layer_in_artboard.overrides[w].isDefault)) {
205 | instance.overrides[w].value = current_layer_in_artboard.overrides[w].value
206 | }
207 |
208 | if (current_layer_in_artboard.overrides[w].property == 'layerStyle' && !(current_layer_in_artboard.overrides[w].isDefault)) {
209 | layerstyleReferences.forEach((element) => {
210 | if (element.id == current_layer_in_artboard.overrides[w].value) {
211 | var layer_style_switch_name = element.name.replace(fromTheme, toTheme)
212 | layerstyleReferences.forEach((sub_element) => {
213 |
214 | if (sub_element.name == layer_style_switch_name) {
215 |
216 | var sharedStyle = sub_element.import()
217 | instance.overrides[w].value = sharedStyle.id
218 | }
219 |
220 | })
221 | }
222 | })
223 | }
224 |
225 | if (current_layer_in_artboard.overrides[w].property == 'textStyle' && !(current_layer_in_artboard.overrides[w].isDefault)) {
226 |
227 | textstyleReferences.forEach((element) => {
228 |
229 | if (element.id == current_layer_in_artboard.overrides[w].value) {
230 | var text_stlye_override_switch_name = element.name.replace(fromTheme, toTheme)
231 | //look for the switched text style by its name
232 |
233 | textstyleReferences.forEach((sub_element) => {
234 | if (sub_element.name == text_stlye_override_switch_name) {
235 | var textStyle_to_import = sub_element.import()
236 | instance.overrides[w].value = textStyle_to_import.id
237 | }
238 | });
239 |
240 | }
241 | })
242 | }
243 |
244 | if (current_layer_in_artboard.overrides[w].property == 'symbolID' && !(current_layer_in_artboard.overrides[w].isDefault)) {
245 | var override_symbol_master = document.getSymbolMasterWithID(current_layer_in_artboard.overrides[w].value)
246 | var override_library_linked = override_symbol_master.getLibrary()
247 |
248 | var override_symbolReferences = override_library_linked.getImportableSymbolReferencesForDocument(document)
249 |
250 | override_symbolReferences.forEach((element) => {
251 |
252 | if (element.id == current_layer_in_artboard.overrides[w].value) {
253 |
254 |
255 | var symbol_override_switch_name = element.name.replace(fromTheme, toTheme)
256 | //look for the switched symbol by its name
257 |
258 | override_symbolReferences.forEach((sub_element) => {
259 | if (sub_element.name == symbol_override_switch_name) {
260 |
261 | //importing the same symbol into the artboard , deleting it afterward to have it as a reference
262 |
263 | var master_to_delte = sub_element.import();
264 | var instance_to_delete = master_to_delte.createNewInstance();
265 |
266 | instance_to_delete.parent = myArtboard
267 | instance.overrides[w].value = instance_to_delete.symbolId
268 | instance_to_delete.remove()
269 |
270 | }
271 |
272 | });
273 | }
274 | })
275 | }
276 |
277 | }
278 | }
279 |
280 | })
281 | }
282 |
283 | //////////TEXT LAYER
284 |
285 | if (current_layer_in_artboard.type == 'Text') {
286 | var text = new Text({
287 | text: current_layer_in_artboard.text,
288 | frame: current_layer_in_artboard.frame,
289 | style: current_layer_in_artboard.style,
290 | name: current_layer_in_artboard.name,
291 | sharedStyleId: current_layer_in_artboard.sharedStyleId,
292 | sharedStyle: current_layer_in_artboard.sharedStyle
293 | })
294 | text.behaviour = current_layer_in_artboard.behaviour;
295 | text.parent = myArtboard
296 |
297 | if (text.sharedStyle != null) {
298 | if (text.sharedStyle.name.includes(fromTheme)) {
299 | var switch_text_style = text.sharedStyle.name.replace(fromTheme, toTheme)
300 |
301 | textstyleReferences.forEach((element) => {
302 | if (element.name == switch_text_style) {
303 | var new_text_style = element.import();
304 | text.sharedStyle = new_text_style;
305 | text.style.syncWithSharedStyle(new_text_style)
306 | }
307 | })
308 |
309 | }
310 |
311 | }
312 | else {
313 | //there are no text styles, just local swatches used
314 |
315 | if (!isGlobalColour) {
316 | log("Looking into local swatches for text colours")
317 | log("Current text color" + text.style.textColor)
318 | docSwatches.forEach((element) => {
319 | if (element.color == text.style.textColor) {
320 | var swatch_switch = element.name
321 | swatch_switch = swatch_switch.replace(fromTheme, toTheme)
322 | docSwatches.forEach((sub_swatch) => {
323 | if (sub_swatch.name == swatch_switch) {
324 | text.style.textColor = sub_swatch.referencingColor
325 | }
326 | })
327 |
328 | }
329 | })
330 | }
331 |
332 | //No text styles, global swatches are used
333 | else {
334 | var global_swatch_switch_text
335 | log("Looking into global swatches")
336 |
337 | //importing all swatches into an array to get colours and names
338 |
339 | swatchRefs.forEach((element) => {
340 | imported_swatches.push(element.import())
341 | })
342 | /*finding which swatch is used currently based on color code */
343 | imported_swatches.forEach((sub_element) => {
344 | if (sub_element.color == text.style.textColor) {
345 | log("Current swatch is" + sub_element.name)
346 |
347 | global_swatch_switch_text = sub_element.name
348 | global_swatch_switch_text = global_swatch_switch_text.replace(fromTheme, toTheme)
349 | }
350 | })
351 | /*finding out the alternative darl/light swatch, then replacing it for the shape */
352 | imported_swatches.forEach((sub_sub_element) => {
353 | if (sub_sub_element.name == global_swatch_switch_text) {
354 | text.style.textColor = sub_sub_element.referencingColor
355 | }
356 | })
357 |
358 | }
359 |
360 |
361 | }
362 | }
363 |
364 |
365 | //////////SHAPE LAYER
366 |
367 | if (current_layer_in_artboard.type == 'ShapePath') {
368 | const shapePath = new ShapePath({
369 | shapeType: current_layer_in_artboard.shapeType,
370 | sharedStyle: current_layer_in_artboard.sharedStyle,
371 | frame: current_layer_in_artboard.frame,
372 | points: current_layer_in_artboard.points,
373 | transform: current_layer_in_artboard.transform,
374 | name: current_layer_in_artboard.name,
375 | style: current_layer_in_artboard.style,
376 | parent: myArtboard
377 |
378 | })
379 | shapePath.transform.rotation = current_layer_in_artboard.transform.rotation
380 |
381 | if (shapePath.sharedStyle != null) {
382 | //layerstyleReferences only looks at layerstyles imported from the previous symbol in the document.
383 | layerstyleReferences.forEach((element) => {
384 | if (element.id == shapePath.sharedStyleId) {
385 |
386 | var switch_layer_style = element.name
387 | switch_layer_style = switch_layer_style.replace(fromTheme, toTheme)
388 |
389 | layerstyleReferences.forEach((sub_element) => {
390 | if (sub_element.name == switch_layer_style) {
391 | var new_new_layer_style = sub_element.import();
392 | shapePath.sharedStyleId = new_new_layer_style.id;
393 | shapePath.style.syncWithSharedStyle(new_new_layer_style)
394 | }
395 | })
396 | }
397 | })
398 | }
399 |
400 | else {
401 | //shapes using colour variables/swatches. Check if swatches are in a Colour global library or not
402 |
403 | if (!isGlobalColour) {
404 | log("Looking into local swatches")
405 | docSwatches.forEach((element) => {
406 | if (element.color == shapePath.style.fills[0].color) {
407 | var swatch_switch = element.name
408 | swatch_switch = swatch_switch.replace(fromTheme, toTheme)
409 | docSwatches.forEach((sub_swatch) => {
410 | if (sub_swatch.name == swatch_switch) {
411 | shapePath.style.fills[0].color = sub_swatch.referencingColor
412 | }
413 | })
414 |
415 | }
416 | })
417 | }
418 | else {
419 | var global_swatch_switch
420 | log("Looking into global swatches")
421 |
422 | //importing all swatches into an array to get colours and names
423 |
424 | swatchRefs.forEach((element) => {
425 | imported_swatches.push(element.import())
426 | })
427 | /*finding which swatch is used currently based on color code */
428 | imported_swatches.forEach((sub_element) => {
429 | if (sub_element.color == shapePath.style.fills[0].color) {
430 | log("Current swatch is" + sub_element.name)
431 |
432 | global_swatch_switch = sub_element.name
433 | global_swatch_switch = global_swatch_switch.replace(fromTheme, toTheme)
434 | }
435 | })
436 | /*finding out the alternative darl/light swatch, then replacing it for the shape */
437 | imported_swatches.forEach((sub_sub_element) => {
438 | if (sub_sub_element.name == global_swatch_switch) {
439 | shapePath.style.fills[0].color = sub_sub_element.referencingColor
440 | }
441 | })
442 |
443 |
444 |
445 |
446 |
447 | }
448 |
449 |
450 |
451 |
452 |
453 |
454 |
455 | }
456 | }
457 | }
458 |
459 |
460 |
461 |
462 | }
463 | }
464 |
465 | else
466 | {
467 | UI.message('Please select one or more artboards')
468 | }
469 | });
470 |
471 |
472 |
473 |
474 |
--------------------------------------------------------------------------------
/switch-light-dark.sketchplugin/Contents/Resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chaos-machine/switch-theme/180588fede36f0940e2cb67f3d5a0772f9c24296/switch-light-dark.sketchplugin/Contents/Resources/icon.png
--------------------------------------------------------------------------------
/switch-light-dark.sketchplugin/Contents/Sketch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/sketch-hq/SketchAPI/develop/docs/sketch-plugin-manifest-schema.json",
3 | "icon": "icon.png",
4 | "homepage": "https://github.com/chaos-machine/switch-theme",
5 | "version": "2.1.0",
6 | "identifier": "com.sketchapp.examples.switchtheme",
7 | "bundleVersion": 1,
8 | "commands": [
9 | {
10 | "shortcut": "ctrl shift t",
11 | "script": "switch_theme.js",
12 | "name": "Switch Theme",
13 | "identifier": "switchtheme"
14 | }
15 | ],
16 | "menu": {
17 | "isRoot": true,
18 | "items": [
19 | "switchtheme"
20 | ]
21 | },
22 | "description": "Switch colour variables, symbols, overrides, layer styles and text styles",
23 | "name": "Light/Dark Switch",
24 | "disableCocoaScriptPreprocessor": true,
25 | "appcast": "https://raw.githubusercontent.com/chaos-machine/switch-theme/master/.appcast.xml",
26 | "author": "Tudor Teisanu",
27 | "authorEmail": "tudor703344@gmail.com"
28 | }
--------------------------------------------------------------------------------
/switch-light-dark.sketchplugin/Contents/Sketch/switch_theme.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, {
45 | /******/ configurable: false,
46 | /******/ enumerable: true,
47 | /******/ get: getter
48 | /******/ });
49 | /******/ }
50 | /******/ };
51 | /******/
52 | /******/ // getDefaultExport function for compatibility with non-harmony modules
53 | /******/ __webpack_require__.n = function(module) {
54 | /******/ var getter = module && module.__esModule ?
55 | /******/ function getDefault() { return module['default']; } :
56 | /******/ function getModuleExports() { return module; };
57 | /******/ __webpack_require__.d(getter, 'a', getter);
58 | /******/ return getter;
59 | /******/ };
60 | /******/
61 | /******/ // Object.prototype.hasOwnProperty.call
62 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
63 | /******/
64 | /******/ // __webpack_public_path__
65 | /******/ __webpack_require__.p = "";
66 | /******/
67 | /******/ // Load entry module and return exports
68 | /******/ return __webpack_require__(__webpack_require__.s = 2);
69 | /******/ })
70 | /************************************************************************/
71 | /******/ ([
72 | /* 0 */
73 | /***/ (function(module, exports) {
74 |
75 | module.exports = require("sketch/dom");
76 |
77 | /***/ }),
78 | /* 1 */
79 | /***/ (function(module, exports) {
80 |
81 | module.exports = require("sketch");
82 |
83 | /***/ }),
84 | /* 2 */
85 | /***/ (function(module, exports, __webpack_require__) {
86 |
87 | "use strict";
88 |
89 |
90 | var sketch = __webpack_require__(1);
91 | var Artboard = sketch.Artboard;
92 | var Text = __webpack_require__(1).Text;
93 | var ShapePath = __webpack_require__(0).ShapePath;
94 | var Group = __webpack_require__(0).Group;
95 |
96 | var document = sketch.getSelectedDocument();
97 | var page = document.selectedPage;
98 | var docSwatches = document.swatches;
99 | var imported_swatches = [];
100 |
101 | var selection = context.selection;
102 | var fromTheme, toTheme;
103 | var currentArtboard;
104 | var newArtboardName;
105 | var instance;
106 | var group_name;
107 |
108 | var move = 0;
109 | var master_iterator = -1;
110 |
111 | var CreateArtboard = true;
112 | var TextLibrary = void 0;
113 | var ColourLibrary = void 0;
114 |
115 | var isGlobalColour = false;
116 | var isGlobalText = false;
117 |
118 | var myArtboard;
119 |
120 | var layerstyleReferences;
121 | var textstyleReferences;
122 | var swatchRefs = void 0;
123 |
124 | function removeArtboardNames() {
125 |
126 | //removes current artboard naming
127 |
128 | if (newArtboardName.includes("Dark")) {
129 | newArtboardName = newArtboardName.replace('Dark', '');
130 | } else if (newArtboardName.includes("Light")) {
131 | newArtboardName = newArtboardName.replace('Light', '');
132 | }
133 |
134 | if (newArtboardName.includes("dark")) {
135 | newArtboardName = newArtboardName.replace('dark', '');
136 | } else if (newArtboardName.includes("light")) {
137 | newArtboardName = newArtboardName.replace('light', '');
138 | }
139 |
140 | if (newArtboardName.includes("dakr")) {
141 | newArtboardName = newArtboardName.replace('dakr', '');
142 | } else if (newArtboardName.includes("lihgt")) {
143 | newArtboardName = newArtboardName.replace('lihgt', '');
144 | }
145 | }
146 |
147 | function createArtboatd() {
148 | if (CreateArtboard) {
149 | myArtboard = new Artboard({
150 | parent: page,
151 | name: newArtboardName + ' ' + toTheme,
152 | frame: {
153 | x: currentArtboard.frame.x + currentArtboard.frame.width + move,
154 | y: currentArtboard.frame.y,
155 | width: currentArtboard.frame.width,
156 | height: currentArtboard.frame.height
157 | }
158 | });
159 |
160 | myArtboard.background.enabled = true;
161 |
162 | if (toTheme == "Dark") {
163 | myArtboard.background.color = '#000000ff';
164 | }
165 | CreateArtboard = false;
166 | }
167 | }
168 |
169 | var libraries = __webpack_require__(0).getLibraries();
170 | for (var l = 0; l < Object.keys(libraries).length; l++) {
171 | if (libraries[l].name.includes('Type') || libraries[l].name.includes('Text') || libraries[l].name.includes('Fonts') || libraries[l].name.includes('Fundamentals')) {
172 | isGlobalText = true;
173 | TextLibrary = sketch.getLibraries()[l];
174 | textstyleReferences = TextLibrary.getImportableTextStyleReferencesForDocument(document);
175 | }
176 |
177 | if (libraries[l].name.includes('Color') || libraries[l].name.includes('Fundamentals') || libraries[l].name.includes('Colours')) {
178 | isGlobalColour = true;
179 | ColourLibrary = sketch.getLibraries()[l];
180 | layerstyleReferences = ColourLibrary.getImportableLayerStyleReferencesForDocument(document);
181 | swatchRefs = ColourLibrary.getImportableSwatchReferencesForDocument(document);
182 | }
183 | }
184 |
185 | //for each layer selected in the document, checking if there are artboards with sublayers
186 |
187 |
188 | var UI = __webpack_require__(3);
189 |
190 | UI.getInputFromUser("Switch to", {
191 | type: UI.INPUT_TYPE.selection,
192 | possibleValues: ['Light', 'Dark']
193 | }, function (err, value) {
194 | if (err) {
195 | UI.close();
196 | return;
197 | }
198 |
199 | if (value == 'Light') {
200 | fromTheme = 'Dark';
201 | toTheme = 'Light';
202 | }
203 | if (value == 'Dark') {
204 | fromTheme = 'Light';
205 | toTheme = 'Dark';
206 | }
207 | });
208 |
209 | selection.forEach(function (layer) {
210 | if (layer.layers && layer['class']() == "MSArtboardGroup") {
211 | master_iterator++;move += 150;
212 | var children = layer.children();
213 | currentArtboard = sketch.getSelectedDocument().selectedLayers.layers[master_iterator];
214 |
215 | //artboard name handling
216 |
217 | newArtboardName = sketch.getSelectedDocument().selectedLayers.layers[master_iterator].name;
218 | removeArtboardNames();
219 |
220 | CreateArtboard = true;
221 | createArtboatd();
222 |
223 | //////////GETTING ALL LAYERS IN AN ARTBOARD BY NAME, THEN ID
224 |
225 | for (var f = 0; f < children.count(); f++) {
226 | if (children[f]['class']() != "MSArtboardGroup") {
227 | var extracted_children_id = children[f].toString().split('(').pop().split(')')[0];
228 | var current_layer_in_artboard = document.getLayerWithID(extracted_children_id);
229 |
230 | //////////SYMBOL LAYER
231 |
232 | if (current_layer_in_artboard.type == "SymbolInstance") {
233 |
234 | //I use the extracted ID and found layer to match the correct library & master references
235 |
236 | var library_linked = current_layer_in_artboard.master.getLibrary();
237 | var symbolReferences = library_linked.getImportableSymbolReferencesForDocument(document);
238 | var _swatchRefs = library_linked.getImportableSwatchReferencesForDocument(document);
239 |
240 | if (!isGlobalColour) {
241 | layerstyleReferences = library_linked.getImportableLayerStyleReferencesForDocument(document);
242 | }
243 | if (!isGlobalText) {
244 | textstyleReferences = library_linked.getImportableTextStyleReferencesForDocument(document);
245 | }
246 |
247 | symbolReferences.forEach(function (ImportableObject) {
248 | if (ImportableObject.id == current_layer_in_artboard.symbolId) {
249 | var imported_symbol_name = ImportableObject.name.replace(fromTheme, toTheme);
250 | var to_Import = symbolReferences.filter(function (element) {
251 | return element.name == imported_symbol_name;
252 | });
253 | var symbolMaster = to_Import[0]['import']();
254 | instance = symbolMaster.createNewInstance();
255 |
256 | //sizes checked to match symbol to existing instance
257 |
258 | var new_frame = current_layer_in_artboard.frame;
259 | var new_x = new_frame.x;
260 | var new_y = new_frame.y;
261 | var new_width = new_frame.width;
262 | var new_height = new_frame.height;
263 | var new_rotation = current_layer_in_artboard.transform.rotation;
264 | var new_transform = current_layer_in_artboard.transform;
265 | var new_instance_name = current_layer_in_artboard.name;
266 |
267 | instance.name = new_instance_name;
268 | instance.transform = new_transform;
269 | instance.transform.rotation = new_rotation;
270 | instance.frame = { x: new_x, y: new_y, width: new_width, height: new_height };
271 | instance.parent = myArtboard;
272 |
273 | //going through overrides for symbols and texts separately
274 |
275 | for (var w = 0; w < Object.keys(instance.overrides).length; w++) {
276 |
277 | //only get the override if the value is differnet from the default one, otherwise let the symbol handle it
278 |
279 | //looking at overriding text
280 | if (current_layer_in_artboard.overrides[w].property == 'stringValue' && !current_layer_in_artboard.overrides[w].isDefault) {
281 | instance.overrides[w].value = current_layer_in_artboard.overrides[w].value;
282 | }
283 |
284 | if (current_layer_in_artboard.overrides[w].property == 'layerStyle' && !current_layer_in_artboard.overrides[w].isDefault) {
285 | layerstyleReferences.forEach(function (element) {
286 | if (element.id == current_layer_in_artboard.overrides[w].value) {
287 | var layer_style_switch_name = element.name.replace(fromTheme, toTheme);
288 | layerstyleReferences.forEach(function (sub_element) {
289 |
290 | if (sub_element.name == layer_style_switch_name) {
291 |
292 | var sharedStyle = sub_element['import']();
293 | instance.overrides[w].value = sharedStyle.id;
294 | }
295 | });
296 | }
297 | });
298 | }
299 |
300 | if (current_layer_in_artboard.overrides[w].property == 'textStyle' && !current_layer_in_artboard.overrides[w].isDefault) {
301 |
302 | textstyleReferences.forEach(function (element) {
303 |
304 | if (element.id == current_layer_in_artboard.overrides[w].value) {
305 | var text_stlye_override_switch_name = element.name.replace(fromTheme, toTheme);
306 | //look for the switched text style by its name
307 |
308 | textstyleReferences.forEach(function (sub_element) {
309 | if (sub_element.name == text_stlye_override_switch_name) {
310 | var textStyle_to_import = sub_element['import']();
311 | instance.overrides[w].value = textStyle_to_import.id;
312 | }
313 | });
314 | }
315 | });
316 | }
317 |
318 | if (current_layer_in_artboard.overrides[w].property == 'symbolID' && !current_layer_in_artboard.overrides[w].isDefault) {
319 | var override_symbol_master = document.getSymbolMasterWithID(current_layer_in_artboard.overrides[w].value);
320 | var override_library_linked = override_symbol_master.getLibrary();
321 |
322 | var override_symbolReferences = override_library_linked.getImportableSymbolReferencesForDocument(document);
323 |
324 | override_symbolReferences.forEach(function (element) {
325 |
326 | if (element.id == current_layer_in_artboard.overrides[w].value) {
327 |
328 | var symbol_override_switch_name = element.name.replace(fromTheme, toTheme);
329 | //look for the switched symbol by its name
330 |
331 | override_symbolReferences.forEach(function (sub_element) {
332 | if (sub_element.name == symbol_override_switch_name) {
333 |
334 | //importing the same symbol into the artboard , deleting it afterward to have it as a reference
335 |
336 | var master_to_delte = sub_element['import']();
337 | var instance_to_delete = master_to_delte.createNewInstance();
338 |
339 | instance_to_delete.parent = myArtboard;
340 | instance.overrides[w].value = instance_to_delete.symbolId;
341 | instance_to_delete.remove();
342 | }
343 | });
344 | }
345 | });
346 | }
347 | }
348 | }
349 | });
350 | }
351 |
352 | //////////TEXT LAYER
353 |
354 | if (current_layer_in_artboard.type == 'Text') {
355 | var text = new Text({
356 | text: current_layer_in_artboard.text,
357 | frame: current_layer_in_artboard.frame,
358 | style: current_layer_in_artboard.style,
359 | name: current_layer_in_artboard.name,
360 | sharedStyleId: current_layer_in_artboard.sharedStyleId,
361 | sharedStyle: current_layer_in_artboard.sharedStyle
362 | });
363 | text.behaviour = current_layer_in_artboard.behaviour;
364 | text.parent = myArtboard;
365 |
366 | if (text.sharedStyle != null) {
367 | if (text.sharedStyle.name.includes(fromTheme)) {
368 | var switch_text_style = text.sharedStyle.name.replace(fromTheme, toTheme);
369 |
370 | textstyleReferences.forEach(function (element) {
371 | if (element.name == switch_text_style) {
372 | var new_text_style = element['import']();
373 | text.sharedStyle = new_text_style;
374 | text.style.syncWithSharedStyle(new_text_style);
375 | }
376 | });
377 | }
378 | } else {
379 | //there are no text styles, just local swatches used
380 |
381 | if (!isGlobalColour) {
382 | log("Looking into local swatches for text colours");
383 | log("Current text color" + text.style.textColor);
384 | docSwatches.forEach(function (element) {
385 | if (element.color == text.style.textColor) {
386 | var swatch_switch = element.name;
387 | swatch_switch = swatch_switch.replace(fromTheme, toTheme);
388 | docSwatches.forEach(function (sub_swatch) {
389 | if (sub_swatch.name == swatch_switch) {
390 | text.style.textColor = sub_swatch.referencingColor;
391 | }
392 | });
393 | }
394 | });
395 | }
396 |
397 | //No text styles, global swatches are used
398 | else {
399 | var global_swatch_switch_text;
400 | log("Looking into global swatches");
401 |
402 | //importing all swatches into an array to get colours and names
403 |
404 | swatchRefs.forEach(function (element) {
405 | imported_swatches.push(element['import']());
406 | });
407 | /*finding which swatch is used currently based on color code */
408 | imported_swatches.forEach(function (sub_element) {
409 | if (sub_element.color == text.style.textColor) {
410 | log("Current swatch is" + sub_element.name);
411 |
412 | global_swatch_switch_text = sub_element.name;
413 | global_swatch_switch_text = global_swatch_switch_text.replace(fromTheme, toTheme);
414 | }
415 | });
416 | /*finding out the alternative darl/light swatch, then replacing it for the shape */
417 | imported_swatches.forEach(function (sub_sub_element) {
418 | if (sub_sub_element.name == global_swatch_switch_text) {
419 | text.style.textColor = sub_sub_element.referencingColor;
420 | }
421 | });
422 | }
423 | }
424 | }
425 |
426 | //////////SHAPE LAYER
427 |
428 | if (current_layer_in_artboard.type == 'ShapePath') {
429 | var global_swatch_switch;
430 |
431 | (function () {
432 | var shapePath = new ShapePath({
433 | shapeType: current_layer_in_artboard.shapeType,
434 | sharedStyle: current_layer_in_artboard.sharedStyle,
435 | frame: current_layer_in_artboard.frame,
436 | points: current_layer_in_artboard.points,
437 | transform: current_layer_in_artboard.transform,
438 | name: current_layer_in_artboard.name,
439 | style: current_layer_in_artboard.style,
440 | parent: myArtboard
441 |
442 | });
443 | shapePath.transform.rotation = current_layer_in_artboard.transform.rotation;
444 |
445 | if (shapePath.sharedStyle != null) {
446 | //layerstyleReferences only looks at layerstyles imported from the previous symbol in the document.
447 | layerstyleReferences.forEach(function (element) {
448 | if (element.id == shapePath.sharedStyleId) {
449 |
450 | var switch_layer_style = element.name;
451 | switch_layer_style = switch_layer_style.replace(fromTheme, toTheme);
452 |
453 | layerstyleReferences.forEach(function (sub_element) {
454 | if (sub_element.name == switch_layer_style) {
455 | var new_new_layer_style = sub_element['import']();
456 | shapePath.sharedStyleId = new_new_layer_style.id;
457 | shapePath.style.syncWithSharedStyle(new_new_layer_style);
458 | }
459 | });
460 | }
461 | });
462 | } else {
463 | //shapes using colour variables/swatches. Check if swatches are in a Colour global library or not
464 |
465 | if (!isGlobalColour) {
466 | log("Looking into local swatches");
467 | docSwatches.forEach(function (element) {
468 | if (element.color == shapePath.style.fills[0].color) {
469 | var swatch_switch = element.name;
470 | swatch_switch = swatch_switch.replace(fromTheme, toTheme);
471 | docSwatches.forEach(function (sub_swatch) {
472 | if (sub_swatch.name == swatch_switch) {
473 | shapePath.style.fills[0].color = sub_swatch.referencingColor;
474 | }
475 | });
476 | }
477 | });
478 | } else {
479 | log("Looking into global swatches");
480 |
481 | //importing all swatches into an array to get colours and names
482 |
483 | swatchRefs.forEach(function (element) {
484 | imported_swatches.push(element['import']());
485 | });
486 | /*finding which swatch is used currently based on color code */
487 | imported_swatches.forEach(function (sub_element) {
488 | if (sub_element.color == shapePath.style.fills[0].color) {
489 | log("Current swatch is" + sub_element.name);
490 |
491 | global_swatch_switch = sub_element.name;
492 | global_swatch_switch = global_swatch_switch.replace(fromTheme, toTheme);
493 | }
494 | });
495 | /*finding out the alternative darl/light swatch, then replacing it for the shape */
496 | imported_swatches.forEach(function (sub_sub_element) {
497 | if (sub_sub_element.name == global_swatch_switch) {
498 | shapePath.style.fills[0].color = sub_sub_element.referencingColor;
499 | }
500 | });
501 | }
502 | }
503 | })();
504 | }
505 | }
506 | }
507 | } else {
508 | UI.message('Please select one or more artboards');
509 | }
510 | });
511 |
512 | /***/ }),
513 | /* 3 */
514 | /***/ (function(module, exports) {
515 |
516 | module.exports = require("sketch/ui");
517 |
518 | /***/ })
519 | /******/ ]);
520 | if (key === 'default' && typeof exports === 'function') {
521 | exports(context);
522 | } else {
523 | exports[key](context);
524 | }
525 | }
526 | that['onRun'] = __skpm_run.bind(this, 'default')
527 |
--------------------------------------------------------------------------------