├── .appcast.xml
├── .gitignore
├── LICENSE
├── README.md
├── artwork
├── Icon.sketch
├── text-to-json.gif
└── text-to-styles.gif
├── assets
├── icon-64.png
└── icon.png
├── package-lock.json
├── package.json
├── sample
├── text-styles-sample-simple.sketch
├── text-styles-sample.sketch
├── tokens-array.json
└── tokens-object.json
├── src
├── createTextStyles.js
├── generators.js
├── manifest.json
├── maninfest.all.json
├── renderJSON.js
├── renderStyleSheet.js
└── setupDocument.js
└── text-to-styles.sketchplugin
└── Contents
├── Resources
├── icon-64.png
└── icon.png
└── Sketch
├── __createTextStyles.js
├── __createTextStyles.js.map
├── __renderJSON.js
├── __renderJSON.js.map
├── __renderStyleSheet.js
├── __renderStyleSheet.js.map
├── __setupDocument.js
├── __setupDocument.js.map
└── manifest.json
/.appcast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 |
6 |
7 | -
8 |
9 |
10 | -
11 |
12 |
13 | -
14 |
15 |
16 | -
17 |
18 |
19 | -
20 |
21 |
22 | -
23 |
24 |
25 | -
26 |
27 |
28 | -
29 |
30 |
31 | -
32 |
33 |
34 | -
35 |
36 |
37 | -
38 |
39 |
40 | -
41 |
42 |
43 | -
44 |
45 |
46 | -
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Thomas Brasington
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | # Text to Styles
4 |
5 | 
6 |
7 |
8 | ## What?
9 |
10 | Generate all the Sketch text styles you have based on a config set up in your artboards. No more making and maintaining multiple variations!
11 |
12 | ## Why?
13 |
14 | If your text style system requires the use of different alignments or colour variations you are faced with either detaching styles, risking updates overwrite the tweaks you make or you manually have to create every style.
15 |
16 | This plugin aims to solve the generation and maintenance of Sketch text styles where you need colour and alignment variations of your text styles.
17 |
18 | ## Installation
19 |
20 | [](https://sketchpacks.com/tbrasington/text-to-styles/install)
21 |
22 | Either install via Sketchpacks, Sketch Runner or...
23 |
24 | 1. Download from the [releases page](https://github.com/tbrasington/text-to-styles/releases)
25 | 2. Unzip
26 | 3. Double Click on `text-to-styles.sketchplugin`
27 |
28 | ## Text Style naming convention
29 | This is an opinioated plugin on how Text Styles should be named. The naming convention is:
30 |
31 | `Style Name/Colour/Alignment/Breakpoint Varation`
32 |
33 | The breakpoint variation is optional.
34 |
35 |
36 | ## Your Page setup
37 |
38 | There is a sample project under [sample/text-styles-sample.sketch](https://github.com/tbrasington/text-to-styles/blob/master/sample/text-styles-sample.sketch) to base your text and colour tokens off
39 |
40 | You will need to set your Page structure and naming like this:
41 |
42 | - Styles
43 | - Colours or Colors
44 | - Alignments
45 |
46 | Please note that this is case sensitive!
47 |
48 | ### Styles
49 | Add your base text styles here. This plugin will pick up on:
50 |
51 | - Font Family
52 | - Font Size
53 | - Font Weight
54 | - Font Style
55 | - Line Height
56 | - Letter Spacing
57 | - Text Transform (uppercase,lowercase)
58 | - Paragraph Spacing
59 |
60 | #### Breakpoint adjustments
61 | If you wish to add breakpoint adjustment for styles use the following naming syntax for the layer
62 |
63 | `Style Name/Breakpoint Variation`
64 |
65 | e.g.
66 |
67 | `Heading 1/BP1`
68 |
69 | The plugin will then split the name and add the breakpoint to the end of the text style name
70 |
71 | ### Colours
72 | Add shapes here with the colour value you want to render. The name of the layer defines the name in the Text Style palette.
73 | Order is done alphabetically.
74 |
75 | ### Alignments
76 | Add your alignments here by setting each text layer to your preffered alignment.
77 | Order is set Left, Center, Right.
78 |
79 | ## Commands
80 |
81 | There are several commands available `Run Document Setup`, `Create Text Styles`, `Render Style Sheet` and `Export JSON Tokens`
82 |
83 | ### Run Document Setup
84 | Sets up the Sketch document Page names with sample Styles, Alignments and Colors. You can then remove or modify them as you see fit.
85 |
86 | ### Create Text Styles
87 | Converts the contents of Styles, Alignments and Colors into text styles.
88 |
89 | ### Render Style Sheet
90 | This will reate a Page called "Rendered Styles" and create every combination within your text styles. Please make sure you have run the Create Text Styles command before.
91 |
92 | #### Performance
93 | This command can take a long time to run. The more combinations the longer it will take.
94 |
95 | ### Export JSON Tokens
96 |
97 | 
98 |
99 |
100 | This will export out the text styles and colour palettes as a JSON file to use in other applications. Perhaps your production code base or documentation.
101 |
102 | You will be presented with two options for formatting the text style json. Either an Array or an Object. Depending on your needs you may want the Object.
103 |
104 |
105 | #### Array formatting
106 |
107 | ```
108 | {
109 | "name": "Style 1",
110 | "styles": {
111 | "fontFamily": "SFProDisplay-Semibold",
112 | "fontSize": "28px",
113 | "lineHeight": "34px",
114 | "fontWeight": 8,
115 | "paragraphSpacing": 25,
116 | "letterSpacing": "0.02em",
117 | "textTransform": "none"
118 | },
119 | "alignments": [
120 | "left",
121 | "right",
122 | "center"
123 | ],
124 | "adjustments": [
125 | {
126 | "name": "BP3",
127 | "styles": {
128 | "fontSize": "42px",
129 | "lineHeight": "48px",
130 | "paragraphSpacing": 100,
131 | "letterSpacing": "0.03em"
132 | }
133 | }
134 | ]
135 | }
136 | ```
137 | #### Object formatting
138 |
139 | ```
140 | "Style 1": {
141 | "name": "Style 1",
142 | "styles": {
143 | "fontFamily": "SFProDisplay-Semibold",
144 | "fontSize": "28px",
145 | "lineHeight": "34px",
146 | "fontWeight": 8,
147 | "paragraphSpacing": 25,
148 | "letterSpacing": "0.02em",
149 | "textTransform": "none"
150 | },
151 | "alignments": [
152 | "left",
153 | "right",
154 | "center"
155 | ],
156 | "adjustments": [
157 | {
158 | "name": "BP3",
159 | "styles": {
160 | "fontSize": "42px",
161 | "lineHeight": "48px",
162 | "paragraphSpacing": 100,
163 | "letterSpacing": "0.03em"
164 | }
165 | }
166 | ]
167 | }
168 | ```
169 |
170 |
171 |
172 | ---
173 |
174 | @tbrasington | tbrasington.com
175 |
--------------------------------------------------------------------------------
/artwork/Icon.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/artwork/Icon.sketch
--------------------------------------------------------------------------------
/artwork/text-to-json.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/artwork/text-to-json.gif
--------------------------------------------------------------------------------
/artwork/text-to-styles.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/artwork/text-to-styles.gif
--------------------------------------------------------------------------------
/assets/icon-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/assets/icon-64.png
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/assets/icon.png
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "text-to-styles",
3 | "version": "4.0.0",
4 | "license": "MIT",
5 | "repository": "https://github.com/tbrasington/text-to-styles.git",
6 | "description": "Generates Sketch Text Styles from Layers to easily manage, size, colour and alignment variations",
7 | "engines": {
8 | "sketch": ">=53.0"
9 | },
10 | "skpm": {
11 | "name": "Text to Styles",
12 | "manifest": "src/manifest.json",
13 | "main": "text-to-styles.sketchplugin",
14 | "assets": [
15 | "assets/**/*"
16 | ],
17 | "identifier": "text-to-styles.plugin"
18 | },
19 | "scripts": {
20 | "build": "skpm-build",
21 | "watch": "skpm-build --watch",
22 | "start": "skpm-build --watch --run",
23 | "postinstall": "npm run build && skpm-link"
24 | },
25 | "devDependencies": {
26 | "@skpm/builder": "^0.7.5"
27 | },
28 | "author": "Thomas Brasington ",
29 | "dependencies": {
30 | "@skpm/dialog": "^0.4.0",
31 | "@skpm/fs": "^0.1.4",
32 | "@skpm/path": "^0.1.4",
33 | "json-format": "^1.0.1",
34 | "path": "^0.12.7",
35 | "ramda": "^0.26.1"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/sample/text-styles-sample-simple.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/sample/text-styles-sample-simple.sketch
--------------------------------------------------------------------------------
/sample/text-styles-sample.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/sample/text-styles-sample.sketch
--------------------------------------------------------------------------------
/sample/tokens-array.json:
--------------------------------------------------------------------------------
1 | {
2 | "colours": {
3 | "Black": "rgba(0,0,0,1)",
4 | "Hot UI Blue": "rgba(0,88,255,1)",
5 | "Pinky Red": "rgba(254,84,105,1)",
6 | "Baby Green": "rgba(58,175,149,1)"
7 | },
8 | "typography": [
9 | {
10 | "name": "Style 1",
11 | "styles": {
12 | "fontFamily": "SF Pro Display",
13 | "fontWeight": 8,
14 | "fontSize": "28px",
15 | "lineHeight": "34px",
16 | "fontStyle": "normal",
17 | "paragraphSpacing": 25,
18 | "letterSpacing": "0.02em",
19 | "textTransform": "none"
20 | },
21 | "alignments": [
22 | "left",
23 | "right",
24 | "center"
25 | ],
26 | "adjustments": [
27 | {
28 | "name": "BP3",
29 | "styles": {
30 | "fontSize": "42px",
31 | "lineHeight": "48px",
32 | "paragraphSpacing": 100,
33 | "letterSpacing": "0.03em"
34 | }
35 | }
36 | ]
37 | },
38 | {
39 | "name": "Style 2",
40 | "styles": {
41 | "fontFamily": "Helvetica Neue",
42 | "fontWeight": 3,
43 | "fontSize": "14px",
44 | "lineHeight": "0px",
45 | "fontStyle": "normal",
46 | "paragraphSpacing": 0,
47 | "letterSpacing": "0em",
48 | "textTransform": "none"
49 | },
50 | "alignments": [
51 | "left",
52 | "right",
53 | "center"
54 | ],
55 | "adjustments": []
56 | },
57 | {
58 | "name": "Style 3",
59 | "styles": {
60 | "fontFamily": "Arial",
61 | "fontWeight": 9,
62 | "fontSize": "14px",
63 | "lineHeight": "0px",
64 | "fontStyle": "normal",
65 | "paragraphSpacing": 0,
66 | "letterSpacing": "0em",
67 | "textTransform": "none"
68 | },
69 | "alignments": [
70 | "left",
71 | "right",
72 | "center"
73 | ],
74 | "adjustments": []
75 | },
76 | {
77 | "name": "Style 4",
78 | "styles": {
79 | "fontFamily": "SF Pro Display",
80 | "fontWeight": 5,
81 | "fontSize": "14px",
82 | "lineHeight": "16px",
83 | "fontStyle": "normal",
84 | "paragraphSpacing": 20,
85 | "letterSpacing": "0.2em",
86 | "textTransform": "uppercase"
87 | },
88 | "alignments": [
89 | "left",
90 | "right",
91 | "center"
92 | ],
93 | "adjustments": [
94 | {
95 | "name": "bp2",
96 | "styles": {
97 | "fontSize": "18px",
98 | "lineHeight": "20px",
99 | "letterSpacing": "0.5em"
100 | }
101 | },
102 | {
103 | "name": "bp3",
104 | "styles": {
105 | "fontSize": "18px",
106 | "lineHeight": "40px",
107 | "letterSpacing": "0.5000625000000001em"
108 | }
109 | }
110 | ]
111 | },
112 | {
113 | "name": "Style 5",
114 | "styles": {
115 | "fontFamily": "SF Pro Display",
116 | "fontWeight": 3,
117 | "fontSize": "200px",
118 | "lineHeight": "200px",
119 | "fontStyle": "normal",
120 | "paragraphSpacing": 200,
121 | "letterSpacing": "2em",
122 | "textTransform": "none"
123 | },
124 | "alignments": [
125 | "left",
126 | "right",
127 | "center"
128 | ],
129 | "adjustments": []
130 | },
131 | {
132 | "name": "Style 6",
133 | "styles": {
134 | "fontFamily": "SF Pro Display",
135 | "fontWeight": 3,
136 | "fontSize": "200px",
137 | "lineHeight": "200px",
138 | "fontStyle": "normal",
139 | "paragraphSpacing": 200,
140 | "letterSpacing": "2em",
141 | "textTransform": "none"
142 | },
143 | "alignments": [
144 | "left",
145 | "right",
146 | "center"
147 | ],
148 | "adjustments": []
149 | },
150 | {
151 | "name": "Style 7",
152 | "styles": {
153 | "fontFamily": "SF Pro Display",
154 | "fontWeight": 2,
155 | "fontSize": "200px",
156 | "lineHeight": "200px",
157 | "fontStyle": "normal",
158 | "paragraphSpacing": 200,
159 | "letterSpacing": "2em",
160 | "textTransform": "none"
161 | },
162 | "alignments": [
163 | "left",
164 | "right",
165 | "center"
166 | ],
167 | "adjustments": []
168 | },
169 | {
170 | "name": "Style 8",
171 | "styles": {
172 | "fontFamily": "SF Pro Display",
173 | "fontWeight": 5,
174 | "fontSize": "24px",
175 | "lineHeight": "32px",
176 | "fontStyle": "italic",
177 | "paragraphSpacing": 100,
178 | "letterSpacing": "0.1em",
179 | "textTransform": "none"
180 | },
181 | "alignments": [
182 | "left",
183 | "right",
184 | "center"
185 | ],
186 | "adjustments": []
187 | }
188 | ]
189 | }
--------------------------------------------------------------------------------
/sample/tokens-object.json:
--------------------------------------------------------------------------------
1 | {
2 | "colours": {
3 | "Black": "rgba(0,0,0,1)",
4 | "Hot UI Blue": "rgba(0,88,255,1)",
5 | "Pinky Red": "rgba(254,84,105,1)",
6 | "Baby Green": "rgba(58,175,149,1)"
7 | },
8 | "typography": {
9 | "Style 1": {
10 | "name": "Style 1",
11 | "styles": {
12 | "fontFamily": "SFProDisplay-Semibold",
13 | "fontSize": "28px",
14 | "lineHeight": "34px",
15 | "fontWeight": 8,
16 | "paragraphSpacing": 25,
17 | "letterSpacing": "0.02em",
18 | "textTransform": "none"
19 | },
20 | "alignments": [
21 | "left",
22 | "right",
23 | "center"
24 | ],
25 | "adjustments": [
26 | {
27 | "name": "BP3",
28 | "styles": {
29 | "fontSize": "42px",
30 | "lineHeight": "48px",
31 | "paragraphSpacing": 100,
32 | "letterSpacing": "0.03em"
33 | }
34 | }
35 | ]
36 | },
37 | "Style 2": {
38 | "name": "Style 2",
39 | "styles": {
40 | "fontFamily": "SFProText-Regular",
41 | "fontSize": "14px",
42 | "lineHeight": "0px",
43 | "fontWeight": 5,
44 | "paragraphSpacing": 0,
45 | "letterSpacing": "0em",
46 | "textTransform": "none"
47 | },
48 | "alignments": [
49 | "left",
50 | "right",
51 | "center"
52 | ],
53 | "adjustments": []
54 | },
55 | "Style 3": {
56 | "name": "Style 3",
57 | "styles": {
58 | "fontFamily": "SFProText-Bold",
59 | "fontSize": "14px",
60 | "lineHeight": "0px",
61 | "fontWeight": 9,
62 | "paragraphSpacing": 0,
63 | "letterSpacing": "0em",
64 | "textTransform": "none"
65 | },
66 | "alignments": [
67 | "left",
68 | "right",
69 | "center"
70 | ],
71 | "adjustments": []
72 | },
73 | "Style 4": {
74 | "name": "Style 4",
75 | "styles": {
76 | "fontFamily": "SFProDisplay-Regular",
77 | "fontSize": "14px",
78 | "lineHeight": "16px",
79 | "fontWeight": 5,
80 | "paragraphSpacing": 20,
81 | "letterSpacing": "0.2em",
82 | "textTransform": "uppercase"
83 | },
84 | "alignments": [
85 | "left",
86 | "right",
87 | "center"
88 | ],
89 | "adjustments": [
90 | {
91 | "name": "bp2",
92 | "styles": {
93 | "fontSize": "18px",
94 | "lineHeight": "20px",
95 | "letterSpacing": "0.5em"
96 | }
97 | },
98 | {
99 | "name": "bp3",
100 | "styles": {
101 | "fontSize": "18px",
102 | "lineHeight": "40px",
103 | "letterSpacing": "0.5000625000000001em"
104 | }
105 | }
106 | ]
107 | },
108 | "Style 5": {
109 | "name": "Style 5",
110 | "styles": {
111 | "fontFamily": "SFProDisplay-LightItalic",
112 | "fontSize": "200px",
113 | "lineHeight": "200px",
114 | "fontWeight": 3,
115 | "fontStyle": "italic",
116 | "paragraphSpacing": 500,
117 | "letterSpacing": "2em",
118 | "textTransform": "none"
119 | },
120 | "alignments": [
121 | "left",
122 | "right",
123 | "center"
124 | ],
125 | "adjustments": []
126 | }
127 | }
128 | }
--------------------------------------------------------------------------------
/src/createTextStyles.js:
--------------------------------------------------------------------------------
1 | import { splitEvery } from "ramda";
2 | import sketch, { Text } from "sketch/dom";
3 | import { extractStyles, generateTextStyles } from "./generators";
4 |
5 | export default function(context) {
6 | const designTokens = extractStyles(context, false);
7 |
8 | const textStyles = generateTextStyles(designTokens);
9 |
10 | // all the pages are present so we can render the styles
11 | if (designTokens.render) {
12 |
13 |
14 | let document = sketch.fromNative(context.document);
15 | const cachedStyles = document.sharedTextStyles;
16 |
17 | let stored_styles = [];
18 |
19 | // const l = textStyles.length;
20 | // for (let property = 0; property < l; property++) {
21 | // let styleName = textStyles[property].name;
22 | // let checkStyle = cachedStyles.find(item => item.name === styleName);
23 | // if (typeof checkStyle === "object") {
24 | // const layer = new Text({
25 | // style: textStyles[property].style
26 | // });
27 |
28 | // checkStyle.style = layer.style;
29 | // stored_styles.push(checkStyle);
30 | // } else {
31 | // stored_styles.push({
32 | // name: styleName,
33 | // style: textStyles[property].style
34 | // });
35 | // }
36 | // }
37 |
38 | splitEvery(100, textStyles).forEach(styleChunk => {
39 | styleChunk.forEach(style => {
40 | let styleName = style.name;
41 | let checkStyle = cachedStyles.find(item => item.name === styleName);
42 | if (typeof checkStyle === "object") {
43 | const layer = new Text({
44 | style: style.style
45 | });
46 |
47 | checkStyle.style = layer.style;
48 | stored_styles.push(checkStyle);
49 | } else {
50 | stored_styles.push({
51 | name: styleName,
52 | style: style.style
53 | });
54 | }
55 | });
56 | });
57 |
58 | // update the shared text styles with this array
59 | document.sharedTextStyles = stored_styles;
60 |
61 |
62 |
63 | context.document.showMessage(
64 | `${Object.keys(textStyles).length} styles added (${
65 | Object.keys(designTokens.typography).length
66 | } Text Styles * ${Object.keys(designTokens.colours).length} colours * ${
67 | Object.keys(designTokens.textAlignments).length
68 | } alignments) 🙌`
69 | );
70 | } else {
71 | context.document.showMessage(
72 | "No styles rendered. Check your document setup. Documentation here https://github.com/tbrasington/text-to-styles"
73 | );
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/generators.js:
--------------------------------------------------------------------------------
1 |
2 | import dom from "sketch/dom";
3 | import UI from "sketch/ui";
4 |
5 | function convertSketchColourToRGBA(colour) {
6 | const red = Math.round(colour.red() * 255);
7 | const green = Math.round(colour.green() * 255);
8 | const blue = Math.round(colour.blue() * 255);
9 | return "rgba(" + red + "," + green + "," + blue + "," + colour.alpha() + ")";
10 | }
11 |
12 | export function extractStyles(context, convert) {
13 | const doc = context.document;
14 | const pages = doc.pages();
15 |
16 | // we need to check if we have all the pages
17 | let pagesExist = {
18 | alignments: false,
19 | colors: false,
20 | styles: false
21 | };
22 |
23 | // arrays and objects for our styles
24 | let TypographyStyles = [];
25 | let DocumentColours = {};
26 | let textAlignments = [];
27 |
28 | pages.forEach(page => {
29 | // alignments
30 | if (String(page.name()) === "Alignments") {
31 | // page exists set to true
32 | pagesExist.alignments = true;
33 |
34 | page.layers().forEach(layer => {
35 | //log(layer.name() + ' ' + layer.textAlignment())
36 | let alignment = "left";
37 | if (layer.textAlignment() === 4) alignment = "left";
38 | if (layer.textAlignment() === 2) alignment = "center";
39 | if (layer.textAlignment() === 1) alignment = "right";
40 | textAlignments.push(alignment);
41 | });
42 | }
43 |
44 | // page styles
45 | if (String(page.name()) === "Styles") {
46 | // page exists set to true
47 | pagesExist.styles = true;
48 |
49 | // get styles
50 | page.layers().forEach(layer => {
51 | if (layer.class() === MSTextLayer) {
52 | // log(layer.font().fontName())
53 | // log(layer.fontSize())
54 | // log(layer.lineHeight())
55 | // log(layer.characterSpacing())
56 | // log(layer.style().textStyle().encodedAttributes() )
57 | //log(layer.styleAttributes()["MSAttributedStringTextTransformAttribute"])
58 | let textTransform = "none";
59 |
60 | if (
61 | String(
62 | layer.styleAttributes()[
63 | "MSAttributedStringTextTransformAttribute"
64 | ]
65 | ) === "1"
66 | )
67 | textTransform = "uppercase"; // null: none, 1: uppercase and 2 lowercase
68 | if (
69 | String(
70 | layer.styleAttributes()[
71 | "MSAttributedStringTextTransformAttribute"
72 | ]
73 | ) === "2"
74 | )
75 | textTransform = "lowercase";
76 |
77 | // console.log( String(layer.name()) + " " + layer.font().fontName() + " " + dom.fromNative(layer).style.fontWeight + " " + dom.fromNative(layer).style.fontStyle )
78 | // console.log("-----" )
79 |
80 | // fontFamily : dom.fromNative(layer).style.fontFamily ,
81 | // fontWeight : dom.fromNative(layer).style.fontWeight ,
82 | //console.log(dom.fromNative(layer).style.fontStyle)
83 | console.log(layer.sketchObject)
84 |
85 | function appKitWeightToCSSWeight(weight){
86 | return [100,100,100,200,300,400,500,500,600,700,800,900,900,900,900,900][weight]
87 | }
88 | var weight = NSFontManager.sharedFontManager().weightOfFont_(layer.font());
89 | log(appKitWeightToCSSWeight(weight));
90 |
91 | TypographyStyles.push({
92 | name: String(layer.name()),
93 | styles: {
94 | fontFamily: dom.fromNative(layer).style.fontFamily,
95 | fontWeight: convert
96 | ? dom.fromNative(layer).style.fontWeight * 100
97 | : dom.fromNative(layer).style.fontWeight,
98 | fontSize: layer.fontSize() + (convert ? "px" : ""),
99 | lineHeight: layer.lineHeight() + (convert ? "px" : ""),
100 | fontStyle:
101 | dom.fromNative(layer).style.fontStyle != undefined
102 | ? dom.fromNative(layer).style.fontStyle
103 | : "normal",
104 | paragraphSpacing: dom.fromNative(layer).style.paragraphSpacing,
105 | ...(convert && {
106 | letterSpacing: String(layer.characterSpacing() / 10 + "em")
107 | }),
108 | ...(!convert && { kerning: layer.characterSpacing() }),
109 | textTransform: textTransform,
110 | borders: dom.fromNative(layer).style.borders || []
111 | },
112 | alignments: textAlignments,
113 | adjustments: []
114 | });
115 | }
116 | });
117 | }
118 |
119 | // get colours
120 | if (String(page.name()) === "Colours" || String(page.name()) === "Colors") {
121 | // page exists set to true
122 | pagesExist.colors = true;
123 |
124 | DocumentColours = {};
125 | page.layers().forEach(layer => {
126 | DocumentColours[layer.name()] = convert
127 | ? convertSketchColourToRGBA(
128 | layer
129 | .style()
130 | .firstEnabledFill()
131 | .color()
132 | )
133 | : layer
134 | .style()
135 | .firstEnabledFill()
136 | .color();
137 | });
138 | }
139 | });
140 |
141 |
142 | let allPagesHere = true;
143 | let messages = [];
144 |
145 | // first check for pages
146 | if (!pagesExist.alignments) {
147 | messages.push('Your document is missing the page named "Alignments".');
148 | allPagesHere = false;
149 | }
150 |
151 | if (!pagesExist.colors) {
152 | messages.push('Your document is missing the page named "Colors". ');
153 | allPagesHere = false;
154 | }
155 |
156 | if (!pagesExist.styles) {
157 | messages.push('Your document is missing the page named "Styles".');
158 | allPagesHere = false;
159 | }
160 |
161 | // now that we have checked for pages, lets see if there is anything in them
162 | if (pagesExist.alignments && textAlignments.length === 0) {
163 | messages.push("Your alignments page has no alignments in it.");
164 | allPagesHere = false;
165 | }
166 |
167 | if (pagesExist.colors && Object.keys(DocumentColours).length === 0) {
168 | messages.push("Your colors page has no colors in it.");
169 | allPagesHere = false;
170 | }
171 |
172 | if (pagesExist.styles && TypographyStyles.length === 0) {
173 | messages.push("Your styles page has no styles in it.");
174 | allPagesHere = false;
175 | }
176 |
177 | let messageString = "";
178 | messages.forEach(message => {
179 | messageString += message + "\n";
180 | });
181 |
182 | if (!allPagesHere) UI.alert("Unable to render styles", messageString);
183 |
184 | const DesignSystemTokens = {
185 | colours: DocumentColours,
186 | typography: TypographyStyles,
187 | textAlignments: textAlignments,
188 | render: allPagesHere
189 | };
190 |
191 | return DesignSystemTokens;
192 | }
193 |
194 | export function generateTextStyles(json) {
195 | // can we calculate this beforehand?
196 | let typeStyles = new Array();
197 |
198 | json.typography.forEach(item => {
199 | Object.keys(json.colours).forEach(colour => {
200 | item.alignments.map((align, index) => {
201 | // this splits at a slash and adds the adjustments for breakpoints after the alignment
202 | // assumption is that there is only one adjusment
203 | let name = item.name.split("/");
204 | typeStyles.push({
205 | name: `${name[0]}/${colour}/${index +
206 | "_" +
207 | align +
208 | (name.length > 1 ? "/" + name[1] : "")}`,
209 | style: {
210 | textColor: dom.Style.colorToString(json.colours[colour]),
211 | alignment: align,
212 | ...item.styles
213 | }
214 | });
215 | });
216 | });
217 | });
218 |
219 | return typeStyles;
220 | }
221 |
222 | function checkMatch(baseStyle, newStyle, prop) {
223 | let value = true;
224 |
225 | // for now we are just going off the previous style. As this would need to check
226 | // every prop across every adjustment :/
227 | if (JSON.stringify(baseStyle[prop]) === JSON.stringify(newStyle[prop])) {
228 | // very primitive and breaks if order is out of sync
229 | value = false;
230 | }
231 |
232 | //log( prop + ' ' + baseStyle[prop] + ' ----- ' + prop + ' ' +newStyle[prop] + ' value ' + value)
233 |
234 | return value;
235 | }
236 |
237 | export function generateJSONStyles(json, arrayFormat) {
238 | let typeStyles = {};
239 | let refinedBreakpoints = [];
240 | //log(json.typography)
241 | json.typography.forEach(item => {
242 | let name = item.name.split("/");
243 | if (!typeStyles[name[0]]) {
244 | typeStyles[name[0]] = {
245 | name: name[0],
246 | styles: item.styles,
247 | alignments: item.alignments,
248 | adjustments: []
249 | };
250 | } else {
251 | let currentStyle = item.styles;
252 | //let previousStyle = typeStyles[name[0]].styles
253 | // work out previous style
254 | const adjustmentLength = typeStyles[name[0]].adjustments.length;
255 | refinedBreakpoints[adjustmentLength] = { name: name[1], styles: {} };
256 |
257 | // if(adjustmentLength>0){
258 | // previousStyle = typeStyles[name[0]].adjustments[adjustmentLength-1]
259 | // }
260 |
261 | //previousStyle,
262 | Object.keys(currentStyle).map(checked => {
263 | if (checkMatch(typeStyles[name[0]].styles, currentStyle, checked)) {
264 | refinedBreakpoints[adjustmentLength].styles[checked] =
265 | currentStyle[checked];
266 | }
267 | });
268 |
269 | typeStyles[name[0]].adjustments.push(
270 | refinedBreakpoints[adjustmentLength]
271 | );
272 | }
273 | });
274 |
275 | // finally merge colours back in and return text to an array
276 | let formattedTokens = {
277 | colours: json.colours,
278 | typography: arrayFormat
279 | ? Object.keys(typeStyles).map(function(key) {
280 | return typeStyles[key];
281 | })
282 | : typeStyles
283 | };
284 | return formattedTokens;
285 | }
286 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "compatibleVersion": 3,
3 | "bundleVersion": 1,
4 | "icon": "icon.png",
5 | "name": "Text to Styles",
6 | "description": "Generates Sketch Text Styles from Layers to easily manage, size, colour and alignment variations",
7 | "commands": [
8 |
9 | {
10 | "name": "Create Text Styles",
11 | "identifier": "createTextStyles",
12 | "script": "./createTextStyles.js"
13 | }
14 | ],
15 | "menu": {
16 | "title": "Text to Styles",
17 | "items": [
18 | "runDocumentSetup",
19 | "createTextStyles",
20 | "renderStyleSheet",
21 | "renderJSON"
22 | ]
23 | }
24 | }
--------------------------------------------------------------------------------
/src/maninfest.all.json:
--------------------------------------------------------------------------------
1 | {
2 | "compatibleVersion": 3,
3 | "bundleVersion": 1,
4 | "icon": "icon.png",
5 | "name": "Text to Styles",
6 | "description": "Generates Sketch Text Styles from Layers to easily manage, size, colour and alignment variations",
7 | "commands": [
8 | {
9 | "name": "Run Document Setup",
10 | "identifier": "runDocumentSetup",
11 | "script": "./setupDocument.js"
12 | },
13 | {
14 | "name": "Create Text Styles",
15 | "identifier": "createTextStyles",
16 | "script": "./createTextStyles.js"
17 | },
18 | {
19 | "name": "Render Style Sheet",
20 | "identifier": "renderStyleSheet",
21 | "script": "./renderStyleSheet.js"
22 | },
23 | {
24 | "name": "Export JSON Tokens",
25 | "identifier": "renderJSON",
26 | "script": "./renderJSON.js"
27 | }
28 | ],
29 | "menu": {
30 | "title": "Text to Styles",
31 | "items": [
32 | "runDocumentSetup",
33 | "createTextStyles",
34 | "renderStyleSheet",
35 | "renderJSON"
36 | ]
37 | }
38 | }
--------------------------------------------------------------------------------
/src/renderJSON.js:
--------------------------------------------------------------------------------
1 | import dialog from "@skpm/dialog";
2 | import path from "@skpm/path";
3 | import fs from "@skpm/fs";
4 | import jsonFormat from "json-format";
5 | import Sketch from "sketch";
6 |
7 | import { extractStyles, generateJSONStyles } from "./generators";
8 |
9 | function save(filename, fileContents) {
10 | console.log(filename)
11 |
12 | const targetFile = path.resolve(filename);
13 | fs.writeFileSync(targetFile, fileContents, "utf8");
14 | }
15 |
16 | export default function(context) {
17 | const doc = context.document;
18 |
19 | // ok lets get the styles
20 |
21 | const designTokens = extractStyles(context, true);
22 |
23 | if (designTokens.render) {
24 | const options = ["Array", "Object"];
25 | const textSaveSelection = Sketch.UI.getInputFromUser(
26 | "Would you like the text styles as an Array or Object",
27 | {
28 | type: Sketch.UI.INPUT_TYPE.selection,
29 | possibleValues: options
30 | },
31 | (err, value) => {
32 | if (err) {
33 | // most likely the user canceled the input
34 | return;
35 | } else {
36 | if (value[2]) {
37 | let textSaveMethod = true;
38 | if (value === "Object") textSaveMethod = false;
39 | if (value === "Array") textSaveMethod = true;
40 | const arranged = generateJSONStyles(designTokens, textSaveMethod);
41 |
42 | // Save the file
43 | let saveDialog = dialog.showSaveDialog(
44 | doc,
45 | {
46 | defaultPath: "tokens.json",
47 | message: "Choose a folder to save your tokens"
48 | }
49 | ).then( result => {
50 | if(!result.cancelled) save(result.filePath, jsonFormat(arranged));
51 | });
52 |
53 |
54 | }
55 | }
56 | }
57 | );
58 | } else {
59 | context.document.showMessage('No styles rendered. Check your document setup. Documentation here https://github.com/tbrasington/text-to-styles');
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/renderStyleSheet.js:
--------------------------------------------------------------------------------
1 | import sketch, { Text } from "sketch/dom";
2 |
3 | export default function(context) {
4 | let document = sketch.fromNative(context.document);
5 | const pages = context.document.pages();
6 |
7 | // Remove previous rendered pages (thanks to react-sketchapp)
8 | for (let index = pages.length - 1; index >= 0; index -= 1) {
9 | if (pages.length > 1) {
10 | String(pages[index].name()) === "Rendered Styles" &&
11 | context.document.documentData().removePageAtIndex(index);
12 | }
13 | }
14 |
15 | let RenderPage = context.document.addBlankPage();
16 | RenderPage.name = "Rendered Styles";
17 |
18 | let previousFrame = null;
19 | // now make a page
20 |
21 | const stl = document.sharedTextStyles.length;
22 | for (let property = 0; property < stl; property++) {
23 | let textLayer = new Text({
24 | text: document.sharedTextStyles[property].name,
25 | frame: {
26 | width:100,
27 | height: 32,
28 | x: 0,
29 | y:
30 | previousFrame != null
31 | ? Math.ceil(previousFrame.frame.height + previousFrame.frame.y + 24)
32 | : 0
33 | },
34 | sharedStyleId: document.sharedTextStyles[property].id,
35 | style: document.sharedTextStyles[property].style,
36 | parent : RenderPage
37 | });
38 |
39 | textLayer.name = document.sharedTextStyles[property].name;
40 | previousFrame = textLayer;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/setupDocument.js:
--------------------------------------------------------------------------------
1 | import { Text, ShapePath, Style } from "sketch/dom";
2 |
3 | export default function(context) {
4 |
5 | // Remove exisiting Pages
6 | for (let index = context.document.pages().length - 1; index >= 0; index -= 1) {
7 |
8 | context.document.documentData().removePageAtIndex(index);
9 |
10 | }
11 |
12 | // Add pages
13 | const StylesPage = context.document.addBlankPage();
14 | StylesPage.name = "Styles";
15 |
16 | const AlignmentsPage = context.document.addBlankPage();
17 | AlignmentsPage.name = "Alignments";
18 |
19 | const ColorsPage = context.document.addBlankPage();
20 | ColorsPage.name = "Colors";
21 |
22 |
23 | // Add Text to Styles Page
24 | const textLayer1 = new Text({
25 | text: "Style 1",
26 | frame: {
27 | width: 100,
28 | height: 32,
29 | x: 0,
30 | y: 0
31 | },
32 | style: {
33 | fontFamily: 'Helvetica',
34 | fontWeight: 8,
35 | fontSize: 24,
36 | lineHeight: 24 * 1.5,
37 | fontStyle: "normal",
38 | paragraphSpacing: 24*1.5,
39 | kerning : 0
40 | },
41 | parent : StylesPage
42 | });
43 | textLayer1.name = "Style 1";
44 |
45 | const textLayer2 = new Text({
46 | text: "Style 2",
47 | frame: {
48 | width: 100,
49 | height: 32,
50 | x: 0,
51 | y: textLayer1.frame.height + 24
52 | },
53 | style: {
54 | fontFamily: 'Helvetica',
55 | fontWeight: 4,
56 | fontSize: 16,
57 | lineHeight: 16 * 1.5,
58 | fontStyle: "normal",
59 | paragraphSpacing: 16*1.5,
60 | kerning : 0
61 | },
62 | parent : StylesPage
63 | });
64 | textLayer2.name = "Style 2";
65 |
66 | // Add Alignments
67 | const alignmentLayerLeft = new Text({
68 | text: "Left",
69 | frame: {
70 | width: 100,
71 | height: 32,
72 | x: 0,
73 | y: 0
74 | },
75 | style: {
76 | fontFamily: 'Helvetica',
77 | fontWeight: 4,
78 | fontSize: 16,
79 | lineHeight: 16 * 1.5,
80 | fontStyle: "normal",
81 | paragraphSpacing: 16*1.5,
82 | kerning : 0,
83 | alignment : 'left'
84 | },
85 | parent : AlignmentsPage
86 | });
87 | alignmentLayerLeft.name = "Left";
88 |
89 | const alignmentLayerRight = new Text({
90 | text: "Right",
91 | frame: {
92 | width: 100,
93 | height: 32,
94 | x: 0,
95 | y: 0
96 | },
97 | style: {
98 | fontFamily: 'Helvetica',
99 | fontWeight: 4,
100 | fontSize: 16,
101 | lineHeight: 16 * 1.5,
102 | fontStyle: "normal",
103 | paragraphSpacing: 16*1.5,
104 | kerning : 0,
105 | alignment : 'right'
106 | },
107 | parent : AlignmentsPage
108 | });
109 | alignmentLayerLeft.name = "Right";
110 |
111 | // Add Colors
112 | new ShapePath({
113 | name: 'Black',
114 | shapeType: ShapePath.ShapeType.Oval,
115 | parent : ColorsPage,
116 | frame : {
117 | width: 100,
118 | height: 100,
119 | x: 0,
120 | y : 0
121 | },
122 | style : {
123 | fills : [
124 | {
125 | color: '#111111',
126 | fillType: Style.FillType.Color,
127 | }
128 | ],
129 | borders : []
130 | }
131 | });
132 |
133 | new ShapePath({
134 | name: 'Red',
135 | shapeType: ShapePath.ShapeType.Oval,
136 | parent : ColorsPage,
137 | frame : {
138 | width: 100,
139 | height: 100,
140 | x: 124,
141 | y : 0
142 | },
143 | style : {
144 | fills : [
145 | {
146 | color: '#cc0000',
147 | fillType: Style.FillType.Color,
148 | }
149 | ],
150 | borders : []
151 | }
152 | });
153 |
154 | }
155 |
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Resources/icon-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/text-to-styles.sketchplugin/Contents/Resources/icon-64.png
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Resources/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tbrasington/text-to-styles/d3e980b2f06330ddb62690819699e97239a26269/text-to-styles.sketchplugin/Contents/Resources/icon.png
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Sketch/__renderJSON.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./node_modules/@skpm/dialog/lib/index.js","webpack://exports/./node_modules/@skpm/dialog/lib/message-box.js","webpack://exports/./node_modules/@skpm/dialog/lib/open-dialog.js","webpack://exports/./node_modules/@skpm/dialog/lib/save-dialog.js","webpack://exports/./node_modules/@skpm/dialog/lib/utils.js","webpack://exports/./node_modules/@skpm/fs/index.js","webpack://exports/./node_modules/@skpm/path/index.js","webpack://exports/./node_modules/@skpm/path/sketch-specifics.js","webpack://exports/./node_modules/@skpm/promise/index.js","webpack://exports/./node_modules/json-format/index.js","webpack://exports/./src/generators.js","webpack://exports/./src/renderJSON.js","webpack://exports/external \"sketch\"","webpack://exports/external \"sketch/dom\"","webpack://exports/external \"sketch/ui\"","webpack://exports/external \"util\""],"names":["convertSketchColourToRGBA","colour","red","Math","round","green","blue","alpha","extractStyles","context","convert","doc","document","pages","pagesExist","alignments","colors","styles","TypographyStyles","DocumentColours","textAlignments","forEach","page","String","name","layers","layer","alignment","textAlignment","push","class","MSTextLayer","textTransform","styleAttributes","fontFamily","dom","fromNative","style","fontWeight","fontSize","lineHeight","fontStyle","undefined","paragraphSpacing","letterSpacing","characterSpacing","kerning","borders","adjustments","firstEnabledFill","color","allPagesHere","messages","length","Object","keys","messageString","message","UI","alert","DesignSystemTokens","colours","typography","render","generateTextStyles","json","typeStyles","Array","item","map","align","index","split","textColor","Style","colorToString","checkMatch","baseStyle","newStyle","prop","value","JSON","stringify","generateJSONStyles","arrayFormat","refinedBreakpoints","currentStyle","adjustmentLength","checked","formattedTokens","key","save","filename","fileContents","console","log","targetFile","path","resolve","fs","writeFileSync","designTokens","options","textSaveSelection","Sketch","getInputFromUser","type","INPUT_TYPE","selection","possibleValues","err","textSaveMethod","arranged","saveDialog","dialog","showSaveDialog","defaultPath","then","result","cancelled","filePath","jsonFormat","showMessage"],"mappings":";;;;;;;;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;AClFA;AACA;;AAEA;AACA,kBAAkB,mBAAO,CAAC,qEAAe;AACzC,sBAAsB,mBAAO,CAAC,qEAAe;AAC7C,kBAAkB,mBAAO,CAAC,qEAAe;AACzC,sBAAsB,mBAAO,CAAC,qEAAe;AAC7C,kBAAkB,mBAAO,CAAC,qEAAe;AACzC,sBAAsB,mBAAO,CAAC,qEAAe;AAC7C;AACA;;;;;;;;;;;;ACXA;AACA,YAAY,mBAAO,CAAC,yDAAS;;AAE7B;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;;;;;;;;;;;ACnIA;AACA,YAAY,mBAAO,CAAC,yDAAS;;AAE7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,iBAAiB;AACtC;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,qBAAqB,iBAAiB;AACtC;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;;;;;;;;;;;AClHA;AACA,YAAY,mBAAO,CAAC,yDAAS;;AAE7B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;;AAEL;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;;;;;;;;;;;ACrGA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,OAAO;AACP;AACA,GAAG;AACH;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;;;;;;;;;;;;;AC9DA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,mBAAmB,OAAO;AAC1B;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,iBAAiB,kBAAkB;AACnC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,+BAA+B,sDAAsD;AACrF,mCAAmC,0DAA0D;AAC7F,6BAA6B,mDAAmD;AAChF,wBAAwB,eAAe;AACvC,wBAAwB,iDAAiD;AACzE,0BAA0B,gDAAgD;AAC1E,gCAAgC,sDAAsD;AACtF;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;;;;;;AC/UA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,sBAAsB,mBAAO,CAAC,yEAAoB;;AAElD;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iBAAiB,kBAAkB;AACnC;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA,sCAAsC,8BAA8B;AACpE;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,mBAAmB,sBAAsB;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;;AAEA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA,UAAU,yBAAyB;AACnC;AACA;AACA;AACA;;AAEA;AACA;AACA,UAAU,qBAAqB;AAC/B;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,UAAU,aAAa;AACvB;AACA;AACA;AACA;AACA,4CAA4C;AAC5C;AACA,WAAW;AACX;AACA,qCAAqC;AACrC;AACA;AACA,SAAS;AACT;AACA;AACA,gDAAgD;AAChD;AACA,WAAW;AACX;AACA,wCAAwC;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,2CAA2C,cAAc;AACzD;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC,QAAQ;AACzC;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,+BAA+B,QAAQ;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL,+BAA+B,QAAQ;AACvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iCAAiC,QAAQ;AACzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,UAAU,YAAY;AACtB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;;;;;;AC3gBA,WAAW,mBAAO,CAAC,kBAAM;;AAEzB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;AC7BA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;;AAEA;AACA;AACA,WAAW,SAAS;AACpB;AACA;AACA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,aAAa,SAAS;AACtB;AACA,aAAa,kBAAkB;AAC/B;AACA,aAAa,kBAAkB;AAC/B;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA,+CAA+C,SAAS;AACxD;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA,mBAAmB,iBAAiB;AACpC;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;;AAEA,qCAAqC,SAAS;AAC9C;AACA;AACA,GAAG;AACH;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;;;;;;;;;;;AC9QA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,UAAU,sBAAsB;AAChC,YAAY;AACZ,GAAG;AACH;AACA;AACA,GAAG;AACH,wBAAwB,kCAAkC,EAAE;AAC5D,0BAA0B,gBAAgB;AAC1C,uCAAuC,kDAAkD;;AAEzF;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,0B;;AAEA;AACA,iBAAiB,iBAAiB;AAClC;;AAEA;AACA,aAAa;AACb;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,c;AACA,K;AACA;;AAEA;AACA;AACA;AACA,4CAA4C,4BAA4B,EAAE;AAC1E;AACA,kCAAkC;;AAElC;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;;;;;;;;;;;;;AC5EA;AACA;;AAEA,SAASA,yBAAT,CAAmCC,MAAnC,EAA2C;AACzC,MAAMC,GAAG,GAAGC,IAAI,CAACC,KAAL,CAAWH,MAAM,CAACC,GAAP,KAAe,GAA1B,CAAZ;AACA,MAAMG,KAAK,GAAGF,IAAI,CAACC,KAAL,CAAWH,MAAM,CAACI,KAAP,KAAiB,GAA5B,CAAd;AACA,MAA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","file":"__renderJSON.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/renderJSON.js\");\n","/* let's try to match the API from Electron's Dialog\n(https://github.com/electron/electron/blob/master/docs/api/dialog.md) */\n\nmodule.exports = {\n showOpenDialog: require('./open-dialog').openDialog,\n showOpenDialogSync: require('./open-dialog').openDialogSync,\n showSaveDialog: require('./save-dialog').saveDialog,\n showSaveDialogSync: require('./save-dialog').saveDialogSync,\n showMessageBox: require('./message-box').messageBox,\n showMessageBoxSync: require('./message-box').messageBoxSync,\n // showErrorBox: require('./error-box'),\n}\n","/* eslint-disable no-not-accumulator-reassign/no-not-accumulator-reassign */\nvar utils = require('./utils')\n\nvar typeMap = {\n none: 0,\n info: 1,\n error: 2,\n question: 1,\n warning: 2,\n}\n\nfunction setupOptions(document, options) {\n if (\n !document ||\n (typeof document.isKindOfClass !== 'function' && !document.sketchObject)\n ) {\n options = document\n document = undefined\n } else if (document.sketchObject) {\n document = document.sketchObject\n }\n if (!options) {\n options = {}\n }\n\n var dialog = NSAlert.alloc().init()\n\n if (options.type) {\n dialog.alertStyle = typeMap[options.type] || 0\n }\n\n if (options.buttons && options.buttons.length) {\n options.buttons.forEach(function addButton(button) {\n dialog.addButtonWithTitle(\n options.normalizeAccessKeys ? button.replace(/&/g, '') : button\n )\n // TODO: add keyboard shortcut if options.normalizeAccessKeys\n })\n }\n\n if (typeof options.defaultId !== 'undefined') {\n var buttons = dialog.buttons()\n if (options.defaultId < buttons.length) {\n // Focus the button at defaultId if the user opted to do so.\n // The first button added gets set as the default selected.\n // So remove that default, and make the requested button the default.\n buttons[0].setKeyEquivalent('')\n buttons[options.defaultId].setKeyEquivalent('\\r')\n }\n }\n\n if (options.title) {\n // not shown on macOS\n }\n\n if (options.message) {\n dialog.messageText = options.message\n }\n\n if (options.detail) {\n dialog.informativeText = options.detail\n }\n\n if (options.checkboxLabel) {\n dialog.showsSuppressionButton = true\n dialog.suppressionButton().title = options.checkboxLabel\n\n if (typeof options.checkboxChecked !== 'undefined') {\n dialog.suppressionButton().state = options.checkboxChecked\n ? NSOnState\n : NSOffState\n }\n }\n\n if (options.icon) {\n if (typeof options.icon === 'string') {\n options.icon = NSImage.alloc().initWithContentsOfFile(options.icon)\n }\n dialog.icon = options.icon\n } else if (\n typeof __command !== 'undefined' &&\n __command.pluginBundle() &&\n __command.pluginBundle().icon()\n ) {\n dialog.icon = __command.pluginBundle().icon()\n } else {\n var icon = NSImage.imageNamed('plugins')\n if (icon) {\n dialog.icon = icon\n }\n }\n\n return {\n document: document,\n options: options,\n dialog: dialog,\n }\n}\n\n// https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowmessageboxbrowserwindow-options\nmodule.exports.messageBox = function messageBox(document, options) {\n var setup = setupOptions(document, options)\n\n return utils.runDialog(\n setup.dialog,\n function getResult(_dialog, returnCode) {\n return {\n response:\n setup.options.buttons && setup.options.buttons.length\n ? Number(returnCode) - 1000\n : Number(returnCode),\n checkboxChecked: _dialog.suppressionButton().state() == NSOnState,\n }\n },\n setup.document\n )\n}\n\n// https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowmessageboxsyncbrowserwindow-options\nmodule.exports.messageBoxSync = function messageBoxSync(document, options) {\n var setup = setupOptions(document, options)\n\n return utils.runDialogSync(\n setup.dialog,\n function getResult(_dialog, returnCode) {\n return setup.options.buttons && setup.options.buttons.length\n ? Number(returnCode) - 1000\n : Number(returnCode)\n },\n setup.document\n )\n}\n","/* eslint-disable no-not-accumulator-reassign/no-not-accumulator-reassign */\nvar utils = require('./utils')\n\nfunction setupOptions(document, options) {\n if (\n !document ||\n (typeof document.isKindOfClass !== 'function' && !document.sketchObject)\n ) {\n options = document\n document = undefined\n }\n if (!options) {\n options = {}\n }\n\n var dialog = NSOpenPanel.openPanel()\n\n if (options.title) {\n dialog.title = options.title\n }\n\n if (options.defaultPath) {\n dialog.setDirectoryURL(utils.getURL(options.defaultPath))\n }\n\n if (options.buttonLabel) {\n dialog.prompt = options.buttonLabel\n }\n\n if (options.filters && options.filters.length) {\n var exts = []\n options.filters.forEach(function setFilter(filter) {\n filter.extensions.forEach(function setExtension(ext) {\n exts.push(ext)\n })\n })\n\n dialog.allowedFileTypes = exts\n }\n\n var hasProperty =\n Array.isArray(options.properties) && options.properties.length > 0\n dialog.canChooseFiles =\n hasProperty && options.properties.indexOf('openFile') !== -1\n dialog.canChooseDirectories =\n hasProperty && options.properties.indexOf('openDirectory') !== -1\n dialog.allowsMultipleSelection =\n hasProperty && options.properties.indexOf('multiSelections') !== -1\n dialog.showsHiddenFiles =\n hasProperty && options.properties.indexOf('showHiddenFiles') !== -1\n dialog.canCreateDirectories =\n hasProperty && options.properties.indexOf('createDirectory') !== -1\n dialog.resolvesAliases =\n !hasProperty || options.properties.indexOf('noResolveAliases') === -1\n dialog.treatsFilePackagesAsDirectories =\n hasProperty && options.properties.indexOf('treatPackageAsDirectory') !== -1\n\n if (options.message) {\n dialog.message = options.message\n }\n\n return {\n document: document,\n options: options,\n dialog: dialog,\n }\n}\n\n// https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowopendialogbrowserwindow-options\nmodule.exports.openDialog = function openDialog(document, options) {\n var setup = setupOptions(document, options)\n\n return utils.runDialog(\n setup.dialog,\n function getResult(_dialog, returnCode) {\n if (returnCode != NSOKButton) {\n return {\n canceled: true,\n filePaths: [],\n }\n }\n var result = []\n var urls = _dialog.URLs()\n for (var k = 0; k < urls.length; k += 1) {\n result.push(String(urls[k].path()))\n }\n return {\n canceled: false,\n filePaths: result,\n }\n },\n setup.document\n )\n}\n\n// https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowopendialogsyncbrowserwindow-options\nmodule.exports.openDialogSync = function openDialogSync(document, options) {\n var setup = setupOptions(document, options)\n\n return utils.runDialogSync(\n setup.dialog,\n function getResult(_dialog, returnCode) {\n if (returnCode != NSOKButton) {\n return []\n }\n var result = []\n var urls = _dialog.URLs()\n for (var k = 0; k < urls.length; k += 1) {\n result.push(String(urls[k].path()))\n }\n return result\n },\n setup.document\n )\n}\n","/* eslint-disable no-not-accumulator-reassign/no-not-accumulator-reassign */\nvar utils = require('./utils')\n\nfunction setupOptions(document, options) {\n if (\n !document ||\n (typeof document.isKindOfClass !== 'function' && !document.sketchObject)\n ) {\n options = document\n document = undefined\n }\n if (!options) {\n options = {}\n }\n\n var dialog = NSSavePanel.savePanel()\n\n if (options.title) {\n dialog.title = options.title\n }\n\n if (options.defaultPath) {\n // that's a path\n dialog.setDirectoryURL(utils.getURL(options.defaultPath))\n\n if (\n options.defaultPath[0] === '.' ||\n options.defaultPath[0] === '~' ||\n options.defaultPath[0] === '/'\n ) {\n var parts = options.defaultPath.split('/')\n if (parts.length > 1 && parts[parts.length - 1]) {\n dialog.setNameFieldStringValue(parts[parts.length - 1])\n }\n } else {\n dialog.setNameFieldStringValue(options.defaultPath)\n }\n }\n\n if (options.buttonLabel) {\n dialog.prompt = options.buttonLabel\n }\n\n if (options.filters && options.filters.length) {\n var exts = []\n options.filters.forEach(function setFilter(filter) {\n filter.extensions.forEach(function setExtension(ext) {\n exts.push(ext)\n })\n })\n\n dialog.allowedFileTypes = exts\n }\n\n if (options.message) {\n dialog.message = options.message\n }\n\n if (options.nameFieldLabel) {\n dialog.nameFieldLabel = options.nameFieldLabel\n }\n\n if (options.showsTagField) {\n dialog.showsTagField = options.showsTagField\n }\n\n return {\n document: document,\n options: options,\n dialog: dialog,\n }\n}\n\n// https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowsavedialogbrowserwindow-options\nmodule.exports.saveDialog = function saveDialog(document, options) {\n var setup = setupOptions(document, options)\n\n return utils.runDialog(\n setup.dialog,\n function getResult(_dialog, returnCode) {\n return {\n canceled: returnCode != NSOKButton,\n filePath:\n returnCode == NSOKButton ? String(_dialog.URL().path()) : undefined,\n }\n },\n setup.document\n )\n}\n\n// https://github.com/electron/electron/blob/master/docs/api/dialog.md#dialogshowsavedialogsyncbrowserwindow-options\nmodule.exports.saveDialogSync = function saveDialogSync(document, options) {\n var setup = setupOptions(document, options)\n\n return utils.runDialogSync(\n setup.dialog,\n function getResult(_dialog, returnCode) {\n return returnCode == NSOKButton ? String(_dialog.URL().path()) : undefined\n },\n setup.document\n )\n}\n","module.exports.getURL = function getURL(path) {\n return NSURL.URLWithString(\n String(\n NSString.stringWithString(path).stringByExpandingTildeInPath()\n ).replace(/ /g, '%20')\n )\n}\n\nmodule.exports.runDialog = function runDialog(dialog, getResult, document) {\n if (!document) {\n var returnCode = dialog.runModal()\n return Promise.resolve(getResult(dialog, returnCode))\n }\n\n var fiber = coscript.createFiber()\n\n var window = (document.sketchObject || document).documentWindow()\n\n return new Promise(function p(resolve, reject) {\n dialog.beginSheetModalForWindow_completionHandler(\n window,\n __mocha__.createBlock_function('v16@?0q8', function onCompletion(\n _returnCode\n ) {\n try {\n resolve(getResult(dialog, _returnCode))\n } catch (err) {\n reject(err)\n }\n NSApp.endSheet(dialog)\n if (fiber) {\n fiber.cleanup()\n } else {\n coscript.shouldKeepAround = false\n }\n })\n )\n })\n}\n\nmodule.exports.runDialogSync = function runDialog(dialog, getResult, document) {\n var returnCode\n\n if (!document) {\n returnCode = dialog.runModal()\n return getResult(dialog, returnCode)\n }\n\n var window = (document.sketchObject || document).documentWindow()\n\n dialog.beginSheetModalForWindow_completionHandler(\n window,\n __mocha__.createBlock_function('v16@?0q8', function onCompletion(\n _returnCode\n ) {\n NSApp.stopModalWithCode(_returnCode)\n })\n )\n\n returnCode = NSApp.runModalForWindow(window)\n NSApp.endSheet(dialog)\n return getResult(dialog, returnCode)\n}\n","// TODO: async. Should probably be done with NSFileHandle and some notifications\n// TODO: file descriptor. Needs to be done with NSFileHandle\n\nmodule.exports.constants = {\n F_OK: 0,\n R_OK: 4,\n W_OK: 2,\n X_OK: 1\n}\n\nmodule.exports.accessSync = function(path, mode) {\n mode = mode | 0\n var fileManager = NSFileManager.defaultManager()\n\n switch (mode) {\n case 0:\n return module.exports.existsSync(path)\n case 1:\n return Boolean(fileManager.isExecutableFileAtPath(path))\n case 2:\n return Boolean(fileManager.isWritableFileAtPath(path))\n case 3:\n return Boolean(fileManager.isExecutableFileAtPath(path) && fileManager.isWritableFileAtPath(path))\n case 4:\n return Boolean(fileManager.isReadableFileAtPath(path))\n case 5:\n return Boolean(fileManager.isReadableFileAtPath(path) && fileManager.isExecutableFileAtPath(path))\n case 6:\n return Boolean(fileManager.isReadableFileAtPath(path) && fileManager.isWritableFileAtPath(path))\n case 7:\n return Boolean(fileManager.isReadableFileAtPath(path) && fileManager.isWritableFileAtPath(path) && fileManager.isExecutableFileAtPath(path))\n }\n}\n\nmodule.exports.appendFileSync = function(file, data, options) {\n if (!module.exports.existsSync(file)) {\n return module.exports.writeFileSync(file, data, options)\n }\n\n var handle = NSFileHandle.fileHandleForWritingAtPath(file)\n handle.seekToEndOfFile()\n\n if (data && data.mocha && data.mocha().class() === 'NSData') {\n handle.writeData(data)\n return\n }\n\n var encoding = options && options.encoding ? options.encoding : (options ? options : 'utf8')\n\n var string = NSString.stringWithString(data)\n var nsdata\n\n switch (encoding) {\n case 'utf8':\n nsdata = string.dataUsingEncoding(NSUTF8StringEncoding)\n break\n case 'ascii':\n nsdata = string.dataUsingEncoding(NSASCIIStringEncoding)\n break\n case 'utf16le':\n case 'ucs2':\n nsdata = string.dataUsingEncoding(NSUTF16LittleEndianStringEncoding)\n break\n case 'base64':\n var plainData = string.dataUsingEncoding(NSUTF8StringEncoding)\n nsdata = plainData.base64EncodedStringWithOptions(0).dataUsingEncoding(NSUTF8StringEncoding)\n break\n case 'latin1':\n case 'binary':\n nsdata = string.dataUsingEncoding(NSISOLatin1StringEncoding)\n break\n case 'hex':\n // TODO: how?\n default:\n nsdata = string.dataUsingEncoding(NSUTF8StringEncoding)\n break\n }\n\n handle.writeData(data)\n}\n\nmodule.exports.chmodSync = function(path, mode) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n fileManager.setAttributes_ofItemAtPath_error({\n NSFilePosixPermissions: mode\n }, path, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.copyFileSync = function(path, dest, flags) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n fileManager.copyItemAtPath_toPath_error(path, dest, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.existsSync = function(path) {\n var fileManager = NSFileManager.defaultManager()\n return Boolean(fileManager.fileExistsAtPath(path))\n}\n\nmodule.exports.linkSync = function(existingPath, newPath) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n fileManager.linkItemAtPath_toPath_error(existingPath, newPath, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.mkdirSync = function(path, mode) {\n mode = mode || 0o777\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n fileManager.createDirectoryAtPath_withIntermediateDirectories_attributes_error(path, false, {\n NSFilePosixPermissions: mode\n }, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.mkdtempSync = function(path) {\n function makeid() {\n var text = \"\";\n var possible = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n\n for (var i = 0; i < 6; i++)\n text += possible.charAt(Math.floor(Math.random() * possible.length));\n\n return text;\n }\n var tempPath = path + makeid()\n module.exports.mkdirSync(tempPath)\n return tempPath\n}\n\nmodule.exports.readdirSync = function(path) {\n var fileManager = NSFileManager.defaultManager()\n var paths = fileManager.subpathsAtPath(path)\n var arr = []\n for (var i = 0; i < paths.length; i++) {\n arr.push(paths[i])\n }\n return arr\n}\n\nmodule.exports.readFileSync = function(path, options) {\n var encoding = options && options.encoding ? options.encoding : (options ? options : 'buffer')\n var fileManager = NSFileManager.defaultManager()\n var data = fileManager.contentsAtPath(path)\n switch (encoding) {\n case 'utf8':\n return String(NSString.alloc().initWithData_encoding(data, NSUTF8StringEncoding))\n case 'ascii':\n return String(NSString.alloc().initWithData_encoding(data, NSASCIIStringEncoding))\n case 'utf16le':\n case 'ucs2':\n return String(NSString.alloc().initWithData_encoding(data, NSUTF16LittleEndianStringEncoding))\n case 'base64':\n var nsdataDecoded = NSData.alloc().initWithBase64EncodedData_options(data, 0)\n return String(NSString.alloc().initWithData_encoding(nsdataDecoded, NSUTF8StringEncoding))\n case 'latin1':\n case 'binary':\n return String(NSString.alloc().initWithData_encoding(data, NSISOLatin1StringEncoding))\n case 'hex':\n // TODO: how?\n return data\n default:\n return data\n }\n}\n\nmodule.exports.readlinkSync = function(path) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n var result = fileManager.destinationOfSymbolicLinkAtPath_error(path, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n\n return result\n}\n\nmodule.exports.realpathSync = function(path) {\n return NSString.stringByResolvingSymlinksInPath(path)\n}\n\nmodule.exports.renameSync = function(oldPath, newPath) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n fileManager.moveItemAtPath_toPath_error(oldPath, newPath, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.rmdirSync = function(path) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n fileManager.removeItemAtPath_error(path, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.statSync = function(path) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n var result = fileManager.attributesOfItemAtPath_error(path, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n\n return {\n dev: String(result.NSFileDeviceIdentifier),\n // ino: 48064969, The file system specific \"Inode\" number for the file.\n mode: result.NSFileType | result.NSFilePosixPermissions,\n nlink: Number(result.NSFileReferenceCount),\n uid: String(result.NSFileOwnerAccountID),\n gid: String(result.NSFileGroupOwnerAccountID),\n // rdev: 0, A numeric device identifier if the file is considered \"special\".\n size: Number(result.NSFileSize),\n // blksize: 4096, The file system block size for i/o operations.\n // blocks: 8, The number of blocks allocated for this file.\n atimeMs: Number(result.NSFileModificationDate.timeIntervalSince1970()) * 1000,\n mtimeMs: Number(result.NSFileModificationDate.timeIntervalSince1970()) * 1000,\n ctimeMs: Number(result.NSFileModificationDate.timeIntervalSince1970()) * 1000,\n birthtimeMs: Number(result.NSFileCreationDate.timeIntervalSince1970()) * 1000,\n atime: new Date(Number(result.NSFileModificationDate.timeIntervalSince1970()) * 1000 + 0.5), // the 0.5 comes from the node source. Not sure why it's added but in doubt...\n mtime: new Date(Number(result.NSFileModificationDate.timeIntervalSince1970()) * 1000 + 0.5),\n ctime: new Date(Number(result.NSFileModificationDate.timeIntervalSince1970()) * 1000 + 0.5),\n birthtime: new Date(Number(result.NSFileCreationDate.timeIntervalSince1970()) * 1000 + 0.5),\n isBlockDevice: function() { return result.NSFileType === NSFileTypeBlockSpecial },\n isCharacterDevice: function() { return result.NSFileType === NSFileTypeCharacterSpecial },\n isDirectory: function() { return result.NSFileType === NSFileTypeDirectory },\n isFIFO: function() { return false },\n isFile: function() { return result.NSFileType === NSFileTypeRegular },\n isSocket: function() { return result.NSFileType === NSFileTypeSocket },\n isSymbolicLink: function() { return result.NSFileType === NSFileTypeSymbolicLink },\n }\n}\n\nmodule.exports.symlinkSync = function(target, path) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n var result = fileManager.createSymbolicLinkAtPath_withDestinationPath_error(path, target, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.truncateSync = function(path, len) {\n var hFile = NSFileHandle.fileHandleForUpdatingAtPath(sFilePath)\n hFile.truncateFileAtOffset(len || 0)\n hFile.closeFile()\n}\n\nmodule.exports.unlinkSync = function(path) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n var result = fileManager.removeItemAtPath_error(path, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.utimesSync = function(path, aTime, mTime) {\n var err = MOPointer.alloc().init()\n var fileManager = NSFileManager.defaultManager()\n var result = fileManager.setAttributes_ofItemAtPath_error({\n NSFileModificationDate: aTime\n }, path, err)\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n\nmodule.exports.writeFileSync = function(path, data, options) {\n var encoding = options && options.encoding ? options.encoding : (options ? options : 'utf8')\n\n if (data && data.mocha && data.mocha().class() === 'NSData') {\n data.writeToFile_atomically(path, true)\n return\n }\n\n var err = MOPointer.alloc().init()\n var string = NSString.stringWithString(data)\n\n switch (encoding) {\n case 'utf8':\n string.writeToFile_atomically_encoding_error(path, true, NSUTF8StringEncoding, err)\n break\n case 'ascii':\n string.writeToFile_atomically_encoding_error(path, true, NSASCIIStringEncoding, err)\n break\n case 'utf16le':\n case 'ucs2':\n string.writeToFile_atomically_encoding_error(path, true, NSUTF16LittleEndianStringEncoding, err)\n break\n case 'base64':\n var plainData = string.dataUsingEncoding(NSUTF8StringEncoding)\n var nsdataEncoded = plainData.base64EncodedStringWithOptions(0)\n nsdataEncoded.writeToFile_atomically(path, true)\n break\n case 'latin1':\n case 'binary':\n string.writeToFile_atomically_encoding_error(path, true, NSISOLatin1StringEncoding, err)\n break\n case 'hex':\n // TODO: how?\n default:\n string.writeToFile_atomically_encoding_error(path, true, NSUTF8StringEncoding, err)\n break\n }\n\n if (err.value() !== null) {\n throw new Error(err.value())\n }\n}\n","// Copyright Joyent, Inc. and other Node contributors.\n//\n// Permission is hereby granted, free of charge, to any person obtaining a\n// copy of this software and associated documentation files (the\n// \"Software\"), to deal in the Software without restriction, including\n// without limitation the rights to use, copy, modify, merge, publish,\n// distribute, sublicense, and/or sell copies of the Software, and to permit\n// persons to whom the Software is furnished to do so, subject to the\n// following conditions:\n//\n// The above copyright notice and this permission notice shall be included\n// in all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\n// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN\n// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,\n// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR\n// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE\n// USE OR OTHER DEALINGS IN THE SOFTWARE.\n\nvar sketchSpecifics = require('./sketch-specifics')\n\n// we only expose the posix implementation since Sketch only runs on macOS\n\nvar CHAR_FORWARD_SLASH = 47\nvar CHAR_DOT = 46\n\n// Resolves . and .. elements in a path with directory names\nfunction normalizeString(path, allowAboveRoot) {\n var res = ''\n var lastSegmentLength = 0\n var lastSlash = -1\n var dots = 0\n var code\n for (var i = 0; i <= path.length; i += 1) {\n if (i < path.length) code = path.charCodeAt(i)\n else if (code === CHAR_FORWARD_SLASH) break\n else code = CHAR_FORWARD_SLASH\n if (code === CHAR_FORWARD_SLASH) {\n if (lastSlash === i - 1 || dots === 1) {\n // NOOP\n } else if (lastSlash !== i - 1 && dots === 2) {\n if (\n res.length < 2 ||\n lastSegmentLength !== 2 ||\n res.charCodeAt(res.length - 1) !== CHAR_DOT ||\n res.charCodeAt(res.length - 2) !== CHAR_DOT\n ) {\n if (res.length > 2) {\n var lastSlashIndex = res.lastIndexOf('/')\n if (lastSlashIndex !== res.length - 1) {\n if (lastSlashIndex === -1) {\n res = ''\n lastSegmentLength = 0\n } else {\n res = res.slice(0, lastSlashIndex)\n lastSegmentLength = res.length - 1 - res.lastIndexOf('/')\n }\n lastSlash = i\n dots = 0\n continue\n }\n } else if (res.length === 2 || res.length === 1) {\n res = ''\n lastSegmentLength = 0\n lastSlash = i\n dots = 0\n continue\n }\n }\n if (allowAboveRoot) {\n if (res.length > 0) res += '/..'\n else res = '..'\n lastSegmentLength = 2\n }\n } else {\n if (res.length > 0) res += '/' + path.slice(lastSlash + 1, i)\n else res = path.slice(lastSlash + 1, i)\n lastSegmentLength = i - lastSlash - 1\n }\n lastSlash = i\n dots = 0\n } else if (code === CHAR_DOT && dots !== -1) {\n ++dots\n } else {\n dots = -1\n }\n }\n return res\n}\n\nfunction _format(sep, pathObject) {\n var dir = pathObject.dir || pathObject.root\n var base =\n pathObject.base || (pathObject.name || '') + (pathObject.ext || '')\n if (!dir) {\n return base\n }\n if (dir === pathObject.root) {\n return dir + base\n }\n return dir + sep + base\n}\n\nvar posix = {\n // path.resolve([from ...], to)\n resolve: function resolve() {\n var resolvedPath = ''\n var resolvedAbsolute = false\n var cwd\n\n for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i -= 1) {\n var path\n if (i >= 0) {\n path = arguments[i]\n } else {\n if (cwd === undefined) {\n cwd = posix.dirname(sketchSpecifics.cwd())\n }\n path = cwd\n }\n\n path = sketchSpecifics.getString(path, 'path')\n\n // Skip empty entries\n if (path.length === 0) {\n continue\n }\n\n resolvedPath = path + '/' + resolvedPath\n resolvedAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH\n }\n\n // At this point the path should be resolved to a full absolute path, but\n // handle relative paths to be safe (might happen when process.cwd() fails)\n\n // Normalize the path\n resolvedPath = normalizeString(resolvedPath, !resolvedAbsolute)\n\n if (resolvedAbsolute) {\n if (resolvedPath.length > 0) return '/' + resolvedPath\n else return '/'\n } else if (resolvedPath.length > 0) {\n return resolvedPath\n } else {\n return '.'\n }\n },\n\n normalize: function normalize(path) {\n path = sketchSpecifics.getString(path, 'path')\n\n if (path.length === 0) return '.'\n\n var isAbsolute = path.charCodeAt(0) === CHAR_FORWARD_SLASH\n var trailingSeparator =\n path.charCodeAt(path.length - 1) === CHAR_FORWARD_SLASH\n\n // Normalize the path\n path = normalizeString(path, !isAbsolute)\n\n if (path.length === 0 && !isAbsolute) path = '.'\n if (path.length > 0 && trailingSeparator) path += '/'\n\n if (isAbsolute) return '/' + path\n return path\n },\n\n isAbsolute: function isAbsolute(path) {\n path = sketchSpecifics.getString(path, 'path')\n return path.length > 0 && path.charCodeAt(0) === CHAR_FORWARD_SLASH\n },\n\n join: function join() {\n if (arguments.length === 0) return '.'\n var joined\n for (var i = 0; i < arguments.length; i += 1) {\n var arg = arguments[i]\n arg = sketchSpecifics.getString(arg, 'path')\n if (arg.length > 0) {\n if (joined === undefined) joined = arg\n else joined += '/' + arg\n }\n }\n if (joined === undefined) return '.'\n return posix.normalize(joined)\n },\n\n relative: function relative(from, to) {\n from = sketchSpecifics.getString(from, 'from path')\n to = sketchSpecifics.getString(to, 'to path')\n\n if (from === to) return ''\n\n from = posix.resolve(from)\n to = posix.resolve(to)\n\n if (from === to) return ''\n\n // Trim any leading backslashes\n var fromStart = 1\n for (; fromStart < from.length; fromStart += 1) {\n if (from.charCodeAt(fromStart) !== CHAR_FORWARD_SLASH) break\n }\n var fromEnd = from.length\n var fromLen = fromEnd - fromStart\n\n // Trim any leading backslashes\n var toStart = 1\n for (; toStart < to.length; toStart += 1) {\n if (to.charCodeAt(toStart) !== CHAR_FORWARD_SLASH) break\n }\n var toEnd = to.length\n var toLen = toEnd - toStart\n\n // Compare paths to find the longest common path from root\n var length = fromLen < toLen ? fromLen : toLen\n var lastCommonSep = -1\n var i = 0\n for (; i <= length; i += 1) {\n if (i === length) {\n if (toLen > length) {\n if (to.charCodeAt(toStart + i) === CHAR_FORWARD_SLASH) {\n // We get here if `from` is the exact base path for `to`.\n // For example: from='/foo/bar'; to='/foo/bar/baz'\n return to.slice(toStart + i + 1)\n } else if (i === 0) {\n // We get here if `from` is the root\n // For example: from='/'; to='/foo'\n return to.slice(toStart + i)\n }\n } else if (fromLen > length) {\n if (from.charCodeAt(fromStart + i) === CHAR_FORWARD_SLASH) {\n // We get here if `to` is the exact base path for `from`.\n // For example: from='/foo/bar/baz'; to='/foo/bar'\n lastCommonSep = i\n } else if (i === 0) {\n // We get here if `to` is the root.\n // For example: from='/foo'; to='/'\n lastCommonSep = 0\n }\n }\n break\n }\n var fromCode = from.charCodeAt(fromStart + i)\n var toCode = to.charCodeAt(toStart + i)\n if (fromCode !== toCode) break\n else if (fromCode === CHAR_FORWARD_SLASH) lastCommonSep = i\n }\n\n var out = ''\n // Generate the relative path based on the path difference between `to`\n // and `from`\n for (i = fromStart + lastCommonSep + 1; i <= fromEnd; i += 1) {\n if (i === fromEnd || from.charCodeAt(i) === CHAR_FORWARD_SLASH) {\n if (out.length === 0) out += '..'\n else out += '/..'\n }\n }\n\n // Lastly, append the rest of the destination (`to`) path that comes after\n // the common path parts\n if (out.length > 0) return out + to.slice(toStart + lastCommonSep)\n else {\n toStart += lastCommonSep\n if (to.charCodeAt(toStart) === CHAR_FORWARD_SLASH) toStart += 1\n return to.slice(toStart)\n }\n },\n\n toNamespacedPath: function toNamespacedPath(path) {\n // Non-op on posix systems\n return path\n },\n\n dirname: function dirname(path) {\n path = sketchSpecifics.getString(path, 'path')\n if (path.length === 0) return '.'\n var code = path.charCodeAt(0)\n var hasRoot = code === CHAR_FORWARD_SLASH\n var end = -1\n var matchedSlash = true\n for (var i = path.length - 1; i >= 1; i -= 1) {\n code = path.charCodeAt(i)\n if (code === CHAR_FORWARD_SLASH) {\n if (!matchedSlash) {\n end = i\n break\n }\n } else {\n // We saw the first non-path separator\n matchedSlash = false\n }\n }\n\n if (end === -1) return hasRoot ? '/' : '.'\n if (hasRoot && end === 1) return '//'\n return path.slice(0, end)\n },\n\n basename: function basename(path, ext) {\n if (ext !== undefined)\n ext = sketchSpecifics.getString(ext, 'ext')\n path = sketchSpecifics.getString(path, 'path')\n\n var start = 0\n var end = -1\n var matchedSlash = true\n var i\n\n if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {\n if (ext.length === path.length && ext === path) return ''\n var extIdx = ext.length - 1\n var firstNonSlashEnd = -1\n for (i = path.length - 1; i >= 0; i -= 1) {\n var code = path.charCodeAt(i)\n if (code === CHAR_FORWARD_SLASH) {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n start = i + 1\n break\n }\n } else {\n if (firstNonSlashEnd === -1) {\n // We saw the first non-path separator, remember this index in case\n // we need it if the extension ends up not matching\n matchedSlash = false\n firstNonSlashEnd = i + 1\n }\n if (extIdx >= 0) {\n // Try to match the explicit extension\n if (code === ext.charCodeAt(extIdx)) {\n if (--extIdx === -1) {\n // We matched the extension, so mark this as the end of our path\n // component\n end = i\n }\n } else {\n // Extension does not match, so our result is the entire path\n // component\n extIdx = -1\n end = firstNonSlashEnd\n }\n }\n }\n }\n\n if (start === end) end = firstNonSlashEnd\n else if (end === -1) end = path.length\n return path.slice(start, end)\n } else {\n for (i = path.length - 1; i >= 0; --i) {\n if (path.charCodeAt(i) === CHAR_FORWARD_SLASH) {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n start = i + 1\n break\n }\n } else if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // path component\n matchedSlash = false\n end = i + 1\n }\n }\n\n if (end === -1) return ''\n return path.slice(start, end)\n }\n },\n\n extname: function extname(path) {\n path = sketchSpecifics.getString(path, 'path')\n var startDot = -1\n var startPart = 0\n var end = -1\n var matchedSlash = true\n // Track the state of characters (if any) we see before our first dot and\n // after any path separator we find\n var preDotState = 0\n for (var i = path.length - 1; i >= 0; --i) {\n var code = path.charCodeAt(i)\n if (code === CHAR_FORWARD_SLASH) {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n startPart = i + 1\n break\n }\n continue\n }\n if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // extension\n matchedSlash = false\n end = i + 1\n }\n if (code === CHAR_DOT) {\n // If this is our first dot, mark it as the start of our extension\n if (startDot === -1) startDot = i\n else if (preDotState !== 1) preDotState = 1\n } else if (startDot !== -1) {\n // We saw a non-dot and non-path separator before our dot, so we should\n // have a good chance at having a non-empty extension\n preDotState = -1\n }\n }\n\n if (\n startDot === -1 ||\n end === -1 ||\n // We saw a non-dot character immediately before the dot\n preDotState === 0 ||\n // The (right-most) trimmed path component is exactly '..'\n (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)\n ) {\n return ''\n }\n return path.slice(startDot, end)\n },\n\n format: function format(pathObject) {\n if (pathObject === null || typeof pathObject !== 'object') {\n throw new Error('pathObject should be an Object')\n }\n return _format('/', pathObject)\n },\n\n parse: function parse(path) {\n path = sketchSpecifics.getString(path, 'path')\n\n var ret = { root: '', dir: '', base: '', ext: '', name: '' }\n if (path.length === 0) return ret\n var code = path.charCodeAt(0)\n var isAbsolute = code === CHAR_FORWARD_SLASH\n var start\n if (isAbsolute) {\n ret.root = '/'\n start = 1\n } else {\n start = 0\n }\n var startDot = -1\n var startPart = 0\n var end = -1\n var matchedSlash = true\n var i = path.length - 1\n\n // Track the state of characters (if any) we see before our first dot and\n // after any path separator we find\n var preDotState = 0\n\n // Get non-dir info\n for (; i >= start; --i) {\n code = path.charCodeAt(i)\n if (code === CHAR_FORWARD_SLASH) {\n // If we reached a path separator that was not part of a set of path\n // separators at the end of the string, stop now\n if (!matchedSlash) {\n startPart = i + 1\n break\n }\n continue\n }\n if (end === -1) {\n // We saw the first non-path separator, mark this as the end of our\n // extension\n matchedSlash = false\n end = i + 1\n }\n if (code === CHAR_DOT) {\n // If this is our first dot, mark it as the start of our extension\n if (startDot === -1) startDot = i\n else if (preDotState !== 1) preDotState = 1\n } else if (startDot !== -1) {\n // We saw a non-dot and non-path separator before our dot, so we should\n // have a good chance at having a non-empty extension\n preDotState = -1\n }\n }\n\n if (\n startDot === -1 ||\n end === -1 ||\n // We saw a non-dot character immediately before the dot\n preDotState === 0 ||\n // The (right-most) trimmed path component is exactly '..'\n (preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)\n ) {\n if (end !== -1) {\n if (startPart === 0 && isAbsolute)\n ret.base = ret.name = path.slice(1, end)\n else ret.base = ret.name = path.slice(startPart, end)\n }\n } else {\n if (startPart === 0 && isAbsolute) {\n ret.name = path.slice(1, startDot)\n ret.base = path.slice(1, end)\n } else {\n ret.name = path.slice(startPart, startDot)\n ret.base = path.slice(startPart, end)\n }\n ret.ext = path.slice(startDot, end)\n }\n\n if (startPart > 0) ret.dir = path.slice(0, startPart - 1)\n else if (isAbsolute) ret.dir = '/'\n\n return ret\n },\n\n sep: '/',\n delimiter: ':',\n win32: null,\n posix: null,\n\n resourcePath: sketchSpecifics.resourcePath,\n}\n\nmodule.exports = posix\nmodule.exports.posix = posix\n","var util = require('util')\n\nmodule.exports.getString = function getString(path, argumentName) {\n if (!util.isString(path)) {\n // let's make a special case for NSURL\n if (util.getNativeClass(path) === 'NSURL') {\n return String(path.path().copy())\n }\n throw new Error(argumentName + ' should be a string. Got ' + typeof path + ' instead.')\n }\n return String(path)\n}\n\nmodule.exports.cwd = function cwd() {\n if (typeof __command !== 'undefined' && __command.script() && __command.script().URL()) {\n return String(__command.script().URL().path().copy())\n }\n return String(MSPluginManager.defaultPluginURL().path().copy())\n}\n\nmodule.exports.resourcePath = function resourcePath(resourceName) {\n if (typeof __command === 'undefined' || !__command.pluginBundle()) {\n return undefined\n }\n var resource = __command.pluginBundle().urlForResourceNamed(resourceName)\n if (!resource) {\n return undefined\n }\n return String(resource.path())\n}\n","/* from https://github.com/taylorhakes/promise-polyfill */\n\nfunction promiseFinally(callback) {\n var constructor = this.constructor;\n return this.then(\n function(value) {\n return constructor.resolve(callback()).then(function() {\n return value;\n });\n },\n function(reason) {\n return constructor.resolve(callback()).then(function() {\n return constructor.reject(reason);\n });\n }\n );\n}\n\nfunction noop() {}\n\n/**\n * @constructor\n * @param {Function} fn\n */\nfunction Promise(fn) {\n if (!(this instanceof Promise))\n throw new TypeError(\"Promises must be constructed via new\");\n if (typeof fn !== \"function\") throw new TypeError(\"not a function\");\n /** @type {!number} */\n this._state = 0;\n /** @type {!boolean} */\n this._handled = false;\n /** @type {Promise|undefined} */\n this._value = undefined;\n /** @type {!Array} */\n this._deferreds = [];\n\n doResolve(fn, this);\n}\n\nfunction handle(self, deferred) {\n while (self._state === 3) {\n self = self._value;\n }\n if (self._state === 0) {\n self._deferreds.push(deferred);\n return;\n }\n self._handled = true;\n Promise._immediateFn(function() {\n var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;\n if (cb === null) {\n (self._state === 1 ? resolve : reject)(deferred.promise, self._value);\n return;\n }\n var ret;\n try {\n ret = cb(self._value);\n } catch (e) {\n reject(deferred.promise, e);\n return;\n }\n resolve(deferred.promise, ret);\n });\n}\n\nfunction resolve(self, newValue) {\n try {\n // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure\n if (newValue === self)\n throw new TypeError(\"A promise cannot be resolved with itself.\");\n if (\n newValue &&\n (typeof newValue === \"object\" || typeof newValue === \"function\")\n ) {\n var then = newValue.then;\n if (newValue instanceof Promise) {\n self._state = 3;\n self._value = newValue;\n finale(self);\n return;\n } else if (typeof then === \"function\") {\n doResolve(then.bind(newValue), self);\n return;\n }\n }\n self._state = 1;\n self._value = newValue;\n finale(self);\n } catch (e) {\n reject(self, e);\n }\n}\n\nfunction reject(self, newValue) {\n self._state = 2;\n self._value = newValue;\n finale(self);\n}\n\nfunction finale(self) {\n if (self._state === 2 && self._deferreds.length === 0) {\n Promise._immediateFn(function() {\n if (!self._handled) {\n Promise._unhandledRejectionFn(self._value, self);\n }\n });\n }\n\n for (var i = 0, len = self._deferreds.length; i < len; i++) {\n handle(self, self._deferreds[i]);\n }\n self._deferreds = null;\n}\n\n/**\n * @constructor\n */\nfunction Handler(onFulfilled, onRejected, promise) {\n this.onFulfilled = typeof onFulfilled === \"function\" ? onFulfilled : null;\n this.onRejected = typeof onRejected === \"function\" ? onRejected : null;\n this.promise = promise;\n}\n\n/**\n * Take a potentially misbehaving resolver function and make sure\n * onFulfilled and onRejected are only called once.\n *\n * Makes no guarantees about asynchrony.\n */\nfunction doResolve(fn, self) {\n var done = false;\n try {\n fn(\n function(value) {\n if (done) {\n Promise._multipleResolvesFn(\"resolve\", self, value);\n return;\n }\n done = true;\n resolve(self, value);\n },\n function(reason) {\n if (done) {\n Promise._multipleResolvesFn(\"reject\", self, reason);\n return;\n }\n done = true;\n reject(self, reason);\n }\n );\n } catch (ex) {\n if (done) {\n Promise._multipleResolvesFn(\"reject\", self, ex);\n return;\n }\n done = true;\n reject(self, ex);\n }\n}\n\nPromise.prototype[\"catch\"] = function(onRejected) {\n return this.then(null, onRejected);\n};\n\nPromise.prototype.then = function(onFulfilled, onRejected) {\n // @ts-ignore\n var prom = new this.constructor(noop);\n\n handle(this, new Handler(onFulfilled, onRejected, prom));\n return prom;\n};\n\nPromise.prototype[\"finally\"] = promiseFinally;\n\nPromise.all = function(arr) {\n return new Promise(function(resolve, reject) {\n if (!Array.isArray(arr)) {\n return reject(new TypeError(\"Promise.all accepts an array\"));\n }\n\n var args = Array.prototype.slice.call(arr);\n if (args.length === 0) return resolve([]);\n var remaining = args.length;\n\n function res(i, val) {\n try {\n if (val && (typeof val === \"object\" || typeof val === \"function\")) {\n var then = val.then;\n if (typeof then === \"function\") {\n then.call(\n val,\n function(val) {\n res(i, val);\n },\n reject\n );\n return;\n }\n }\n args[i] = val;\n if (--remaining === 0) {\n resolve(args);\n }\n } catch (ex) {\n reject(ex);\n }\n }\n\n for (var i = 0; i < args.length; i++) {\n res(i, args[i]);\n }\n });\n};\n\nPromise.resolve = function(value) {\n if (value && typeof value === \"object\" && value.constructor === Promise) {\n return value;\n }\n\n return new Promise(function(resolve) {\n resolve(value);\n });\n};\n\nPromise.reject = function(value) {\n return new Promise(function(resolve, reject) {\n reject(value);\n });\n};\n\nPromise.race = function(arr) {\n return new Promise(function(resolve, reject) {\n if (!Array.isArray(arr)) {\n return reject(new TypeError(\"Promise.race accepts an array\"));\n }\n\n for (var i = 0, len = arr.length; i < len; i++) {\n Promise.resolve(arr[i]).then(resolve, reject);\n }\n });\n};\n\n// Use polyfill for setImmediate for performance gains\nPromise._immediateFn = setImmediate;\n\nPromise._unhandledRejectionFn = function _unhandledRejectionFn(err, promise) {\n if (\n typeof process !== \"undefined\" &&\n process.listenerCount &&\n (process.listenerCount(\"unhandledRejection\") ||\n process.listenerCount(\"uncaughtException\"))\n ) {\n process.emit(\"unhandledRejection\", err, promise);\n process.emit(\"uncaughtException\", err, \"unhandledRejection\");\n } else if (typeof console !== \"undefined\" && console) {\n console.warn(\"Possible Unhandled Promise Rejection:\", err);\n }\n};\n\nPromise._multipleResolvesFn = function _multipleResolvesFn(\n type,\n promise,\n value\n) {\n if (typeof process !== \"undefined\" && process.emit) {\n process.emit(\"multipleResolves\", type, promise, value);\n }\n};\n\nmodule.exports = Promise;\n","/*\n change for npm modules.\n by Luiz Estácio.\n\n json-format v.1.1\n http://github.com/phoboslab/json-format\n\n Released under MIT license:\n http://www.opensource.org/licenses/mit-license.php\n*/\nvar p = [],\n indentConfig = {\n tab: { char: '\\t', size: 1 },\n space: { char: ' ', size: 4 }\n },\n configDefault = {\n type: 'tab'\n },\n push = function( m ) { return '\\\\' + p.push( m ) + '\\\\'; },\n pop = function( m, i ) { return p[i-1] },\n tabs = function( count, indentType) { return new Array( count + 1 ).join( indentType ); };\n\nfunction JSONFormat ( json, indentType ) {\n p = [];\n var out = \"\",\n indent = 0;\n\n // Extract backslashes and strings\n json = json\n .replace( /\\\\./g, push )\n .replace( /(\".*?\"|'.*?')/g, push )\n .replace( /\\s+/, '' ); \n\n // Indent and insert newlines\n for( var i = 0; i < json.length; i++ ) {\n var c = json.charAt(i);\n\n switch(c) {\n case '{':\n case '[':\n out += c + \"\\n\" + tabs(++indent, indentType);\n break;\n case '}':\n case ']':\n out += \"\\n\" + tabs(--indent, indentType) + c;\n break;\n case ',':\n out += \",\\n\" + tabs(indent, indentType);\n break;\n case ':':\n out += \": \";\n break;\n default:\n out += c;\n break; \n } \n }\n\n // Strip whitespace from numeric arrays and put backslashes \n // and strings back in\n out = out\n .replace( /\\[[\\d,\\s]+?\\]/g, function(m){ return m.replace(/\\s/g,''); } )\n .replace( /\\\\(\\d+)\\\\/g, pop ) // strings\n .replace( /\\\\(\\d+)\\\\/g, pop ); // backslashes in strings\n\n return out;\n};\n\nmodule.exports = function(json, config){\n config = config || configDefault;\n var indent = indentConfig[config.type];\n\n if ( indent == null ) {\n throw new Error('Unrecognized indent type: \"' + config.type + '\"');\n }\n var indentType = new Array((config.size || indent.size) + 1).join(indent.char);\n return JSONFormat(JSON.stringify(json), indentType);\n}\n","\nimport dom from \"sketch/dom\";\nimport UI from \"sketch/ui\";\n\nfunction convertSketchColourToRGBA(colour) {\n const red = Math.round(colour.red() * 255);\n const green = Math.round(colour.green() * 255);\n const blue = Math.round(colour.blue() * 255);\n return \"rgba(\" + red + \",\" + green + \",\" + blue + \",\" + colour.alpha() + \")\";\n}\n\nexport function extractStyles(context, convert) {\n const doc = context.document;\n const pages = doc.pages();\n\n // we need to check if we have all the pages\n let pagesExist = {\n alignments: false,\n colors: false,\n styles: false\n };\n\n // arrays and objects for our styles\n let TypographyStyles = [];\n let DocumentColours = {};\n let textAlignments = [];\n\n pages.forEach(page => {\n // alignments\n if (String(page.name()) === \"Alignments\") {\n // page exists set to true\n pagesExist.alignments = true;\n\n page.layers().forEach(layer => {\n //log(layer.name() + ' ' + layer.textAlignment())\n let alignment = \"left\";\n if (layer.textAlignment() === 4) alignment = \"left\";\n if (layer.textAlignment() === 2) alignment = \"center\";\n if (layer.textAlignment() === 1) alignment = \"right\";\n textAlignments.push(alignment);\n });\n }\n\n // page styles\n if (String(page.name()) === \"Styles\") {\n // page exists set to true\n pagesExist.styles = true;\n\n // get styles\n page.layers().forEach(layer => {\n if (layer.class() === MSTextLayer) {\n // log(layer.font().fontName())\n // log(layer.fontSize())\n // log(layer.lineHeight())\n // log(layer.characterSpacing())\n // log(layer.style().textStyle().encodedAttributes() )\n //log(layer.styleAttributes()[\"MSAttributedStringTextTransformAttribute\"])\n let textTransform = \"none\";\n\n if (\n String(\n layer.styleAttributes()[\n \"MSAttributedStringTextTransformAttribute\"\n ]\n ) === \"1\"\n )\n textTransform = \"uppercase\"; // null: none, 1: uppercase and 2 lowercase\n if (\n String(\n layer.styleAttributes()[\n \"MSAttributedStringTextTransformAttribute\"\n ]\n ) === \"2\"\n )\n textTransform = \"lowercase\";\n\n // console.log( String(layer.name()) + \" \" + layer.font().fontName() + \" \" + dom.fromNative(layer).style.fontWeight + \" \" + dom.fromNative(layer).style.fontStyle )\n // console.log(\"-----\" )\n\n // fontFamily : dom.fromNative(layer).style.fontFamily ,\n // fontWeight : dom.fromNative(layer).style.fontWeight ,\n //console.log(dom.fromNative(layer).style.fontStyle)\n //console.log(dom.fromNative(layer).style.borders)\n\n \n TypographyStyles.push({\n name: String(layer.name()),\n styles: {\n fontFamily: dom.fromNative(layer).style.fontFamily,\n fontWeight: convert\n ? dom.fromNative(layer).style.fontWeight * 100\n : dom.fromNative(layer).style.fontWeight,\n fontSize: layer.fontSize() + (convert ? \"px\" : \"\"),\n lineHeight: layer.lineHeight() + (convert ? \"px\" : \"\"),\n fontStyle:\n dom.fromNative(layer).style.fontStyle != undefined\n ? dom.fromNative(layer).style.fontStyle\n : \"normal\",\n paragraphSpacing: dom.fromNative(layer).style.paragraphSpacing,\n ...(convert && {\n letterSpacing: String(layer.characterSpacing() / 10 + \"em\")\n }),\n ...(!convert && { kerning: layer.characterSpacing() }),\n textTransform: textTransform,\n borders: dom.fromNative(layer).style.borders || []\n },\n alignments: textAlignments,\n adjustments: []\n });\n }\n });\n }\n\n // get colours\n if (String(page.name()) === \"Colours\" || String(page.name()) === \"Colors\") {\n // page exists set to true\n pagesExist.colors = true;\n\n DocumentColours = {};\n page.layers().forEach(layer => {\n DocumentColours[layer.name()] = convert\n ? convertSketchColourToRGBA(\n layer\n .style()\n .firstEnabledFill()\n .color()\n )\n : layer\n .style()\n .firstEnabledFill()\n .color();\n });\n }\n });\n\n\n let allPagesHere = true;\n let messages = [];\n\n // first check for pages\n if (!pagesExist.alignments) {\n messages.push('Your document is missing the page named \"Alignments\".');\n allPagesHere = false;\n }\n\n if (!pagesExist.colors) {\n messages.push('Your document is missing the page named \"Colors\". ');\n allPagesHere = false;\n }\n\n if (!pagesExist.styles) {\n messages.push('Your document is missing the page named \"Styles\".');\n allPagesHere = false;\n }\n\n // now that we have checked for pages, lets see if there is anything in them\n if (pagesExist.alignments && textAlignments.length === 0) {\n messages.push(\"Your alignments page has no alignments in it.\");\n allPagesHere = false;\n }\n\n if (pagesExist.colors && Object.keys(DocumentColours).length === 0) {\n messages.push(\"Your colors page has no colors in it.\");\n allPagesHere = false;\n }\n\n if (pagesExist.styles && TypographyStyles.length === 0) {\n messages.push(\"Your styles page has no styles in it.\");\n allPagesHere = false;\n }\n\n let messageString = \"\";\n messages.forEach(message => {\n messageString += message + \"\\n\";\n });\n\n if (!allPagesHere) UI.alert(\"Unable to render styles\", messageString);\n\n const DesignSystemTokens = {\n colours: DocumentColours,\n typography: TypographyStyles,\n textAlignments: textAlignments,\n render: allPagesHere\n };\n\n return DesignSystemTokens;\n}\n\nexport function generateTextStyles(json) {\n // can we calculate this beforehand?\n let typeStyles = new Array();\n\n json.typography.forEach(item => {\n Object.keys(json.colours).forEach(colour => {\n item.alignments.map((align, index) => {\n // this splits at a slash and adds the adjustments for breakpoints after the alignment\n // assumption is that there is only one adjusment\n let name = item.name.split(\"/\");\n typeStyles.push({\n name: `${name[0]}/${colour}/${index +\n \"_\" +\n align +\n (name.length > 1 ? \"/\" + name[1] : \"\")}`,\n style: {\n textColor: dom.Style.colorToString(json.colours[colour]),\n alignment: align,\n ...item.styles\n }\n });\n });\n });\n });\n\n return typeStyles;\n}\n\nfunction checkMatch(baseStyle, newStyle, prop) {\n let value = true;\n\n // for now we are just going off the previous style. As this would need to check\n // every prop across every adjustment :/\n if (JSON.stringify(baseStyle[prop]) === JSON.stringify(newStyle[prop])) {\n // very primitive and breaks if order is out of sync\n value = false;\n }\n\n //log( prop + ' ' + baseStyle[prop] + ' ----- ' + prop + ' ' +newStyle[prop] + ' value ' + value)\n\n return value;\n}\n\nexport function generateJSONStyles(json, arrayFormat) {\n let typeStyles = {};\n let refinedBreakpoints = [];\n //log(json.typography)\n json.typography.forEach(item => {\n let name = item.name.split(\"/\");\n if (!typeStyles[name[0]]) {\n typeStyles[name[0]] = {\n name: name[0],\n styles: item.styles,\n alignments: item.alignments,\n adjustments: []\n };\n } else {\n let currentStyle = item.styles;\n //let previousStyle = typeStyles[name[0]].styles\n // work out previous style\n const adjustmentLength = typeStyles[name[0]].adjustments.length;\n refinedBreakpoints[adjustmentLength] = { name: name[1], styles: {} };\n\n // if(adjustmentLength>0){\n // previousStyle = typeStyles[name[0]].adjustments[adjustmentLength-1]\n // }\n\n //previousStyle,\n Object.keys(currentStyle).map(checked => {\n if (checkMatch(typeStyles[name[0]].styles, currentStyle, checked)) {\n refinedBreakpoints[adjustmentLength].styles[checked] =\n currentStyle[checked];\n }\n });\n\n typeStyles[name[0]].adjustments.push(\n refinedBreakpoints[adjustmentLength]\n );\n }\n });\n\n // finally merge colours back in and return text to an array\n let formattedTokens = {\n colours: json.colours,\n typography: arrayFormat\n ? Object.keys(typeStyles).map(function(key) {\n return typeStyles[key];\n })\n : typeStyles\n };\n return formattedTokens;\n}\n","import dialog from \"@skpm/dialog\";\nimport path from \"@skpm/path\";\nimport fs from \"@skpm/fs\";\nimport jsonFormat from \"json-format\";\nimport Sketch from \"sketch\";\n\nimport { extractStyles, generateJSONStyles } from \"./generators\";\n\nfunction save(filename, fileContents) {\n console.log(filename)\n\n const targetFile = path.resolve(filename);\n fs.writeFileSync(targetFile, fileContents, \"utf8\");\n}\n\nexport default function(context) {\n const doc = context.document;\n\n // ok lets get the styles\n\n const designTokens = extractStyles(context, true);\n\n if (designTokens.render) {\n const options = [\"Array\", \"Object\"];\n const textSaveSelection = Sketch.UI.getInputFromUser(\n \"Would you like the text styles as an Array or Object\",\n {\n type: Sketch.UI.INPUT_TYPE.selection,\n possibleValues: options\n },\n (err, value) => {\n if (err) {\n // most likely the user canceled the input\n return;\n } else {\n if (value[2]) {\n let textSaveMethod = true;\n if (value === \"Object\") textSaveMethod = false;\n if (value === \"Array\") textSaveMethod = true;\n const arranged = generateJSONStyles(designTokens, textSaveMethod);\n\n // Save the file\n let saveDialog = dialog.showSaveDialog(\n doc,\n {\n defaultPath: \"tokens.json\",\n message: \"Choose a folder to save your tokens\"\n }\n ).then( result => {\n if(!result.cancelled) save(result.filePath, jsonFormat(arranged));\n });\n\n\n }\n }\n }\n );\n } else {\n context.document.showMessage('No styles rendered. Check your document setup. Documentation here https://github.com/tbrasington/text-to-styles');\n }\n}\n","module.exports = require(\"sketch\");","module.exports = require(\"sketch/dom\");","module.exports = require(\"sketch/ui\");","module.exports = require(\"util\");"],"sourceRoot":""}
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Sketch/__renderStyleSheet.js:
--------------------------------------------------------------------------------
1 | var globalThis = this;
2 | var global = this;
3 | function __skpm_run (key, context) {
4 | globalThis.context = context;
5 | try {
6 |
7 | var exports =
8 | /******/ (function(modules) { // webpackBootstrap
9 | /******/ // The module cache
10 | /******/ var installedModules = {};
11 | /******/
12 | /******/ // The require function
13 | /******/ function __webpack_require__(moduleId) {
14 | /******/
15 | /******/ // Check if module is in cache
16 | /******/ if(installedModules[moduleId]) {
17 | /******/ return installedModules[moduleId].exports;
18 | /******/ }
19 | /******/ // Create a new module (and put it into the cache)
20 | /******/ var module = installedModules[moduleId] = {
21 | /******/ i: moduleId,
22 | /******/ l: false,
23 | /******/ exports: {}
24 | /******/ };
25 | /******/
26 | /******/ // Execute the module function
27 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
28 | /******/
29 | /******/ // Flag the module as loaded
30 | /******/ module.l = true;
31 | /******/
32 | /******/ // Return the exports of the module
33 | /******/ return module.exports;
34 | /******/ }
35 | /******/
36 | /******/
37 | /******/ // expose the modules object (__webpack_modules__)
38 | /******/ __webpack_require__.m = modules;
39 | /******/
40 | /******/ // expose the module cache
41 | /******/ __webpack_require__.c = installedModules;
42 | /******/
43 | /******/ // define getter function for harmony exports
44 | /******/ __webpack_require__.d = function(exports, name, getter) {
45 | /******/ if(!__webpack_require__.o(exports, name)) {
46 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
47 | /******/ }
48 | /******/ };
49 | /******/
50 | /******/ // define __esModule on exports
51 | /******/ __webpack_require__.r = function(exports) {
52 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
53 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
54 | /******/ }
55 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
56 | /******/ };
57 | /******/
58 | /******/ // create a fake namespace object
59 | /******/ // mode & 1: value is a module id, require it
60 | /******/ // mode & 2: merge all properties of value into the ns
61 | /******/ // mode & 4: return value when already ns object
62 | /******/ // mode & 8|1: behave like require
63 | /******/ __webpack_require__.t = function(value, mode) {
64 | /******/ if(mode & 1) value = __webpack_require__(value);
65 | /******/ if(mode & 8) return value;
66 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
67 | /******/ var ns = Object.create(null);
68 | /******/ __webpack_require__.r(ns);
69 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
70 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
71 | /******/ return ns;
72 | /******/ };
73 | /******/
74 | /******/ // getDefaultExport function for compatibility with non-harmony modules
75 | /******/ __webpack_require__.n = function(module) {
76 | /******/ var getter = module && module.__esModule ?
77 | /******/ function getDefault() { return module['default']; } :
78 | /******/ function getModuleExports() { return module; };
79 | /******/ __webpack_require__.d(getter, 'a', getter);
80 | /******/ return getter;
81 | /******/ };
82 | /******/
83 | /******/ // Object.prototype.hasOwnProperty.call
84 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
85 | /******/
86 | /******/ // __webpack_public_path__
87 | /******/ __webpack_require__.p = "";
88 | /******/
89 | /******/
90 | /******/ // Load entry module and return exports
91 | /******/ return __webpack_require__(__webpack_require__.s = "./src/renderStyleSheet.js");
92 | /******/ })
93 | /************************************************************************/
94 | /******/ ({
95 |
96 | /***/ "./src/renderStyleSheet.js":
97 | /*!*********************************!*\
98 | !*** ./src/renderStyleSheet.js ***!
99 | \*********************************/
100 | /*! exports provided: default */
101 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
102 |
103 | "use strict";
104 | __webpack_require__.r(__webpack_exports__);
105 | /* harmony import */ var sketch_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sketch/dom */ "sketch/dom");
106 | /* harmony import */ var sketch_dom__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sketch_dom__WEBPACK_IMPORTED_MODULE_0__);
107 |
108 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
109 | var document = sketch_dom__WEBPACK_IMPORTED_MODULE_0___default.a.fromNative(context.document);
110 | var pages = context.document.pages(); // Remove previous rendered pages (thanks to react-sketchapp)
111 |
112 | for (var index = pages.length - 1; index >= 0; index -= 1) {
113 | if (pages.length > 1) {
114 | String(pages[index].name()) === "Rendered Styles" && context.document.documentData().removePageAtIndex(index);
115 | }
116 | }
117 |
118 | var RenderPage = context.document.addBlankPage();
119 | RenderPage.name = "Rendered Styles";
120 | var previousFrame = null; // now make a page
121 |
122 | var stl = document.sharedTextStyles.length;
123 |
124 | for (var property = 0; property < stl; property++) {
125 | var textLayer = new sketch_dom__WEBPACK_IMPORTED_MODULE_0__["Text"]({
126 | text: document.sharedTextStyles[property].name,
127 | frame: {
128 | width: 100,
129 | height: 32,
130 | x: 0,
131 | y: previousFrame != null ? Math.ceil(previousFrame.frame.height + previousFrame.frame.y + 24) : 0
132 | },
133 | sharedStyleId: document.sharedTextStyles[property].id,
134 | style: document.sharedTextStyles[property].style,
135 | parent: RenderPage
136 | });
137 | textLayer.name = document.sharedTextStyles[property].name;
138 | previousFrame = textLayer;
139 | }
140 | });
141 |
142 | /***/ }),
143 |
144 | /***/ "sketch/dom":
145 | /*!*****************************!*\
146 | !*** external "sketch/dom" ***!
147 | \*****************************/
148 | /*! no static exports found */
149 | /***/ (function(module, exports) {
150 |
151 | module.exports = require("sketch/dom");
152 |
153 | /***/ })
154 |
155 | /******/ });
156 | if (key === 'default' && typeof exports === 'function') {
157 | exports(context);
158 | } else if (typeof exports[key] !== 'function') {
159 | throw new Error('Missing export named "' + key + '". Your command should contain something like `export function " + key +"() {}`.');
160 | } else {
161 | exports[key](context);
162 | }
163 | } catch (err) {
164 | if (typeof process !== 'undefined' && process.listenerCount && process.listenerCount('uncaughtException')) {
165 | process.emit("uncaughtException", err, "uncaughtException");
166 | } else {
167 | throw err
168 | }
169 | }
170 | }
171 | globalThis['onRun'] = __skpm_run.bind(this, 'default')
172 |
173 | //# sourceMappingURL=__renderStyleSheet.js.map
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Sketch/__renderStyleSheet.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/renderStyleSheet.js","webpack://exports/external \"sketch/dom\""],"names":["context","document","sketch","fromNative","pages","index","length","String","name","documentData","removePageAtIndex","RenderPage","addBlankPage","previousFrame","stl","sharedTextStyles","property","textLayer","Text","text","frame","width","height","x","y","Math","ceil","sharedStyleId","id","style","parent"],"mappings":";;;;;;;;QAAA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;;QAEA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;;;QAGA;QACA;;QAEA;QACA;;QAEA;QACA;QACA;QACA,0CAA0C,gCAAgC;QAC1E;QACA;;QAEA;QACA;QACA;QACA,wDAAwD,kBAAkB;QAC1E;QACA,iDAAiD,cAAc;QAC/D;;QAEA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA;QACA,yCAAyC,iCAAiC;QAC1E,gHAAgH,mBAAmB,EAAE;QACrI;QACA;;QAEA;QACA;QACA;QACA,2BAA2B,0BAA0B,EAAE;QACvD,iCAAiC,eAAe;QAChD;QACA;QACA;;QAEA;QACA,sDAAsD,+DAA+D;;QAErH;QACA;;;QAGA;QACA;;;;;;;;;;;;;AClFA;AAAA;AAAA;AAAA;AAEe,yEAASA,OAAT,EAAkB;AAC/B,MAAIC,QAAQ,GAAGC,iDAAM,CAACC,UAAP,CAAkBH,OAAO,CAACC,QAA1B,CAAf;AACA,MAAMG,KAAK,GAAGJ,OAAO,CAACC,QAAR,CAAiBG,KAAjB,EAAd,CAF+B,CAI/B;;AACA,OAAK,IAAIC,KAAK,GAAGD,KAAK,CAACE,MAAN,GAAe,CAAhC,EAAmCD,KAAK,IAAI,CAA5C,EAA+CA,KAAK,IAAI,CAAxD,EAA2D;AACzD,QAAID,KAAK,CAACE,MAAN,GAAe,CAAnB,EAAsB;AACpBC,YAAM,CAACH,KAAK,CAACC,KAAD,CAAL,CAAaG,IAAb,EAAD,CAAN,KAAgC,iBAAhC,IACER,OAAO,CAACC,QAAR,CAAiBQ,YAAjB,GAAgCC,iBAAhC,CAAkDL,KAAlD,CADF;AAED;AACF;;AAED,MAAIM,UAAU,GAAGX,OAAO,CAACC,QAAR,CAAiBW,YAAjB,EAAjB;AACAD,YAAU,CAACH,IAAX,GAAkB,iBAAlB;AAEA,MAAIK,aAAa,GAAG,IAApB,CAf+B,CAgB/B;;AAEA,MAAMC,GAAG,GAAGb,QAAQ,CAACc,gBAAT,CAA0BT,MAAtC;;AACA,OAAK,IAAIU,QAAQ,GAAG,CAApB,EAAuBA,QAAQ,GAAGF,GAAlC,EAAuCE,QAAQ,EAA/C,EAAmD;AACjD,QAAIC,SAAS,GAAG,IAAIC,+CAAJ,CAAS;AACvBC,UAAI,EAAElB,QAAQ,CAACc,gBAAT,CAA0BC,QAA1B,EAAoCR,IADnB;AAEvBY,WAAK,EAAE;AACLC,aAAK,EAAC,GADD;AAELC,cAAM,EAAE,EAFH;AAGLC,SAAC,EAAE,CAHE;AAILC,SAAC,EACCX,aAAa,IAAI,IAAjB,GACIY,IAAI,CAACC,IAAL,CAAUb,aAAa,CAACO,KAAd,CAAoBE,MAApB,GAA6BT,aAAa,CAACO,KAAd,CAAoBI,CAAjD,GAAqD,EAA/D,CADJ,GAEI;AAPD,OAFgB;AAWvBG,mBAAa,EAAE1B,QAAQ,CAACc,gBAAT,CAA0BC,QAA1B,EAAoCY,EAX5B;AAYvBC,WAAK,EAAE5B,QAAQ,CAACc,gBAAT,CAA0BC,QAA1B,EAAoCa,KAZpB;AAavBC,YAAM,EAAGnB;AAbc,KAAT,CAAhB;AAgBAM,aAAS,CAACT,IAAV,GAAiBP,QAAQ,CAACc,gBAAT,CAA0BC,QAA1B,EAAoCR,IAArD;AACAK,iBAAa,GAAGI,SAAhB;AACD;AACF,C;;;;;;;;;;;ACzCD,uC","file":"__renderStyleSheet.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/renderStyleSheet.js\");\n","import sketch, { Text } from \"sketch/dom\";\n\nexport default function(context) {\n let document = sketch.fromNative(context.document);\n const pages = context.document.pages();\n\n // Remove previous rendered pages (thanks to react-sketchapp)\n for (let index = pages.length - 1; index >= 0; index -= 1) {\n if (pages.length > 1) {\n String(pages[index].name()) === \"Rendered Styles\" &&\n context.document.documentData().removePageAtIndex(index);\n }\n }\n\n let RenderPage = context.document.addBlankPage();\n RenderPage.name = \"Rendered Styles\";\n\n let previousFrame = null;\n // now make a page\n\n const stl = document.sharedTextStyles.length;\n for (let property = 0; property < stl; property++) {\n let textLayer = new Text({\n text: document.sharedTextStyles[property].name,\n frame: {\n width:100,\n height: 32,\n x: 0,\n y:\n previousFrame != null\n ? Math.ceil(previousFrame.frame.height + previousFrame.frame.y + 24)\n : 0\n },\n sharedStyleId: document.sharedTextStyles[property].id,\n style: document.sharedTextStyles[property].style,\n parent : RenderPage\n });\n\n textLayer.name = document.sharedTextStyles[property].name;\n previousFrame = textLayer;\n }\n}\n","module.exports = require(\"sketch/dom\");"],"sourceRoot":""}
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Sketch/__setupDocument.js:
--------------------------------------------------------------------------------
1 | var globalThis = this;
2 | var global = this;
3 | function __skpm_run (key, context) {
4 | globalThis.context = context;
5 | try {
6 |
7 | var exports =
8 | /******/ (function(modules) { // webpackBootstrap
9 | /******/ // The module cache
10 | /******/ var installedModules = {};
11 | /******/
12 | /******/ // The require function
13 | /******/ function __webpack_require__(moduleId) {
14 | /******/
15 | /******/ // Check if module is in cache
16 | /******/ if(installedModules[moduleId]) {
17 | /******/ return installedModules[moduleId].exports;
18 | /******/ }
19 | /******/ // Create a new module (and put it into the cache)
20 | /******/ var module = installedModules[moduleId] = {
21 | /******/ i: moduleId,
22 | /******/ l: false,
23 | /******/ exports: {}
24 | /******/ };
25 | /******/
26 | /******/ // Execute the module function
27 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
28 | /******/
29 | /******/ // Flag the module as loaded
30 | /******/ module.l = true;
31 | /******/
32 | /******/ // Return the exports of the module
33 | /******/ return module.exports;
34 | /******/ }
35 | /******/
36 | /******/
37 | /******/ // expose the modules object (__webpack_modules__)
38 | /******/ __webpack_require__.m = modules;
39 | /******/
40 | /******/ // expose the module cache
41 | /******/ __webpack_require__.c = installedModules;
42 | /******/
43 | /******/ // define getter function for harmony exports
44 | /******/ __webpack_require__.d = function(exports, name, getter) {
45 | /******/ if(!__webpack_require__.o(exports, name)) {
46 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
47 | /******/ }
48 | /******/ };
49 | /******/
50 | /******/ // define __esModule on exports
51 | /******/ __webpack_require__.r = function(exports) {
52 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
53 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
54 | /******/ }
55 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
56 | /******/ };
57 | /******/
58 | /******/ // create a fake namespace object
59 | /******/ // mode & 1: value is a module id, require it
60 | /******/ // mode & 2: merge all properties of value into the ns
61 | /******/ // mode & 4: return value when already ns object
62 | /******/ // mode & 8|1: behave like require
63 | /******/ __webpack_require__.t = function(value, mode) {
64 | /******/ if(mode & 1) value = __webpack_require__(value);
65 | /******/ if(mode & 8) return value;
66 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
67 | /******/ var ns = Object.create(null);
68 | /******/ __webpack_require__.r(ns);
69 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
70 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
71 | /******/ return ns;
72 | /******/ };
73 | /******/
74 | /******/ // getDefaultExport function for compatibility with non-harmony modules
75 | /******/ __webpack_require__.n = function(module) {
76 | /******/ var getter = module && module.__esModule ?
77 | /******/ function getDefault() { return module['default']; } :
78 | /******/ function getModuleExports() { return module; };
79 | /******/ __webpack_require__.d(getter, 'a', getter);
80 | /******/ return getter;
81 | /******/ };
82 | /******/
83 | /******/ // Object.prototype.hasOwnProperty.call
84 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
85 | /******/
86 | /******/ // __webpack_public_path__
87 | /******/ __webpack_require__.p = "";
88 | /******/
89 | /******/
90 | /******/ // Load entry module and return exports
91 | /******/ return __webpack_require__(__webpack_require__.s = "./src/setupDocument.js");
92 | /******/ })
93 | /************************************************************************/
94 | /******/ ({
95 |
96 | /***/ "./src/setupDocument.js":
97 | /*!******************************!*\
98 | !*** ./src/setupDocument.js ***!
99 | \******************************/
100 | /*! exports provided: default */
101 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
102 |
103 | "use strict";
104 | __webpack_require__.r(__webpack_exports__);
105 | /* harmony import */ var sketch_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sketch/dom */ "sketch/dom");
106 | /* harmony import */ var sketch_dom__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sketch_dom__WEBPACK_IMPORTED_MODULE_0__);
107 |
108 | /* harmony default export */ __webpack_exports__["default"] = (function (context) {
109 | // Remove exisiting Pages
110 | for (var index = context.document.pages().length - 1; index >= 0; index -= 1) {
111 | context.document.documentData().removePageAtIndex(index);
112 | } // Add pages
113 |
114 |
115 | var StylesPage = context.document.addBlankPage();
116 | StylesPage.name = "Styles";
117 | var AlignmentsPage = context.document.addBlankPage();
118 | AlignmentsPage.name = "Alignments";
119 | var ColorsPage = context.document.addBlankPage();
120 | ColorsPage.name = "Colors"; // Add Text to Styles Page
121 |
122 | var textLayer1 = new sketch_dom__WEBPACK_IMPORTED_MODULE_0__["Text"]({
123 | text: "Style 1",
124 | frame: {
125 | width: 100,
126 | height: 32,
127 | x: 0,
128 | y: 0
129 | },
130 | style: {
131 | fontFamily: 'Helvetica',
132 | fontWeight: 8,
133 | fontSize: 24,
134 | lineHeight: 24 * 1.5,
135 | fontStyle: "normal",
136 | paragraphSpacing: 24 * 1.5,
137 | kerning: 0
138 | },
139 | parent: StylesPage
140 | });
141 | textLayer1.name = "Style 1";
142 | var textLayer2 = new sketch_dom__WEBPACK_IMPORTED_MODULE_0__["Text"]({
143 | text: "Style 2",
144 | frame: {
145 | width: 100,
146 | height: 32,
147 | x: 0,
148 | y: textLayer1.frame.height + 24
149 | },
150 | style: {
151 | fontFamily: 'Helvetica',
152 | fontWeight: 4,
153 | fontSize: 16,
154 | lineHeight: 16 * 1.5,
155 | fontStyle: "normal",
156 | paragraphSpacing: 16 * 1.5,
157 | kerning: 0
158 | },
159 | parent: StylesPage
160 | });
161 | textLayer2.name = "Style 2"; // Add Alignments
162 |
163 | var alignmentLayerLeft = new sketch_dom__WEBPACK_IMPORTED_MODULE_0__["Text"]({
164 | text: "Left",
165 | frame: {
166 | width: 100,
167 | height: 32,
168 | x: 0,
169 | y: 0
170 | },
171 | style: {
172 | fontFamily: 'Helvetica',
173 | fontWeight: 4,
174 | fontSize: 16,
175 | lineHeight: 16 * 1.5,
176 | fontStyle: "normal",
177 | paragraphSpacing: 16 * 1.5,
178 | kerning: 0,
179 | alignment: 'left'
180 | },
181 | parent: AlignmentsPage
182 | });
183 | alignmentLayerLeft.name = "Left";
184 | var alignmentLayerRight = new sketch_dom__WEBPACK_IMPORTED_MODULE_0__["Text"]({
185 | text: "Right",
186 | frame: {
187 | width: 100,
188 | height: 32,
189 | x: 0,
190 | y: 0
191 | },
192 | style: {
193 | fontFamily: 'Helvetica',
194 | fontWeight: 4,
195 | fontSize: 16,
196 | lineHeight: 16 * 1.5,
197 | fontStyle: "normal",
198 | paragraphSpacing: 16 * 1.5,
199 | kerning: 0,
200 | alignment: 'right'
201 | },
202 | parent: AlignmentsPage
203 | });
204 | alignmentLayerLeft.name = "Right"; // Add Colors
205 |
206 | new sketch_dom__WEBPACK_IMPORTED_MODULE_0__["ShapePath"]({
207 | name: 'Black',
208 | shapeType: sketch_dom__WEBPACK_IMPORTED_MODULE_0__["ShapePath"].ShapeType.Oval,
209 | parent: ColorsPage,
210 | frame: {
211 | width: 100,
212 | height: 100,
213 | x: 0,
214 | y: 0
215 | },
216 | style: {
217 | fills: [{
218 | color: '#111111',
219 | fillType: sketch_dom__WEBPACK_IMPORTED_MODULE_0__["Style"].FillType.Color
220 | }],
221 | borders: []
222 | }
223 | });
224 | new sketch_dom__WEBPACK_IMPORTED_MODULE_0__["ShapePath"]({
225 | name: 'Red',
226 | shapeType: sketch_dom__WEBPACK_IMPORTED_MODULE_0__["ShapePath"].ShapeType.Oval,
227 | parent: ColorsPage,
228 | frame: {
229 | width: 100,
230 | height: 100,
231 | x: 124,
232 | y: 0
233 | },
234 | style: {
235 | fills: [{
236 | color: '#cc0000',
237 | fillType: sketch_dom__WEBPACK_IMPORTED_MODULE_0__["Style"].FillType.Color
238 | }],
239 | borders: []
240 | }
241 | });
242 | });
243 |
244 | /***/ }),
245 |
246 | /***/ "sketch/dom":
247 | /*!*****************************!*\
248 | !*** external "sketch/dom" ***!
249 | \*****************************/
250 | /*! no static exports found */
251 | /***/ (function(module, exports) {
252 |
253 | module.exports = require("sketch/dom");
254 |
255 | /***/ })
256 |
257 | /******/ });
258 | if (key === 'default' && typeof exports === 'function') {
259 | exports(context);
260 | } else if (typeof exports[key] !== 'function') {
261 | throw new Error('Missing export named "' + key + '". Your command should contain something like `export function " + key +"() {}`.');
262 | } else {
263 | exports[key](context);
264 | }
265 | } catch (err) {
266 | if (typeof process !== 'undefined' && process.listenerCount && process.listenerCount('uncaughtException')) {
267 | process.emit("uncaughtException", err, "uncaughtException");
268 | } else {
269 | throw err
270 | }
271 | }
272 | }
273 | globalThis['onRun'] = __skpm_run.bind(this, 'default')
274 |
275 | //# sourceMappingURL=__setupDocument.js.map
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Sketch/__setupDocument.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./src/setupDocument.js","webpack://exports/external \"sketch/dom\""],"names":["context","index","document","pages","length","documentData","removePageAtIndex","StylesPage","addBlankPage","name","AlignmentsPage","ColorsPage","textLayer1","Text","text","frame","width","height","x","y","style","fontFamily","fontWeight","fontSize","lineHeight","fontStyle","paragraphSpacing","kerning","parent","textLayer2","alignmentLayerLeft","alignment","alignmentLayerRight","ShapePath","shapeType","ShapeType","Oval","fills","color","fillType","Style","FillType","Color","borders"],"mappings":"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","file":"__setupDocument.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = \"./src/setupDocument.js\");\n","import { Text, ShapePath, Style } from \"sketch/dom\";\n\nexport default function(context) {\n \n // Remove exisiting Pages\n for (let index = context.document.pages().length - 1; index >= 0; index -= 1) {\n \n context.document.documentData().removePageAtIndex(index);\n \n }\n\n // Add pages\n const StylesPage = context.document.addBlankPage();\n StylesPage.name = \"Styles\";\n \n const AlignmentsPage = context.document.addBlankPage();\n AlignmentsPage.name = \"Alignments\";\n \n const ColorsPage = context.document.addBlankPage();\n ColorsPage.name = \"Colors\";\n\n\n // Add Text to Styles Page\n const textLayer1 = new Text({\n text: \"Style 1\",\n frame: {\n width: 100,\n height: 32,\n x: 0,\n y: 0\n },\n style: {\n fontFamily: 'Helvetica',\n fontWeight: 8,\n fontSize: 24,\n lineHeight: 24 * 1.5,\n fontStyle: \"normal\",\n paragraphSpacing: 24*1.5,\n kerning : 0\n },\n parent : StylesPage\n });\n textLayer1.name = \"Style 1\";\n\n const textLayer2 = new Text({\n text: \"Style 2\",\n frame: {\n width: 100,\n height: 32,\n x: 0,\n y: textLayer1.frame.height + 24\n },\n style: {\n fontFamily: 'Helvetica',\n fontWeight: 4,\n fontSize: 16,\n lineHeight: 16 * 1.5,\n fontStyle: \"normal\",\n paragraphSpacing: 16*1.5,\n kerning : 0\n },\n parent : StylesPage\n });\n textLayer2.name = \"Style 2\";\n\n // Add Alignments\n const alignmentLayerLeft = new Text({\n text: \"Left\",\n frame: {\n width: 100,\n height: 32,\n x: 0,\n y: 0\n },\n style: {\n fontFamily: 'Helvetica',\n fontWeight: 4,\n fontSize: 16,\n lineHeight: 16 * 1.5,\n fontStyle: \"normal\",\n paragraphSpacing: 16*1.5,\n kerning : 0,\n alignment : 'left'\n },\n parent : AlignmentsPage\n });\n alignmentLayerLeft.name = \"Left\";\n\n const alignmentLayerRight = new Text({\n text: \"Right\",\n frame: {\n width: 100,\n height: 32,\n x: 0,\n y: 0\n },\n style: {\n fontFamily: 'Helvetica',\n fontWeight: 4,\n fontSize: 16,\n lineHeight: 16 * 1.5,\n fontStyle: \"normal\",\n paragraphSpacing: 16*1.5,\n kerning : 0,\n alignment : 'right'\n },\n parent : AlignmentsPage\n });\n alignmentLayerLeft.name = \"Right\";\n\n // Add Colors\n new ShapePath({\n name: 'Black',\n shapeType: ShapePath.ShapeType.Oval,\n parent : ColorsPage,\n frame : {\n width: 100,\n height: 100,\n x: 0, \n y : 0\n },\n style : {\n fills : [\n {\n color: '#111111',\n fillType: Style.FillType.Color,\n }\n ],\n borders : []\n }\n });\n\n new ShapePath({\n name: 'Red',\n shapeType: ShapePath.ShapeType.Oval,\n parent : ColorsPage,\n frame : {\n width: 100,\n height: 100,\n x: 124, \n y : 0\n },\n style : {\n fills : [\n {\n color: '#cc0000',\n fillType: Style.FillType.Color,\n }\n ],\n borders : []\n }\n });\n \n}\n","module.exports = require(\"sketch/dom\");"],"sourceRoot":""}
--------------------------------------------------------------------------------
/text-to-styles.sketchplugin/Contents/Sketch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "compatibleVersion": 3,
3 | "bundleVersion": 1,
4 | "icon": "icon.png",
5 | "name": "Text to Styles",
6 | "description": "Generates Sketch Text Styles from Layers to easily manage, size, colour and alignment variations",
7 | "commands": [
8 | {
9 | "name": "Create Text Styles",
10 | "identifier": "createTextStyles",
11 | "script": "__createTextStyles.js"
12 | }
13 | ],
14 | "menu": {
15 | "title": "Text to Styles",
16 | "items": [
17 | "runDocumentSetup",
18 | "createTextStyles",
19 | "renderStyleSheet",
20 | "renderJSON"
21 | ]
22 | },
23 | "version": "4.0.0",
24 | "identifier": "Text to Styles",
25 | "disableCocoaScriptPreprocessor": true,
26 | "appcast": "https://raw.githubusercontent.com/tbrasington/text-to-styles/master/.appcast.xml",
27 | "author": "Thomas Brasington",
28 | "authorEmail": "tbrasington@gmail.com"
29 | }
--------------------------------------------------------------------------------