├── .editorconfig
├── .eslintrc
├── .gitignore
├── .prettierrc
├── Sketch Resize.sketchplugin
└── Contents
│ ├── Resources
│ ├── _webpack_resources
│ │ ├── 43aa738f582ce37c61cb81dcdf421b63.html
│ │ └── 9a9109f28172ef2d57fd3a1b7a72d03b.css
│ ├── resize.png
│ ├── script.js
│ ├── script.js.map
│ └── sketch-icon.png
│ └── Sketch
│ ├── main.js
│ ├── main.js.map
│ └── manifest.json
├── appcast.xml
├── assets
├── resize.png
└── sketch-icon.png
├── images
├── img-header.jpg
├── img-sketch-resize.jpg
├── img-sketch-reverse.jpg
├── img-sketch-runner.jpg
├── img-sketch-styles-generator.jpg
└── img-usage.gif
├── license
├── package.json
├── readme.md
├── resources
└── webview
│ ├── script.js
│ ├── styles.css
│ └── webview.html
├── src
├── actions
│ └── resize.js
├── main.js
└── manifest.json
├── webpack.skpm.config.js
└── yarn.lock
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | indent_size = 2
7 | indent_style = space
8 | insert_final_newline = true
9 | max_line_length = null
10 | trim_trailing_whitespace = true
11 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "amd": true,
5 | "node": true,
6 | "es6": true
7 | },
8 | "parser": "babel-eslint",
9 | "parserOptions": {
10 | "ecmaVersion": 2017,
11 | "sourceType": "module",
12 | "ecmaFeatures": {
13 | "modules": true
14 | }
15 | },
16 | "extends": ["eslint:recommended"],
17 | "rules": {
18 | "no-console": "off"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | build
3 | .DS_Store
4 | .DS_Store?
5 | ._*
6 | .env.local
7 | .env.development.local
8 | .env.test.local
9 | .env.production.local
10 | yarn-debug.log*
11 | yarn-error.log*
12 | npm-debug.log*
13 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "semi": true,
5 | "singleQuote": true
6 | }
7 |
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Resources/_webpack_resources/43aa738f582ce37c61cb81dcdf421b63.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Sketch Resize
7 |
8 |
9 |
10 |
11 |
12 | Resize Element(s)
13 |
14 |
15 |
26 |
27 |
28 | Cancel
29 | Confirm and Resize
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Resources/_webpack_resources/9a9109f28172ef2d57fd3a1b7a72d03b.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | overflow: hidden;
4 | padding: 1px;
5 | color: #9c9c9c;
6 | background: #171717;
7 | font-family: -apple-system;
8 | font-size: 13px;
9 | line-height: 20px;
10 | cursor: default;
11 | }
12 |
13 | *,
14 | *:before,
15 | *:after {
16 | position: relative;
17 | box-sizing: inherit;
18 | margin: 0;
19 | padding: 0;
20 | -webkit-user-select: none;
21 | user-select: none;
22 | }
23 |
24 | input,
25 | textarea {
26 | -webkit-user-select: auto;
27 | user-select: auto;
28 | }
29 |
30 | /* -------------------------------- */
31 | /* header/menubar */
32 | /* -------------------------------- */
33 |
34 | header {
35 | border-bottom: 1px solid #000000;
36 | height: 37px;
37 | color: rgba(255, 255, 255, 0.7);
38 | background-color: #242424;
39 | font-weight: 600;
40 | line-height: 37px;
41 | text-align: center;
42 | }
43 |
44 | /* -------------------------------- */
45 | /* section/content */
46 | /* -------------------------------- */
47 |
48 | section {
49 | padding: 24px;
50 | }
51 |
52 | section > p.info {
53 | margin-bottom: 16px;
54 | font-weight: 400;
55 | color: rgba(255, 255, 255, 0.7);
56 | }
57 |
58 | section > p.info > strong {
59 | color: #ffffff;
60 | }
61 |
62 | section > div {
63 | font-size: 0;
64 | }
65 |
66 | section > div > input {
67 | display: inline-block;
68 | margin-bottom: 16px;
69 | border: 2px solid #242424;
70 | border-radius: 4px;
71 | padding: 12px;
72 | width: calc(50% - 4px);
73 | background-color: #242424;
74 | color: #ffffff;
75 | font-size: 13px;
76 | }
77 |
78 | section > div > input:focus {
79 | outline: 0;
80 | border: 2px solid #1c7ed5;
81 | }
82 |
83 | section > div > input::placeholder {
84 | color: rgba(255, 255, 255, 0.4);
85 | }
86 |
87 | section > div > input#width {
88 | margin-right: 8px;
89 | }
90 |
91 | section > p.tip {
92 | font-size: 12px;
93 | font-weight: 400;
94 | color: rgba(255, 255, 255, 0.4);
95 | }
96 |
97 | /* -------------------------------- */
98 | /* footer/actions */
99 | /* -------------------------------- */
100 |
101 | footer {
102 | border-top: 1px solid rgba(255, 255, 255, 0.1);
103 | padding: 16px 24px;
104 | background-color: #242424;
105 | font-size: 0;
106 | text-align: right;
107 | }
108 |
109 | footer > button {
110 | display: inline-block;
111 | height: 40px;
112 | border: 0;
113 | border-radius: 4px;
114 | padding: 0 12px;
115 | color: #ffffff;
116 | font-size: 13px;
117 | line-height: 16px;
118 | font-weight: 600;
119 | }
120 |
121 | footer > button:focus {
122 | outline: 0;
123 | }
124 |
125 | footer > button:focus:after {
126 | content: '';
127 | display: block;
128 | position: absolute;
129 | top: -5px;
130 | left: -5px;
131 | width: calc(100% + 10px);
132 | height: calc(100% + 10px);
133 | border: 2px solid #1c7ed5;
134 | border-radius: 6px;
135 | }
136 |
137 | footer > button#cancel {
138 | margin-right: 8px;
139 | border: 1px solid rgba(255, 255, 255, 0.4);
140 | background-color: transparent;
141 | }
142 |
143 | footer > button#cancel:hover {
144 | background-color: rgba(255, 255, 255, 0.1);
145 | }
146 |
147 | footer > button#submit {
148 | border: 1px solid #1c7ed5;
149 | background-color: #1c7ed5;
150 | }
151 |
152 | footer > button#submit:hover {
153 | background-color: #186bb5;
154 | }
155 |
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Resources/resize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/Sketch Resize.sketchplugin/Contents/Resources/resize.png
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Resources/script.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 | /******/
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 | /******/
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId]) {
10 | /******/ return installedModules[moduleId].exports;
11 | /******/ }
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ i: moduleId,
15 | /******/ l: false,
16 | /******/ exports: {}
17 | /******/ };
18 | /******/
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 | /******/
22 | /******/ // Flag the module as loaded
23 | /******/ module.l = true;
24 | /******/
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 | /******/
29 | /******/
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 | /******/
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 | /******/
36 | /******/ // define getter function for harmony exports
37 | /******/ __webpack_require__.d = function(exports, name, getter) {
38 | /******/ if(!__webpack_require__.o(exports, name)) {
39 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
40 | /******/ }
41 | /******/ };
42 | /******/
43 | /******/ // define __esModule on exports
44 | /******/ __webpack_require__.r = function(exports) {
45 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
46 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
47 | /******/ }
48 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
49 | /******/ };
50 | /******/
51 | /******/ // create a fake namespace object
52 | /******/ // mode & 1: value is a module id, require it
53 | /******/ // mode & 2: merge all properties of value into the ns
54 | /******/ // mode & 4: return value when already ns object
55 | /******/ // mode & 8|1: behave like require
56 | /******/ __webpack_require__.t = function(value, mode) {
57 | /******/ if(mode & 1) value = __webpack_require__(value);
58 | /******/ if(mode & 8) return value;
59 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
60 | /******/ var ns = Object.create(null);
61 | /******/ __webpack_require__.r(ns);
62 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
63 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
64 | /******/ return ns;
65 | /******/ };
66 | /******/
67 | /******/ // getDefaultExport function for compatibility with non-harmony modules
68 | /******/ __webpack_require__.n = function(module) {
69 | /******/ var getter = module && module.__esModule ?
70 | /******/ function getDefault() { return module['default']; } :
71 | /******/ function getModuleExports() { return module; };
72 | /******/ __webpack_require__.d(getter, 'a', getter);
73 | /******/ return getter;
74 | /******/ };
75 | /******/
76 | /******/ // Object.prototype.hasOwnProperty.call
77 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
78 | /******/
79 | /******/ // __webpack_public_path__
80 | /******/ __webpack_require__.p = "";
81 | /******/
82 | /******/
83 | /******/ // Load entry module and return exports
84 | /******/ return __webpack_require__(__webpack_require__.s = "./resources/webview/script.js");
85 | /******/ })
86 | /************************************************************************/
87 | /******/ ({
88 |
89 | /***/ "./resources/webview/script.js":
90 | /*!*************************************!*\
91 | !*** ./resources/webview/script.js ***!
92 | \*************************************/
93 | /*! no static exports found */
94 | /***/ (function(module, exports) {
95 |
96 | // disable context menu
97 | document.addEventListener('contextmenu', function (event) {
98 | event.preventDefault();
99 | }); // cancel button
100 |
101 | document.getElementById('cancel').addEventListener('click', function (event) {
102 | event.preventDefault();
103 | window.postMessage('cancel');
104 | }); // submit on enter
105 |
106 | document.addEventListener('keypress', function (event) {
107 | if (event.keyCode !== 13) return;
108 | event.preventDefault();
109 | window.postMessage('submit', getValues());
110 | }); // submit button
111 |
112 | document.getElementById('submit').addEventListener('click', function (event) {
113 | event.preventDefault();
114 | window.postMessage('submit', getValues());
115 | }); // get inputs value
116 |
117 | var getValues = function getValues() {
118 | return {
119 | width: document.getElementById('width').value,
120 | height: document.getElementById('height').value
121 | };
122 | };
123 |
124 | /***/ })
125 |
126 | /******/ });
127 | //# sourceMappingURL=script.js.map
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Resources/script.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./resources/webview/script.js"],"names":["document","addEventListener","event","preventDefault","getElementById","window","postMessage","keyCode","getValues","width","value","height"],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kDAA0C,gCAAgC;AAC1E;AACA;;AAEA;AACA;AACA;AACA,gEAAwD,kBAAkB;AAC1E;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAyC,iCAAiC;AAC1E,wHAAgH,mBAAmB,EAAE;AACrI;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;;AAGA;AACA;;;;;;;;;;;;AClFA;AACAA,QAAQ,CAACC,gBAAT,CAA0B,aAA1B,EAAyC,UAAAC,KAAK,EAAI;AAChDA,OAAK,CAACC,cAAN;AACD,CAFD,E,CAIA;;AACAH,QAAQ,CAACI,cAAT,CAAwB,QAAxB,EAAkCH,gBAAlC,CAAmD,OAAnD,EAA4D,UAAAC,KAAK,EAAI;AACnEA,OAAK,CAACC,cAAN;AACAE,QAAM,CAACC,WAAP,CAAmB,QAAnB;AACD,CAHD,E,CAKA;;AACAN,QAAQ,CAACC,gBAAT,CAA0B,UAA1B,EAAsC,UAAAC,KAAK,EAAI;AAC7C,MAAIA,KAAK,CAACK,OAAN,KAAkB,EAAtB,EAA0B;AAC1BL,OAAK,CAACC,cAAN;AACAE,QAAM,CAACC,WAAP,CAAmB,QAAnB,EAA6BE,SAAS,EAAtC;AACD,CAJD,E,CAMA;;AACAR,QAAQ,CAACI,cAAT,CAAwB,QAAxB,EAAkCH,gBAAlC,CAAmD,OAAnD,EAA4D,UAAAC,KAAK,EAAI;AACnEA,OAAK,CAACC,cAAN;AACAE,QAAM,CAACC,WAAP,CAAmB,QAAnB,EAA6BE,SAAS,EAAtC;AACD,CAHD,E,CAKA;;AACA,IAAMA,SAAS,GAAG,SAAZA,SAAY;AAAA,SAAO;AACvBC,SAAK,EAAET,QAAQ,CAACI,cAAT,CAAwB,OAAxB,EAAiCM,KADjB;AAEvBC,UAAM,EAAEX,QAAQ,CAACI,cAAT,CAAwB,QAAxB,EAAkCM;AAFnB,GAAP;AAAA,CAAlB,C","file":"script.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 = \"./resources/webview/script.js\");\n","// disable context menu\ndocument.addEventListener('contextmenu', event => {\n event.preventDefault();\n});\n\n// cancel button\ndocument.getElementById('cancel').addEventListener('click', event => {\n event.preventDefault();\n window.postMessage('cancel');\n});\n\n// submit on enter\ndocument.addEventListener('keypress', event => {\n if (event.keyCode !== 13) return;\n event.preventDefault();\n window.postMessage('submit', getValues());\n});\n\n// submit button\ndocument.getElementById('submit').addEventListener('click', event => {\n event.preventDefault();\n window.postMessage('submit', getValues());\n});\n\n// get inputs value\nconst getValues = () => ({\n width: document.getElementById('width').value,\n height: document.getElementById('height').value\n});\n"],"sourceRoot":""}
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Resources/sketch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/Sketch Resize.sketchplugin/Contents/Resources/sketch-icon.png
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Sketch/main.js:
--------------------------------------------------------------------------------
1 | var that = this;
2 | function __skpm_run (key, context) {
3 | that.context = context;
4 |
5 | var exports =
6 | /******/ (function(modules) { // webpackBootstrap
7 | /******/ // The module cache
8 | /******/ var installedModules = {};
9 | /******/
10 | /******/ // The require function
11 | /******/ function __webpack_require__(moduleId) {
12 | /******/
13 | /******/ // Check if module is in cache
14 | /******/ if(installedModules[moduleId]) {
15 | /******/ return installedModules[moduleId].exports;
16 | /******/ }
17 | /******/ // Create a new module (and put it into the cache)
18 | /******/ var module = installedModules[moduleId] = {
19 | /******/ i: moduleId,
20 | /******/ l: false,
21 | /******/ exports: {}
22 | /******/ };
23 | /******/
24 | /******/ // Execute the module function
25 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
26 | /******/
27 | /******/ // Flag the module as loaded
28 | /******/ module.l = true;
29 | /******/
30 | /******/ // Return the exports of the module
31 | /******/ return module.exports;
32 | /******/ }
33 | /******/
34 | /******/
35 | /******/ // expose the modules object (__webpack_modules__)
36 | /******/ __webpack_require__.m = modules;
37 | /******/
38 | /******/ // expose the module cache
39 | /******/ __webpack_require__.c = installedModules;
40 | /******/
41 | /******/ // define getter function for harmony exports
42 | /******/ __webpack_require__.d = function(exports, name, getter) {
43 | /******/ if(!__webpack_require__.o(exports, name)) {
44 | /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
45 | /******/ }
46 | /******/ };
47 | /******/
48 | /******/ // define __esModule on exports
49 | /******/ __webpack_require__.r = function(exports) {
50 | /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
51 | /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
52 | /******/ }
53 | /******/ Object.defineProperty(exports, '__esModule', { value: true });
54 | /******/ };
55 | /******/
56 | /******/ // create a fake namespace object
57 | /******/ // mode & 1: value is a module id, require it
58 | /******/ // mode & 2: merge all properties of value into the ns
59 | /******/ // mode & 4: return value when already ns object
60 | /******/ // mode & 8|1: behave like require
61 | /******/ __webpack_require__.t = function(value, mode) {
62 | /******/ if(mode & 1) value = __webpack_require__(value);
63 | /******/ if(mode & 8) return value;
64 | /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
65 | /******/ var ns = Object.create(null);
66 | /******/ __webpack_require__.r(ns);
67 | /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
68 | /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
69 | /******/ return ns;
70 | /******/ };
71 | /******/
72 | /******/ // getDefaultExport function for compatibility with non-harmony modules
73 | /******/ __webpack_require__.n = function(module) {
74 | /******/ var getter = module && module.__esModule ?
75 | /******/ function getDefault() { return module['default']; } :
76 | /******/ function getModuleExports() { return module; };
77 | /******/ __webpack_require__.d(getter, 'a', getter);
78 | /******/ return getter;
79 | /******/ };
80 | /******/
81 | /******/ // Object.prototype.hasOwnProperty.call
82 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
83 | /******/
84 | /******/ // __webpack_public_path__
85 | /******/ __webpack_require__.p = "";
86 | /******/
87 | /******/
88 | /******/ // Load entry module and return exports
89 | /******/ return __webpack_require__(__webpack_require__.s = "./src/main.js");
90 | /******/ })
91 | /************************************************************************/
92 | /******/ ({
93 |
94 | /***/ "./node_modules/@skpm/timers/immediate.js":
95 | /*!************************************************!*\
96 | !*** ./node_modules/@skpm/timers/immediate.js ***!
97 | \************************************************/
98 | /*! no static exports found */
99 | /***/ (function(module, exports, __webpack_require__) {
100 |
101 | /* globals coscript, sketch */
102 | var timeout = __webpack_require__(/*! ./timeout */ "./node_modules/@skpm/timers/timeout.js")
103 |
104 | function setImmediate(func, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) {
105 | return timeout.setTimeout(func, 0, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)
106 | }
107 |
108 | function clearImmediate(id) {
109 | return timeout.clearTimeout(id)
110 | }
111 |
112 | module.exports = {
113 | setImmediate: setImmediate,
114 | clearImmediate: clearImmediate
115 | }
116 |
117 |
118 | /***/ }),
119 |
120 | /***/ "./node_modules/@skpm/timers/test-if-fiber.js":
121 | /*!****************************************************!*\
122 | !*** ./node_modules/@skpm/timers/test-if-fiber.js ***!
123 | \****************************************************/
124 | /*! no static exports found */
125 | /***/ (function(module, exports) {
126 |
127 | module.exports = function () {
128 | return typeof coscript !== 'undefined' && coscript.createFiber
129 | }
130 |
131 |
132 | /***/ }),
133 |
134 | /***/ "./node_modules/@skpm/timers/timeout.js":
135 | /*!**********************************************!*\
136 | !*** ./node_modules/@skpm/timers/timeout.js ***!
137 | \**********************************************/
138 | /*! no static exports found */
139 | /***/ (function(module, exports, __webpack_require__) {
140 |
141 | /* globals coscript, sketch */
142 | var fiberAvailable = __webpack_require__(/*! ./test-if-fiber */ "./node_modules/@skpm/timers/test-if-fiber.js")
143 |
144 | var setTimeout
145 | var clearTimeout
146 |
147 | var fibers = []
148 |
149 | if (fiberAvailable()) {
150 | var fibers = []
151 |
152 | setTimeout = function (func, delay, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) {
153 | // fibers takes care of keeping coscript around
154 | var id = fibers.length
155 | fibers.push(coscript.scheduleWithInterval_jsFunction(
156 | (delay || 0) / 1000,
157 | function () {
158 | func(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)
159 | }
160 | ))
161 | return id
162 | }
163 |
164 | clearTimeout = function (id) {
165 | var timeout = fibers[id]
166 | if (timeout) {
167 | timeout.cancel() // fibers takes care of keeping coscript around
168 | fibers[id] = undefined // garbage collect the fiber
169 | }
170 | }
171 | } else {
172 | setTimeout = function (func, delay, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) {
173 | coscript.shouldKeepAround = true
174 | var id = fibers.length
175 | fibers.push(true)
176 | coscript.scheduleWithInterval_jsFunction(
177 | (delay || 0) / 1000,
178 | function () {
179 | if (fibers[id]) { // if not cleared
180 | func(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)
181 | }
182 | clearTimeout(id)
183 | if (fibers.every(function (_id) { return !_id })) { // if everything is cleared
184 | coscript.shouldKeepAround = false
185 | }
186 | }
187 | )
188 | return id
189 | }
190 |
191 | clearTimeout = function (id) {
192 | fibers[id] = false
193 | }
194 | }
195 |
196 | module.exports = {
197 | setTimeout: setTimeout,
198 | clearTimeout: clearTimeout
199 | }
200 |
201 |
202 | /***/ }),
203 |
204 | /***/ "./node_modules/cocoascript-class/lib/index.js":
205 | /*!*****************************************************!*\
206 | !*** ./node_modules/cocoascript-class/lib/index.js ***!
207 | \*****************************************************/
208 | /*! no static exports found */
209 | /***/ (function(module, exports, __webpack_require__) {
210 |
211 | "use strict";
212 |
213 |
214 | Object.defineProperty(exports, "__esModule", {
215 | value: true
216 | });
217 | exports.SuperCall = undefined;
218 | exports.default = ObjCClass;
219 |
220 | var _runtime = __webpack_require__(/*! ./runtime.js */ "./node_modules/cocoascript-class/lib/runtime.js");
221 |
222 | exports.SuperCall = _runtime.SuperCall;
223 |
224 | // super when returnType is id and args are void
225 | // id objc_msgSendSuper(struct objc_super *super, SEL op, void)
226 |
227 | const SuperInit = (0, _runtime.SuperCall)(NSStringFromSelector("init"), [], { type: "@" });
228 |
229 | // Returns a real ObjC class. No need to use new.
230 | function ObjCClass(defn) {
231 | const superclass = defn.superclass || NSObject;
232 | const className = (defn.className || defn.classname || "ObjCClass") + NSUUID.UUID().UUIDString();
233 | const reserved = new Set(['className', 'classname', 'superclass']);
234 | var cls = MOClassDescription.allocateDescriptionForClassWithName_superclass_(className, superclass);
235 | // Add each handler to the class description
236 | const ivars = [];
237 | for (var key in defn) {
238 | const v = defn[key];
239 | if (typeof v == 'function' && key !== 'init') {
240 | var selector = NSSelectorFromString(key);
241 | cls.addInstanceMethodWithSelector_function_(selector, v);
242 | } else if (!reserved.has(key)) {
243 | ivars.push(key);
244 | cls.addInstanceVariableWithName_typeEncoding(key, "@");
245 | }
246 | }
247 |
248 | cls.addInstanceMethodWithSelector_function_(NSSelectorFromString('init'), function () {
249 | const self = SuperInit.call(this);
250 | ivars.map(name => {
251 | Object.defineProperty(self, name, {
252 | get() {
253 | return getIvar(self, name);
254 | },
255 | set(v) {
256 | (0, _runtime.object_setInstanceVariable)(self, name, v);
257 | }
258 | });
259 | self[name] = defn[name];
260 | });
261 | // If there is a passsed-in init funciton, call it now.
262 | if (typeof defn.init == 'function') defn.init.call(this);
263 | return self;
264 | });
265 |
266 | return cls.registerClass();
267 | };
268 |
269 | function getIvar(obj, name) {
270 | const retPtr = MOPointer.new();
271 | (0, _runtime.object_getInstanceVariable)(obj, name, retPtr);
272 | return retPtr.value().retain().autorelease();
273 | }
274 |
275 | /***/ }),
276 |
277 | /***/ "./node_modules/cocoascript-class/lib/runtime.js":
278 | /*!*******************************************************!*\
279 | !*** ./node_modules/cocoascript-class/lib/runtime.js ***!
280 | \*******************************************************/
281 | /*! no static exports found */
282 | /***/ (function(module, exports, __webpack_require__) {
283 |
284 | "use strict";
285 |
286 |
287 | Object.defineProperty(exports, "__esModule", {
288 | value: true
289 | });
290 | exports.SuperCall = SuperCall;
291 | exports.CFunc = CFunc;
292 | const objc_super_typeEncoding = '{objc_super="receiver"@"super_class"#}';
293 |
294 | // You can store this to call your function. this must be bound to the current instance.
295 | function SuperCall(selector, argTypes, returnType) {
296 | const func = CFunc("objc_msgSendSuper", [{ type: '^' + objc_super_typeEncoding }, { type: ":" }, ...argTypes], returnType);
297 | return function (...args) {
298 | const struct = make_objc_super(this, this.superclass());
299 | const structPtr = MOPointer.alloc().initWithValue_(struct);
300 | return func(structPtr, selector, ...args);
301 | };
302 | }
303 |
304 | // Recursively create a MOStruct
305 | function makeStruct(def) {
306 | if (typeof def !== 'object' || Object.keys(def).length == 0) {
307 | return def;
308 | }
309 | const name = Object.keys(def)[0];
310 | const values = def[name];
311 |
312 | const structure = MOStruct.structureWithName_memberNames_runtime(name, Object.keys(values), Mocha.sharedRuntime());
313 |
314 | Object.keys(values).map(member => {
315 | structure[member] = makeStruct(values[member]);
316 | });
317 |
318 | return structure;
319 | }
320 |
321 | function make_objc_super(self, cls) {
322 | return makeStruct({
323 | objc_super: {
324 | receiver: self,
325 | super_class: cls
326 | }
327 | });
328 | }
329 |
330 | // Due to particularities of the JS bridge, we can't call into MOBridgeSupport objects directly
331 | // But, we can ask key value coding to do the dirty work for us ;)
332 | function setKeys(o, d) {
333 | const funcDict = NSMutableDictionary.dictionary();
334 | funcDict.o = o;
335 | Object.keys(d).map(k => funcDict.setValue_forKeyPath(d[k], "o." + k));
336 | }
337 |
338 | // Use any C function, not just ones with BridgeSupport
339 | function CFunc(name, args, retVal) {
340 | function makeArgument(a) {
341 | if (!a) return null;
342 | const arg = MOBridgeSupportArgument.alloc().init();
343 | setKeys(arg, {
344 | type64: a.type
345 | });
346 | return arg;
347 | }
348 | const func = MOBridgeSupportFunction.alloc().init();
349 | setKeys(func, {
350 | name: name,
351 | arguments: args.map(makeArgument),
352 | returnValue: makeArgument(retVal)
353 | });
354 | return func;
355 | }
356 |
357 | /*
358 | @encode(char*) = "*"
359 | @encode(id) = "@"
360 | @encode(Class) = "#"
361 | @encode(void*) = "^v"
362 | @encode(CGRect) = "{CGRect={CGPoint=dd}{CGSize=dd}}"
363 | @encode(SEL) = ":"
364 | */
365 |
366 | function addStructToBridgeSupport(key, structDef) {
367 | // OK, so this is probably the nastiest hack in this file.
368 | // We go modify MOBridgeSupportController behind its back and use kvc to add our own definition
369 | // There isn't another API for this though. So the only other way would be to make a real bridgesupport file.
370 | const symbols = MOBridgeSupportController.sharedController().valueForKey('symbols');
371 | if (!symbols) throw Error("Something has changed within bridge support so we can't add our definitions");
372 | // If someone already added this definition, don't re-register it.
373 | if (symbols[key] !== null) return;
374 | const def = MOBridgeSupportStruct.alloc().init();
375 | setKeys(def, {
376 | name: key,
377 | type: structDef.type
378 | });
379 | symbols[key] = def;
380 | };
381 |
382 | // This assumes the ivar is an object type. Return value is pretty useless.
383 | const object_getInstanceVariable = exports.object_getInstanceVariable = CFunc("object_getInstanceVariable", [{ type: "@" }, { type: '*' }, { type: "^@" }], { type: "^{objc_ivar=}" });
384 | // Again, ivar is of object type
385 | const object_setInstanceVariable = exports.object_setInstanceVariable = CFunc("object_setInstanceVariable", [{ type: "@" }, { type: '*' }, { type: "@" }], { type: "^{objc_ivar=}" });
386 |
387 | // We need Mocha to understand what an objc_super is so we can use it as a function argument
388 | addStructToBridgeSupport('objc_super', { type: objc_super_typeEncoding });
389 |
390 | /***/ }),
391 |
392 | /***/ "./node_modules/promise-polyfill/lib/index.js":
393 | /*!****************************************************!*\
394 | !*** ./node_modules/promise-polyfill/lib/index.js ***!
395 | \****************************************************/
396 | /*! no static exports found */
397 | /***/ (function(module, exports, __webpack_require__) {
398 |
399 | "use strict";
400 | /* WEBPACK VAR INJECTION */(function(setTimeout, setImmediate) {
401 |
402 | /**
403 | * @this {Promise}
404 | */
405 | function finallyConstructor(callback) {
406 | var constructor = this.constructor;
407 | return this.then(
408 | function(value) {
409 | return constructor.resolve(callback()).then(function() {
410 | return value;
411 | });
412 | },
413 | function(reason) {
414 | return constructor.resolve(callback()).then(function() {
415 | return constructor.reject(reason);
416 | });
417 | }
418 | );
419 | }
420 |
421 | // Store setTimeout reference so promise-polyfill will be unaffected by
422 | // other code modifying setTimeout (like sinon.useFakeTimers())
423 | var setTimeoutFunc = setTimeout;
424 |
425 | function noop() {}
426 |
427 | // Polyfill for Function.prototype.bind
428 | function bind(fn, thisArg) {
429 | return function() {
430 | fn.apply(thisArg, arguments);
431 | };
432 | }
433 |
434 | /**
435 | * @constructor
436 | * @param {Function} fn
437 | */
438 | function Promise(fn) {
439 | if (!(this instanceof Promise))
440 | throw new TypeError('Promises must be constructed via new');
441 | if (typeof fn !== 'function') throw new TypeError('not a function');
442 | /** @type {!number} */
443 | this._state = 0;
444 | /** @type {!boolean} */
445 | this._handled = false;
446 | /** @type {Promise|undefined} */
447 | this._value = undefined;
448 | /** @type {!Array} */
449 | this._deferreds = [];
450 |
451 | doResolve(fn, this);
452 | }
453 |
454 | function handle(self, deferred) {
455 | while (self._state === 3) {
456 | self = self._value;
457 | }
458 | if (self._state === 0) {
459 | self._deferreds.push(deferred);
460 | return;
461 | }
462 | self._handled = true;
463 | Promise._immediateFn(function() {
464 | var cb = self._state === 1 ? deferred.onFulfilled : deferred.onRejected;
465 | if (cb === null) {
466 | (self._state === 1 ? resolve : reject)(deferred.promise, self._value);
467 | return;
468 | }
469 | var ret;
470 | try {
471 | ret = cb(self._value);
472 | } catch (e) {
473 | reject(deferred.promise, e);
474 | return;
475 | }
476 | resolve(deferred.promise, ret);
477 | });
478 | }
479 |
480 | function resolve(self, newValue) {
481 | try {
482 | // Promise Resolution Procedure: https://github.com/promises-aplus/promises-spec#the-promise-resolution-procedure
483 | if (newValue === self)
484 | throw new TypeError('A promise cannot be resolved with itself.');
485 | if (
486 | newValue &&
487 | (typeof newValue === 'object' || typeof newValue === 'function')
488 | ) {
489 | var then = newValue.then;
490 | if (newValue instanceof Promise) {
491 | self._state = 3;
492 | self._value = newValue;
493 | finale(self);
494 | return;
495 | } else if (typeof then === 'function') {
496 | doResolve(bind(then, newValue), self);
497 | return;
498 | }
499 | }
500 | self._state = 1;
501 | self._value = newValue;
502 | finale(self);
503 | } catch (e) {
504 | reject(self, e);
505 | }
506 | }
507 |
508 | function reject(self, newValue) {
509 | self._state = 2;
510 | self._value = newValue;
511 | finale(self);
512 | }
513 |
514 | function finale(self) {
515 | if (self._state === 2 && self._deferreds.length === 0) {
516 | Promise._immediateFn(function() {
517 | if (!self._handled) {
518 | Promise._unhandledRejectionFn(self._value);
519 | }
520 | });
521 | }
522 |
523 | for (var i = 0, len = self._deferreds.length; i < len; i++) {
524 | handle(self, self._deferreds[i]);
525 | }
526 | self._deferreds = null;
527 | }
528 |
529 | /**
530 | * @constructor
531 | */
532 | function Handler(onFulfilled, onRejected, promise) {
533 | this.onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : null;
534 | this.onRejected = typeof onRejected === 'function' ? onRejected : null;
535 | this.promise = promise;
536 | }
537 |
538 | /**
539 | * Take a potentially misbehaving resolver function and make sure
540 | * onFulfilled and onRejected are only called once.
541 | *
542 | * Makes no guarantees about asynchrony.
543 | */
544 | function doResolve(fn, self) {
545 | var done = false;
546 | try {
547 | fn(
548 | function(value) {
549 | if (done) return;
550 | done = true;
551 | resolve(self, value);
552 | },
553 | function(reason) {
554 | if (done) return;
555 | done = true;
556 | reject(self, reason);
557 | }
558 | );
559 | } catch (ex) {
560 | if (done) return;
561 | done = true;
562 | reject(self, ex);
563 | }
564 | }
565 |
566 | Promise.prototype['catch'] = function(onRejected) {
567 | return this.then(null, onRejected);
568 | };
569 |
570 | Promise.prototype.then = function(onFulfilled, onRejected) {
571 | // @ts-ignore
572 | var prom = new this.constructor(noop);
573 |
574 | handle(this, new Handler(onFulfilled, onRejected, prom));
575 | return prom;
576 | };
577 |
578 | Promise.prototype['finally'] = finallyConstructor;
579 |
580 | Promise.all = function(arr) {
581 | return new Promise(function(resolve, reject) {
582 | if (!arr || typeof arr.length === 'undefined')
583 | throw new TypeError('Promise.all accepts an array');
584 | var args = Array.prototype.slice.call(arr);
585 | if (args.length === 0) return resolve([]);
586 | var remaining = args.length;
587 |
588 | function res(i, val) {
589 | try {
590 | if (val && (typeof val === 'object' || typeof val === 'function')) {
591 | var then = val.then;
592 | if (typeof then === 'function') {
593 | then.call(
594 | val,
595 | function(val) {
596 | res(i, val);
597 | },
598 | reject
599 | );
600 | return;
601 | }
602 | }
603 | args[i] = val;
604 | if (--remaining === 0) {
605 | resolve(args);
606 | }
607 | } catch (ex) {
608 | reject(ex);
609 | }
610 | }
611 |
612 | for (var i = 0; i < args.length; i++) {
613 | res(i, args[i]);
614 | }
615 | });
616 | };
617 |
618 | Promise.resolve = function(value) {
619 | if (value && typeof value === 'object' && value.constructor === Promise) {
620 | return value;
621 | }
622 |
623 | return new Promise(function(resolve) {
624 | resolve(value);
625 | });
626 | };
627 |
628 | Promise.reject = function(value) {
629 | return new Promise(function(resolve, reject) {
630 | reject(value);
631 | });
632 | };
633 |
634 | Promise.race = function(values) {
635 | return new Promise(function(resolve, reject) {
636 | for (var i = 0, len = values.length; i < len; i++) {
637 | values[i].then(resolve, reject);
638 | }
639 | });
640 | };
641 |
642 | // Use polyfill for setImmediate for performance gains
643 | Promise._immediateFn =
644 | (typeof setImmediate === 'function' &&
645 | function(fn) {
646 | setImmediate(fn);
647 | }) ||
648 | function(fn) {
649 | setTimeoutFunc(fn, 0);
650 | };
651 |
652 | Promise._unhandledRejectionFn = function _unhandledRejectionFn(err) {
653 | if (typeof console !== 'undefined' && console) {
654 | console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console
655 | }
656 | };
657 |
658 | module.exports = Promise;
659 |
660 | /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./node_modules/@skpm/timers/timeout.js */ "./node_modules/@skpm/timers/timeout.js")["setTimeout"], __webpack_require__(/*! ./node_modules/@skpm/timers/immediate.js */ "./node_modules/@skpm/timers/immediate.js")["setImmediate"]))
661 |
662 | /***/ }),
663 |
664 | /***/ "./node_modules/sketch-module-web-view/lib/browser-api.js":
665 | /*!****************************************************************!*\
666 | !*** ./node_modules/sketch-module-web-view/lib/browser-api.js ***!
667 | \****************************************************************/
668 | /*! no static exports found */
669 | /***/ (function(module, exports) {
670 |
671 | function parseHexColor(color) {
672 | // Check the string for incorrect formatting.
673 | if (!color || color[0] !== '#') {
674 | if (
675 | color &&
676 | typeof color.isKindOfClass === 'function' &&
677 | color.isKindOfClass(NSColor)
678 | ) {
679 | return color
680 | }
681 | throw new Error(
682 | 'Incorrect color formating. It should be an hex color: #RRGGBBAA'
683 | )
684 | }
685 |
686 | // append FF if alpha channel is not specified.
687 | var source = color.substr(1)
688 | if (source.length === 3) {
689 | source += 'F'
690 | } else if (source.length === 6) {
691 | source += 'FF'
692 | }
693 | // Convert the string from #FFF format to #FFFFFF format.
694 | var hex
695 | if (source.length === 4) {
696 | for (var i = 0; i < 4; i += 1) {
697 | hex += source[i]
698 | hex += source[i]
699 | }
700 | } else if (source.length === 8) {
701 | hex = source
702 | } else {
703 | return NSColor.whiteColor()
704 | }
705 |
706 | var r = parseInt(hex.slice(0, 2), 16)
707 | var g = parseInt(hex.slice(2, 4), 16)
708 | var b = parseInt(hex.slice(4, 6), 16)
709 | var a = parseInt(hex.slice(6, 8), 16)
710 |
711 | return NSColor.colorWithSRGBRed_green_blue_alpha(r, g, b, a)
712 | }
713 |
714 | module.exports = function(browserWindow, panel, webview) {
715 | // keep reference to the subviews
716 | browserWindow._panel = panel
717 | browserWindow._webview = webview
718 | browserWindow._destroyed = false
719 |
720 | browserWindow.destroy = function() {
721 | return panel.close()
722 | }
723 |
724 | browserWindow.close = function() {
725 | if (panel.delegate().utils.parentWindow) {
726 | var shouldClose = true
727 | browserWindow.emit('close', {
728 | get defaultPrevented() {
729 | return !shouldClose
730 | },
731 | preventDefault: function() {
732 | shouldClose = false
733 | },
734 | })
735 | if (shouldClose) {
736 | panel.delegate().utils.parentWindow.endSheet(panel)
737 | }
738 | return
739 | }
740 |
741 | if (!browserWindow.isClosable()) {
742 | return
743 | }
744 |
745 | panel.performClose(null)
746 | }
747 |
748 | function focus(focused) {
749 | if (browserWindow.isVisible()) {
750 | return
751 | }
752 | if (focused) {
753 | NSApplication.sharedApplication().activateIgnoringOtherApps(true)
754 | panel.makeKeyAndOrderFront(null)
755 | } else {
756 | panel.orderBack(null)
757 | }
758 | }
759 |
760 | browserWindow.focus = focus.bind(this, true)
761 | browserWindow.blur = focus.bind(this, false)
762 |
763 | browserWindow.isFocused = function() {
764 | return panel.isKeyWindow()
765 | }
766 |
767 | browserWindow.isDestroyed = function() {
768 | return browserWindow._destroyed
769 | }
770 |
771 | browserWindow.show = function() {
772 | // This method is supposed to put focus on window, however if the app does not
773 | // have focus then "makeKeyAndOrderFront" will only show the window.
774 | NSApp.activateIgnoringOtherApps(true)
775 |
776 | if (panel.delegate().utils.parentWindow) {
777 | return panel.delegate().utils.parentWindow.beginSheet_completionHandler(
778 | panel,
779 | __mocha__.createBlock_function('v16@?0q8', function() {
780 | browserWindow.emit('closed')
781 | })
782 | )
783 | }
784 |
785 | return panel.makeKeyAndOrderFront(null)
786 | }
787 |
788 | browserWindow.showInactive = function() {
789 | return panel.orderFrontRegardless()
790 | }
791 |
792 | browserWindow.hide = function() {
793 | return panel.orderOut(null)
794 | }
795 |
796 | browserWindow.isVisible = function() {
797 | return panel.isVisible()
798 | }
799 |
800 | browserWindow.isModal = function() {
801 | return false
802 | }
803 |
804 | browserWindow.maximize = function() {
805 | if (!browserWindow.isMaximized()) {
806 | panel.zoom(null)
807 | }
808 | }
809 | browserWindow.unmaximize = function() {
810 | if (browserWindow.isMaximized()) {
811 | panel.zoom(null)
812 | }
813 | }
814 |
815 | browserWindow.isMaximized = function() {
816 | if ((panel.styleMask() & NSResizableWindowMask) !== 0) {
817 | return panel.isZoomed()
818 | }
819 | var rectScreen = NSScreen.mainScreen().visibleFrame()
820 | var rectWindow = panel.frame()
821 | return (
822 | rectScreen.origin.x == rectWindow.origin.x &&
823 | rectScreen.origin.y == rectWindow.origin.y &&
824 | rectScreen.size.width == rectWindow.size.width &&
825 | rectScreen.size.height == rectWindow.size.height
826 | )
827 | }
828 |
829 | browserWindow.minimize = function() {
830 | return panel.miniaturize(null)
831 | }
832 |
833 | browserWindow.restore = function() {
834 | return panel.deminiaturize(null)
835 | }
836 |
837 | browserWindow.isMinimized = function() {
838 | return panel.isMiniaturized()
839 | }
840 |
841 | browserWindow.setFullScreen = function(fullscreen) {
842 | if (fullscreen !== browserWindow.isFullscreen()) {
843 | panel.toggleFullScreen(null)
844 | }
845 | }
846 |
847 | browserWindow.isFullscreen = function() {
848 | return panel.styleMask() & NSFullScreenWindowMask
849 | }
850 |
851 | browserWindow.setAspectRatio = function(aspectRatio /* , extraSize */) {
852 | // Reset the behaviour to default if aspect_ratio is set to 0 or less.
853 | if (aspectRatio > 0.0) {
854 | panel.setAspectRatio(NSMakeSize(aspectRatio, 1.0))
855 | } else {
856 | panel.setResizeIncrements(NSMakeSize(1.0, 1.0))
857 | }
858 | }
859 |
860 | browserWindow.setBounds = function(bounds, animate) {
861 | if (!bounds) {
862 | return
863 | }
864 |
865 | // Do nothing if in fullscreen mode.
866 | if (browserWindow.isFullscreen()) {
867 | return
868 | }
869 |
870 | const newBounds = Object.assign(browserWindow.getBounds(), bounds)
871 |
872 | // TODO: Check size constraints since setFrame does not check it.
873 | // var size = bounds.size
874 | // size.SetToMax(GetMinimumSize());
875 | // gfx::Size max_size = GetMaximumSize();
876 | // if (!max_size.IsEmpty())
877 | // size.SetToMin(max_size);
878 |
879 | var cocoaBounds = NSMakeRect(
880 | newBounds.x,
881 | 0,
882 | newBounds.width,
883 | newBounds.height
884 | )
885 | // Flip Y coordinates based on the primary screen
886 | var screen = NSScreen.screens().firstObject()
887 | cocoaBounds.origin.y = NSHeight(screen.frame()) - newBounds.y
888 |
889 | panel.setFrame_display_animate(cocoaBounds, true, animate)
890 | }
891 |
892 | browserWindow.getBounds = function() {
893 | const cocoaBounds = panel.frame()
894 | var mainScreenRect = NSScreen.screens()
895 | .firstObject()
896 | .frame()
897 | return {
898 | x: cocoaBounds.origin.x,
899 | y: Math.round(NSHeight(mainScreenRect) - cocoaBounds.origin.y),
900 | width: cocoaBounds.size.width,
901 | height: cocoaBounds.size.height,
902 | }
903 | }
904 |
905 | browserWindow.setContentBounds = function(bounds, animate) {
906 | // TODO:
907 | browserWindow.setBounds(bounds, animate)
908 | }
909 |
910 | browserWindow.getContentBounds = function() {
911 | // TODO:
912 | return browserWindow.getBounds()
913 | }
914 |
915 | browserWindow.setSize = function(width, height, animate) {
916 | // TODO: handle resizing around center
917 | return browserWindow.setBounds({ width: width, height: height }, animate)
918 | }
919 |
920 | browserWindow.getSize = function() {
921 | var bounds = browserWindow.getBounds()
922 | return [bounds.width, bounds.height]
923 | }
924 |
925 | browserWindow.setContentSize = function(width, height, animate) {
926 | // TODO: handle resizing around center
927 | return browserWindow.setContentBounds(
928 | { width: width, height: height },
929 | animate
930 | )
931 | }
932 |
933 | browserWindow.getContentSize = function() {
934 | var bounds = browserWindow.getContentBounds()
935 | return [bounds.width, bounds.height]
936 | }
937 |
938 | browserWindow.setMinimumSize = function(width, height) {
939 | const minSize = CGSizeMake(width, height)
940 | panel.setContentMinSize(minSize)
941 | }
942 |
943 | browserWindow.getMinimumSize = function() {
944 | const size = panel.contentMinSize()
945 | return [size.width, size.height]
946 | }
947 |
948 | browserWindow.setMaximumSize = function(width, height) {
949 | const maxSize = CGSizeMake(width, height)
950 | panel.setContentMaxSize(maxSize)
951 | }
952 |
953 | browserWindow.getMaximumSize = function() {
954 | const size = panel.contentMaxSize()
955 | return [size.width, size.height]
956 | }
957 |
958 | browserWindow.setResizable = function(resizable) {
959 | return browserWindow._setStyleMask(resizable, NSResizableWindowMask)
960 | }
961 |
962 | browserWindow.isResizable = function() {
963 | return panel.styleMask() & NSResizableWindowMask
964 | }
965 |
966 | browserWindow.setMovable = function(movable) {
967 | return panel.setMovable(movable)
968 | }
969 | browserWindow.isMovable = function() {
970 | return panel.isMovable()
971 | }
972 |
973 | browserWindow.setMinimizable = function(minimizable) {
974 | return browserWindow._setStyleMask(minimizable, NSMiniaturizableWindowMask)
975 | }
976 |
977 | browserWindow.isMinimizable = function() {
978 | return panel.styleMask() & NSMiniaturizableWindowMask
979 | }
980 |
981 | browserWindow.setMaximizable = function(maximizable) {
982 | if (panel.standardWindowButton(NSWindowZoomButton)) {
983 | panel.standardWindowButton(NSWindowZoomButton).setEnabled(maximizable)
984 | }
985 | }
986 |
987 | browserWindow.isMaximizable = function() {
988 | return (
989 | panel.standardWindowButton(NSWindowZoomButton) &&
990 | panel.standardWindowButton(NSWindowZoomButton).isEnabled()
991 | )
992 | }
993 |
994 | browserWindow.setFullScreenable = function(fullscreenable) {
995 | browserWindow._setCollectionBehavior(
996 | fullscreenable,
997 | NSWindowCollectionBehaviorFullScreenPrimary
998 | )
999 | // On EL Capitan this flag is required to hide fullscreen button.
1000 | browserWindow._setCollectionBehavior(
1001 | !fullscreenable,
1002 | NSWindowCollectionBehaviorFullScreenAuxiliary
1003 | )
1004 | }
1005 |
1006 | browserWindow.isFullScreenable = function() {
1007 | var collectionBehavior = panel.collectionBehavior()
1008 | return collectionBehavior & NSWindowCollectionBehaviorFullScreenPrimary
1009 | }
1010 |
1011 | browserWindow.setClosable = function(closable) {
1012 | browserWindow._setStyleMask(closable, NSClosableWindowMask)
1013 | }
1014 |
1015 | browserWindow.isClosable = function() {
1016 | return panel.styleMask() & NSClosableWindowMask
1017 | }
1018 |
1019 | browserWindow.setAlwaysOnTop = function(top, level, relativeLevel) {
1020 | var windowLevel = NSNormalWindowLevel
1021 | var maxWindowLevel = CGWindowLevelForKey(kCGMaximumWindowLevelKey)
1022 | var minWindowLevel = CGWindowLevelForKey(kCGMinimumWindowLevelKey)
1023 |
1024 | if (top) {
1025 | if (level === 'normal') {
1026 | windowLevel = NSNormalWindowLevel
1027 | } else if (level === 'torn-off-menu') {
1028 | windowLevel = NSTornOffMenuWindowLevel
1029 | } else if (level === 'modal-panel') {
1030 | windowLevel = NSModalPanelWindowLevel
1031 | } else if (level === 'main-menu') {
1032 | windowLevel = NSMainMenuWindowLevel
1033 | } else if (level === 'status') {
1034 | windowLevel = NSStatusWindowLevel
1035 | } else if (level === 'pop-up-menu') {
1036 | windowLevel = NSPopUpMenuWindowLevel
1037 | } else if (level === 'screen-saver') {
1038 | windowLevel = NSScreenSaverWindowLevel
1039 | } else if (level === 'dock') {
1040 | // Deprecated by macOS, but kept for backwards compatibility
1041 | windowLevel = NSDockWindowLevel
1042 | } else {
1043 | windowLevel = NSFloatingWindowLevel
1044 | }
1045 | }
1046 |
1047 | var newLevel = windowLevel + (relativeLevel || 0)
1048 | if (newLevel >= minWindowLevel && newLevel <= maxWindowLevel) {
1049 | panel.setLevel(newLevel)
1050 | } else {
1051 | throw new Error(
1052 | 'relativeLevel must be between ' +
1053 | minWindowLevel +
1054 | ' and ' +
1055 | maxWindowLevel
1056 | )
1057 | }
1058 | }
1059 |
1060 | browserWindow.isAlwaysOnTop = function() {
1061 | return panel.level() !== NSNormalWindowLevel
1062 | }
1063 |
1064 | browserWindow.moveTop = function() {
1065 | return panel.orderFrontRegardless()
1066 | }
1067 |
1068 | browserWindow.center = function() {
1069 | panel.center()
1070 | }
1071 |
1072 | browserWindow.setPosition = function(x, y, animate) {
1073 | return browserWindow.setBounds({ x: x, y: y }, animate)
1074 | }
1075 |
1076 | browserWindow.getPosition = function() {
1077 | var bounds = browserWindow.getBounds()
1078 | return [bounds.x, bounds.y]
1079 | }
1080 |
1081 | browserWindow.setTitle = function(title) {
1082 | panel.setTitle(title)
1083 | }
1084 |
1085 | browserWindow.getTitle = function() {
1086 | return String(panel.title())
1087 | }
1088 |
1089 | var attentionRequestId = 0
1090 | browserWindow.flashFrame = function(flash) {
1091 | if (flash) {
1092 | attentionRequestId = NSApp.requestUserAttention(NSInformationalRequest)
1093 | } else {
1094 | NSApp.cancelUserAttentionRequest(attentionRequestId)
1095 | attentionRequestId = 0
1096 | }
1097 | }
1098 |
1099 | browserWindow.getNativeWindowHandle = function() {
1100 | return panel
1101 | }
1102 |
1103 | browserWindow.getNativeWebViewHandle = function() {
1104 | return webview
1105 | }
1106 |
1107 | browserWindow.loadURL = function(url) {
1108 | // When frameLocation is a file, prefix it with the Sketch Resources path
1109 | if (/^(?!https?|file).*\.html?$/.test(url)) {
1110 | if (typeof __command !== 'undefined' && __command.pluginBundle()) {
1111 | url =
1112 | 'file://' +
1113 | __command
1114 | .pluginBundle()
1115 | .urlForResourceNamed(url)
1116 | .path()
1117 | }
1118 | }
1119 |
1120 | if (/^file:\/\/.*\.html?$/.test(url)) {
1121 | webview.loadFileURL_allowingReadAccessToURL(
1122 | NSURL.fileURLWithPath(url),
1123 | NSURL.fileURLWithPath('file:///')
1124 | )
1125 | return
1126 | }
1127 |
1128 | const properURL = NSURL.URLWithString(url)
1129 | const urlRequest = NSURLRequest.requestWithURL(properURL)
1130 |
1131 | webview.loadRequest(urlRequest)
1132 | }
1133 |
1134 | browserWindow.reload = function() {
1135 | webview.reload()
1136 | }
1137 |
1138 | browserWindow.setHasShadow = function(hasShadow) {
1139 | return panel.setHasShadow(hasShadow)
1140 | }
1141 |
1142 | browserWindow.hasShadow = function() {
1143 | return panel.hasShadow()
1144 | }
1145 |
1146 | browserWindow.setOpacity = function(opacity) {
1147 | return panel.setAlphaValue(opacity)
1148 | }
1149 |
1150 | browserWindow.getOpacity = function() {
1151 | return panel.alphaValue()
1152 | }
1153 |
1154 | browserWindow.setVisibleOnAllWorkspaces = function(visible) {
1155 | return browserWindow._setCollectionBehavior(
1156 | visible,
1157 | NSWindowCollectionBehaviorCanJoinAllSpaces
1158 | )
1159 | }
1160 |
1161 | browserWindow.isVisibleOnAllWorkspaces = function() {
1162 | var collectionBehavior = panel.collectionBehavior()
1163 | return collectionBehavior & NSWindowCollectionBehaviorCanJoinAllSpaces
1164 | }
1165 |
1166 | browserWindow.setIgnoreMouseEvents = function(ignore) {
1167 | return panel.setIgnoresMouseEvents(ignore)
1168 | }
1169 |
1170 | browserWindow.setContentProtection = function(enable) {
1171 | panel.setSharingType(enable ? NSWindowSharingNone : NSWindowSharingReadOnly)
1172 | }
1173 |
1174 | browserWindow.setAutoHideCursor = function(autoHide) {
1175 | panel.setDisableAutoHideCursor(autoHide)
1176 | }
1177 |
1178 | browserWindow.setVibrancy = function(type) {
1179 | var effectView = browserWindow._vibrantView
1180 |
1181 | if (!type) {
1182 | if (effectView == null) {
1183 | return
1184 | }
1185 |
1186 | effectView.removeFromSuperview()
1187 | panel.setVibrantView(null)
1188 | return
1189 | }
1190 |
1191 | if (effectView == null) {
1192 | var contentView = panel.contentView()
1193 | effectView = NSVisualEffectView.alloc().initWithFrame(
1194 | contentView.bounds()
1195 | )
1196 | browserWindow._vibrantView = effectView
1197 |
1198 | effectView.setAutoresizingMask(NSViewWidthSizable | NSViewHeightSizable)
1199 | effectView.setBlendingMode(NSVisualEffectBlendingModeBehindWindow)
1200 | effectView.setState(NSVisualEffectStateActive)
1201 | effectView.setFrame(contentView.bounds())
1202 | contentView.addSubview_positioned_relativeTo(
1203 | effectView,
1204 | NSWindowBelow,
1205 | null
1206 | )
1207 | }
1208 |
1209 | var vibrancyType = NSVisualEffectMaterialLight
1210 |
1211 | if (type === 'appearance-based') {
1212 | vibrancyType = NSVisualEffectMaterialAppearanceBased
1213 | } else if (type === 'light') {
1214 | vibrancyType = NSVisualEffectMaterialLight
1215 | } else if (type === 'dark') {
1216 | vibrancyType = NSVisualEffectMaterialDark
1217 | } else if (type === 'titlebar') {
1218 | vibrancyType = NSVisualEffectMaterialTitlebar
1219 | } else if (type === 'selection') {
1220 | vibrancyType = NSVisualEffectMaterialSelection
1221 | } else if (type === 'menu') {
1222 | vibrancyType = NSVisualEffectMaterialMenu
1223 | } else if (type === 'popover') {
1224 | vibrancyType = NSVisualEffectMaterialPopover
1225 | } else if (type === 'sidebar') {
1226 | vibrancyType = NSVisualEffectMaterialSidebar
1227 | } else if (type === 'medium-light') {
1228 | vibrancyType = NSVisualEffectMaterialMediumLight
1229 | } else if (type === 'ultra-dark') {
1230 | vibrancyType = NSVisualEffectMaterialUltraDark
1231 | }
1232 |
1233 | effectView.setMaterial(vibrancyType)
1234 | }
1235 |
1236 | browserWindow._setBackgroundColor = function(colorName) {
1237 | var color = parseHexColor(colorName)
1238 | webview.setValue_forKey(false, 'drawsBackground')
1239 | panel.backgroundColor = color
1240 | }
1241 |
1242 | browserWindow._invalidate = function() {
1243 | panel.flushWindow()
1244 | panel.contentView().setNeedsDisplay(true)
1245 | }
1246 |
1247 | browserWindow._setStyleMask = function(on, flag) {
1248 | var wasMaximizable = browserWindow.isMaximizable()
1249 | if (on) {
1250 | panel.setStyleMask(panel.styleMask() | flag)
1251 | } else {
1252 | panel.setStyleMask(panel.styleMask() & ~flag)
1253 | }
1254 | // Change style mask will make the zoom button revert to default, probably
1255 | // a bug of Cocoa or macOS.
1256 | browserWindow.setMaximizable(wasMaximizable)
1257 | }
1258 |
1259 | browserWindow._setCollectionBehavior = function(on, flag) {
1260 | var wasMaximizable = browserWindow.isMaximizable()
1261 | if (on) {
1262 | panel.setCollectionBehavior(panel.collectionBehavior() | flag)
1263 | } else {
1264 | panel.setCollectionBehavior(panel.collectionBehavior() & ~flag)
1265 | }
1266 | // Change collectionBehavior will make the zoom button revert to default,
1267 | // probably a bug of Cocoa or macOS.
1268 | browserWindow.setMaximizable(wasMaximizable)
1269 | }
1270 |
1271 | browserWindow._showWindowButton = function(button) {
1272 | var view = panel.standardWindowButton(button)
1273 | view.superview().addSubview_positioned_relative(view, NSWindowAbove, null)
1274 | }
1275 | }
1276 |
1277 |
1278 | /***/ }),
1279 |
1280 | /***/ "./node_modules/sketch-module-web-view/lib/constants.js":
1281 | /*!**************************************************************!*\
1282 | !*** ./node_modules/sketch-module-web-view/lib/constants.js ***!
1283 | \**************************************************************/
1284 | /*! no static exports found */
1285 | /***/ (function(module, exports) {
1286 |
1287 | module.exports = {
1288 | JS_BRIDGE: '__skpm_sketchBridge',
1289 | START_MOVING_WINDOW: '__skpm_startMovingWindow',
1290 | STOP_MOVING_WINDOW: '__skpm_stopMovingWindow',
1291 | MOVE_WINDOW: '__skpm_moveWindow',
1292 | EXECUTE_JAVASCRIPT: '__skpm_executeJS',
1293 | EXECUTE_JAVASCRIPT_SUCCESS: '__skpm_executeJS_success_',
1294 | EXECUTE_JAVASCRIPT_ERROR: '__skpm_executeJS_error_',
1295 | }
1296 |
1297 |
1298 | /***/ }),
1299 |
1300 | /***/ "./node_modules/sketch-module-web-view/lib/dispatch-first-click.js":
1301 | /*!*************************************************************************!*\
1302 | !*** ./node_modules/sketch-module-web-view/lib/dispatch-first-click.js ***!
1303 | \*************************************************************************/
1304 | /*! no static exports found */
1305 | /***/ (function(module, exports) {
1306 |
1307 | var tagsToFocus =
1308 | '["text", "textarea", "date", "datetime-local", "email", "number", "month", "password", "search", "tel", "time", "url", "week" ]'
1309 |
1310 | module.exports = function(webView, event) {
1311 | var point = webView.convertPoint_fromView(event.locationInWindow(), null)
1312 | var x = point.x
1313 | var y = webView.frame().size.height - point.y // the coord start from the bottom instead of the top
1314 | return (
1315 | 'var el = document.elementFromPoint(' + // get the DOM element that match the event
1316 | x +
1317 | ', ' +
1318 | y +
1319 | '); ' +
1320 | 'if (el && ' + // some tags need to be focused instead of clicked
1321 | tagsToFocus +
1322 | '.indexOf(el.type) >= 0 && ' +
1323 | 'el.focus' +
1324 | ') {' +
1325 | 'el.focus();' + // so focus them
1326 | '} else if (el) {' +
1327 | 'el.dispatchEvent(new Event("click", {bubbles: true}))' + // click the others
1328 | '}'
1329 | )
1330 | }
1331 |
1332 |
1333 | /***/ }),
1334 |
1335 | /***/ "./node_modules/sketch-module-web-view/lib/execute-javascript.js":
1336 | /*!***********************************************************************!*\
1337 | !*** ./node_modules/sketch-module-web-view/lib/execute-javascript.js ***!
1338 | \***********************************************************************/
1339 | /*! no static exports found */
1340 | /***/ (function(module, exports, __webpack_require__) {
1341 |
1342 | /* WEBPACK VAR INJECTION */(function(Promise) {var CONSTANTS = __webpack_require__(/*! ./constants */ "./node_modules/sketch-module-web-view/lib/constants.js")
1343 |
1344 | module.exports = function(webview, browserWindow) {
1345 | function executeJavaScript(script, userGesture, callback) {
1346 | if (typeof userGesture === 'function') {
1347 | callback = userGesture
1348 | userGesture = false
1349 | }
1350 | var fiber = coscript.createFiber()
1351 |
1352 | // if the webview is not ready yet, defer the execution until it is
1353 | if (webview.navigationDelegate().valueForKey('state').wasReady == 0) {
1354 | return new Promise(function(resolve, reject) {
1355 | browserWindow.once('ready-to-show', function() {
1356 | executeJavaScript(script, userGesture, callback)
1357 | .then(resolve)
1358 | .catch(reject)
1359 | fiber.cleanup()
1360 | })
1361 | })
1362 | }
1363 |
1364 | return new Promise(function(resolve, reject) {
1365 | var requestId = Math.random()
1366 |
1367 | browserWindow.webContents.on(
1368 | CONSTANTS.EXECUTE_JAVASCRIPT_SUCCESS + requestId,
1369 | function(res) {
1370 | try {
1371 | if (callback) {
1372 | callback(null, res)
1373 | }
1374 | resolve(res)
1375 | } catch (_) {
1376 | // /shrug
1377 | }
1378 | fiber.cleanup()
1379 | }
1380 | )
1381 | browserWindow.webContents.on(
1382 | CONSTANTS.EXECUTE_JAVASCRIPT_ERROR + requestId,
1383 | function(err) {
1384 | try {
1385 | if (callback) {
1386 | callback(err)
1387 | resolve()
1388 | } else {
1389 | reject(err)
1390 | }
1391 | } catch (_) {
1392 | // /shrug
1393 | }
1394 | fiber.cleanup()
1395 | }
1396 | )
1397 |
1398 | webview.evaluateJavaScript_completionHandler(
1399 | 'window.' +
1400 | CONSTANTS.EXECUTE_JAVASCRIPT +
1401 | '(' +
1402 | requestId +
1403 | ', "' +
1404 | script.replace(/"/g, '\\"') +
1405 | '")',
1406 | null
1407 | )
1408 | })
1409 | }
1410 |
1411 | return executeJavaScript
1412 | }
1413 |
1414 | module.exports.injectScript = function(webView) {
1415 | var source =
1416 | 'window.' +
1417 | CONSTANTS.EXECUTE_JAVASCRIPT +
1418 | ' = function(id, script) {' +
1419 | ' try {' +
1420 | ' var res = eval(script);' +
1421 | ' if (res && typeof res.then === "function" && typeof res.catch === "function") {' +
1422 | ' res.then(function (res2) {' +
1423 | ' window.postMessage("' +
1424 | CONSTANTS.EXECUTE_JAVASCRIPT_SUCCESS +
1425 | '" + id, res2);' +
1426 | ' })' +
1427 | ' .catch(function (err) {' +
1428 | ' window.postMessage("' +
1429 | CONSTANTS.EXECUTE_JAVASCRIPT_ERROR +
1430 | '" + id, err);' +
1431 | ' })' +
1432 | ' } else {' +
1433 | ' window.postMessage("' +
1434 | CONSTANTS.EXECUTE_JAVASCRIPT_SUCCESS +
1435 | '" + id, res);' +
1436 | ' }' +
1437 | ' } catch (err) {' +
1438 | ' window.postMessage("' +
1439 | CONSTANTS.EXECUTE_JAVASCRIPT_ERROR +
1440 | '" + id, err);' +
1441 | ' }' +
1442 | '}'
1443 | var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(
1444 | source,
1445 | 0,
1446 | true
1447 | )
1448 | webView
1449 | .configuration()
1450 | .userContentController()
1451 | .addUserScript(script)
1452 | }
1453 |
1454 | /* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./node_modules/promise-polyfill/lib/index.js */ "./node_modules/promise-polyfill/lib/index.js")))
1455 |
1456 | /***/ }),
1457 |
1458 | /***/ "./node_modules/sketch-module-web-view/lib/fitSubview.js":
1459 | /*!***************************************************************!*\
1460 | !*** ./node_modules/sketch-module-web-view/lib/fitSubview.js ***!
1461 | \***************************************************************/
1462 | /*! no static exports found */
1463 | /***/ (function(module, exports) {
1464 |
1465 | function addEdgeConstraint(edge, subview, view, constant) {
1466 | view.addConstraint(
1467 | NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant(
1468 | subview,
1469 | edge,
1470 | NSLayoutRelationEqual,
1471 | view,
1472 | edge,
1473 | 1,
1474 | constant
1475 | )
1476 | )
1477 | }
1478 | module.exports = function fitSubviewToView(subview, view, constants) {
1479 | constants = constants || []
1480 | subview.setTranslatesAutoresizingMaskIntoConstraints(false)
1481 |
1482 | addEdgeConstraint(NSLayoutAttributeLeft, subview, view, constants[0] || 0)
1483 | addEdgeConstraint(NSLayoutAttributeTop, subview, view, constants[1] || 0)
1484 | addEdgeConstraint(NSLayoutAttributeRight, subview, view, constants[2] || 0)
1485 | addEdgeConstraint(NSLayoutAttributeBottom, subview, view, constants[3] || 0)
1486 | }
1487 |
1488 |
1489 | /***/ }),
1490 |
1491 | /***/ "./node_modules/sketch-module-web-view/lib/index.js":
1492 | /*!**********************************************************!*\
1493 | !*** ./node_modules/sketch-module-web-view/lib/index.js ***!
1494 | \**********************************************************/
1495 | /*! no static exports found */
1496 | /***/ (function(module, exports, __webpack_require__) {
1497 |
1498 | /* let's try to match the API from Electron's Browser window
1499 | (https://github.com/electron/electron/blob/master/docs/api/browser-window.md) */
1500 | var EventEmitter = __webpack_require__(/*! events */ "events")
1501 | var buildBrowserAPI = __webpack_require__(/*! ./browser-api */ "./node_modules/sketch-module-web-view/lib/browser-api.js")
1502 | var buildWebAPI = __webpack_require__(/*! ./webview-api */ "./node_modules/sketch-module-web-view/lib/webview-api.js")
1503 | var fitSubviewToView = __webpack_require__(/*! ./fitSubview */ "./node_modules/sketch-module-web-view/lib/fitSubview.js")
1504 | var dispatchFirstClick = __webpack_require__(/*! ./dispatch-first-click */ "./node_modules/sketch-module-web-view/lib/dispatch-first-click.js")
1505 | var injectClientMessaging = __webpack_require__(/*! ./inject-client-messaging */ "./node_modules/sketch-module-web-view/lib/inject-client-messaging.js")
1506 | var movableArea = __webpack_require__(/*! ./movable-area */ "./node_modules/sketch-module-web-view/lib/movable-area.js")
1507 | var executeJavaScript = __webpack_require__(/*! ./execute-javascript */ "./node_modules/sketch-module-web-view/lib/execute-javascript.js")
1508 | var setDelegates = __webpack_require__(/*! ./set-delegates */ "./node_modules/sketch-module-web-view/lib/set-delegates.js")
1509 |
1510 | function BrowserWindow(options) {
1511 | options = options || {}
1512 |
1513 | var identifier = options.identifier || NSUUID.UUID().UUIDString()
1514 | var threadDictionary = NSThread.mainThread().threadDictionary()
1515 |
1516 | var existingBrowserWindow = BrowserWindow.fromId(identifier)
1517 |
1518 | // if we already have a window opened, reuse it
1519 | if (existingBrowserWindow) {
1520 | return existingBrowserWindow
1521 | }
1522 |
1523 | var browserWindow = new EventEmitter()
1524 | browserWindow.id = identifier
1525 |
1526 | if (options.modal && !options.parent) {
1527 | throw new Error('A modal needs to have a parent.')
1528 | }
1529 |
1530 | // Long-running script
1531 | var fiber = coscript.createFiber()
1532 |
1533 | // Window size
1534 | var width = options.width || 800
1535 | var height = options.height || 600
1536 | var mainScreenRect = NSScreen.screens()
1537 | .firstObject()
1538 | .frame()
1539 | var cocoaBounds = NSMakeRect(
1540 | typeof options.x !== 'undefined'
1541 | ? options.x
1542 | : Math.round((NSWidth(mainScreenRect) - width) / 2),
1543 | typeof options.y !== 'undefined'
1544 | ? NSHeight(mainScreenRect) - options.y
1545 | : Math.round((NSHeight(mainScreenRect) - height) / 2),
1546 | width,
1547 | height
1548 | )
1549 |
1550 | if (options.titleBarStyle && options.titleBarStyle !== 'default') {
1551 | options.frame = false
1552 | }
1553 |
1554 | var useStandardWindow = options.windowType !== 'textured'
1555 | var styleMask = NSTitledWindowMask
1556 |
1557 | // this is commented out because the toolbar doesn't appear otherwise :thinking-face:
1558 | // if (!useStandardWindow || options.frame === false) {
1559 | // styleMask = NSFullSizeContentViewWindowMask
1560 | // }
1561 | if (options.minimizable !== false) {
1562 | styleMask |= NSMiniaturizableWindowMask
1563 | }
1564 | if (options.closable !== false) {
1565 | styleMask |= NSClosableWindowMask
1566 | }
1567 | if (options.resizable !== false) {
1568 | styleMask |= NSResizableWindowMask
1569 | }
1570 | if (!useStandardWindow || options.transparent || options.frame === false) {
1571 | styleMask |= NSTexturedBackgroundWindowMask
1572 | }
1573 |
1574 | var panel = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(
1575 | cocoaBounds,
1576 | styleMask,
1577 | NSBackingStoreBuffered,
1578 | true
1579 | )
1580 |
1581 | var wkwebviewConfig = WKWebViewConfiguration.alloc().init()
1582 | var webView = WKWebView.alloc().initWithFrame_configuration(
1583 | CGRectMake(0, 0, options.width || 800, options.height || 600),
1584 | wkwebviewConfig
1585 | )
1586 | injectClientMessaging(webView)
1587 | webView.setAutoresizingMask(NSViewWidthSizable | NSViewHeightSizable)
1588 |
1589 | buildBrowserAPI(browserWindow, panel, webView)
1590 | buildWebAPI(browserWindow, panel, webView)
1591 | setDelegates(browserWindow, panel, webView, options)
1592 |
1593 | if (options.windowType === 'desktop') {
1594 | panel.setLevel(kCGDesktopWindowLevel - 1)
1595 | // panel.setCanBecomeKeyWindow(false)
1596 | panel.setCollectionBehavior(
1597 | NSWindowCollectionBehaviorCanJoinAllSpaces |
1598 | NSWindowCollectionBehaviorStationary |
1599 | NSWindowCollectionBehaviorIgnoresCycle
1600 | )
1601 | }
1602 |
1603 | if (
1604 | typeof options.minWidth !== 'undefined' ||
1605 | typeof options.minHeight !== 'undefined'
1606 | ) {
1607 | browserWindow.setMinimumSize(options.minWidth || 0, options.minHeight || 0)
1608 | }
1609 |
1610 | if (
1611 | typeof options.maxWidth !== 'undefined' ||
1612 | typeof options.maxHeight !== 'undefined'
1613 | ) {
1614 | browserWindow.setMaximumSize(
1615 | options.maxWidth || 10000,
1616 | options.maxHeight || 10000
1617 | )
1618 | }
1619 |
1620 | // if (options.focusable === false) {
1621 | // panel.setCanBecomeKeyWindow(false)
1622 | // }
1623 |
1624 | if (options.transparent || options.frame === false) {
1625 | panel.titlebarAppearsTransparent = true
1626 | panel.titleVisibility = NSWindowTitleHidden
1627 | panel.setOpaque(0)
1628 | panel.isMovableByWindowBackground = true
1629 | var toolbar2 = NSToolbar.alloc().initWithIdentifier(
1630 | 'titlebarStylingToolbar'
1631 | )
1632 | toolbar2.setShowsBaselineSeparator(false)
1633 | panel.setToolbar(toolbar2)
1634 | }
1635 |
1636 | if (options.titleBarStyle === 'hiddenInset') {
1637 | var toolbar = NSToolbar.alloc().initWithIdentifier('titlebarStylingToolbar')
1638 | toolbar.setShowsBaselineSeparator(false)
1639 | panel.setToolbar(toolbar)
1640 | }
1641 |
1642 | if (options.frame === false || !options.useContentSize) {
1643 | browserWindow.setSize(width, height)
1644 | }
1645 |
1646 | if (options.center) {
1647 | browserWindow.center()
1648 | }
1649 |
1650 | if (options.alwaysOnTop) {
1651 | browserWindow.setAlwaysOnTop(true)
1652 | }
1653 |
1654 | if (options.fullscreen) {
1655 | browserWindow.setFullScreen(true)
1656 | }
1657 | browserWindow.setFullScreenable(!!options.fullscreenable)
1658 |
1659 | const title =
1660 | options.title ||
1661 | (typeof __command !== 'undefined' && __command.pluginBundle()
1662 | ? __command.pluginBundle().name()
1663 | : undefined)
1664 | if (title) {
1665 | browserWindow.setTitle(title)
1666 | }
1667 |
1668 | var backgroundColor = options.backgroundColor
1669 | if (options.transparent) {
1670 | backgroundColor = NSColor.clearColor()
1671 | }
1672 | if (!backgroundColor && options.frame === false && options.vibrancy) {
1673 | backgroundColor = NSColor.clearColor()
1674 | }
1675 |
1676 | browserWindow._setBackgroundColor(
1677 | backgroundColor || NSColor.windowBackgroundColor()
1678 | )
1679 |
1680 | if (options.hasShadow === false) {
1681 | browserWindow.setHasShadow(false)
1682 | }
1683 |
1684 | if (typeof options.opacity !== 'undefined') {
1685 | browserWindow.setOpacity(options.opacity)
1686 | }
1687 |
1688 | options.webPreferences = options.webPreferences || {}
1689 |
1690 | webView
1691 | .configuration()
1692 | .preferences()
1693 | .setValue_forKey(
1694 | options.webPreferences.devTools !== false,
1695 | 'developerExtrasEnabled'
1696 | )
1697 | webView
1698 | .configuration()
1699 | .preferences()
1700 | .setValue_forKey(
1701 | options.webPreferences.javascript !== false,
1702 | 'javaScriptEnabled'
1703 | )
1704 | webView
1705 | .configuration()
1706 | .preferences()
1707 | .setValue_forKey(!!options.webPreferences.plugins, 'plugInsEnabled')
1708 | webView
1709 | .configuration()
1710 | .preferences()
1711 | .setValue_forKey(
1712 | options.webPreferences.minimumFontSize || 0,
1713 | 'minimumFontSize'
1714 | )
1715 |
1716 | if (options.webPreferences.zoomFactor) {
1717 | webView.setMagnification(options.webPreferences.zoomFactor)
1718 | }
1719 |
1720 | var contentView = panel.contentView()
1721 |
1722 | if (options.frame !== false) {
1723 | webView.setFrame(contentView.bounds())
1724 | contentView.addSubview(webView)
1725 | } else {
1726 | // In OSX 10.10, adding subviews to the root view for the NSView hierarchy
1727 | // produces warnings. To eliminate the warnings, we resize the contentView
1728 | // to fill the window, and add subviews to that.
1729 | // http://crbug.com/380412
1730 | contentView.setAutoresizingMask(NSViewWidthSizable | NSViewHeightSizable)
1731 | fitSubviewToView(contentView, contentView.superview())
1732 |
1733 | webView.setFrame(contentView.bounds())
1734 | contentView.addSubview(webView)
1735 |
1736 | // The fullscreen button should always be hidden for frameless window.
1737 | if (panel.standardWindowButton(NSWindowFullScreenButton)) {
1738 | panel.standardWindowButton(NSWindowFullScreenButton).setHidden(true)
1739 | }
1740 |
1741 | if (!options.titleBarStyle || options.titleBarStyle === 'default') {
1742 | // Hide the window buttons.
1743 | panel.standardWindowButton(NSWindowZoomButton).setHidden(true)
1744 | panel.standardWindowButton(NSWindowMiniaturizeButton).setHidden(true)
1745 | panel.standardWindowButton(NSWindowCloseButton).setHidden(true)
1746 |
1747 | // Some third-party macOS utilities check the zoom button's enabled state to
1748 | // determine whether to show custom UI on hover, so we disable it here to
1749 | // prevent them from doing so in a frameless app window.
1750 | panel.standardWindowButton(NSWindowZoomButton).setEnabled(false)
1751 | }
1752 | }
1753 |
1754 | if (options.vibrancy) {
1755 | browserWindow.setVibrancy(options.vibrancy)
1756 | }
1757 |
1758 | // Set maximizable state last to ensure zoom button does not get reset
1759 | // by calls to other APIs.
1760 | browserWindow.setMaximizable(options.maximizable !== false)
1761 |
1762 | if (options.acceptsFirstMouse) {
1763 | browserWindow.on('focus', function(event) {
1764 | if (event.type() === NSEventTypeLeftMouseDown) {
1765 | browserWindow.webContents
1766 | .executeJavaScript(dispatchFirstClick(webView, event))
1767 | .catch(() => {})
1768 | }
1769 | })
1770 | }
1771 |
1772 | executeJavaScript.injectScript(webView)
1773 | movableArea.injectScript(webView)
1774 | movableArea.setupHandler(browserWindow)
1775 |
1776 | if (options.show !== false) {
1777 | browserWindow.show()
1778 | }
1779 |
1780 | browserWindow.on('closed', function() {
1781 | browserWindow._destroyed = true
1782 | threadDictionary.removeObjectForKey(identifier)
1783 | fiber.cleanup()
1784 | })
1785 |
1786 | threadDictionary[identifier] = panel
1787 |
1788 | fiber.onCleanup(function() {
1789 | if (!browserWindow._destroyed) {
1790 | browserWindow.destroy()
1791 | }
1792 | })
1793 |
1794 | return browserWindow
1795 | }
1796 |
1797 | BrowserWindow.fromId = function(identifier) {
1798 | var threadDictionary = NSThread.mainThread().threadDictionary()
1799 |
1800 | if (threadDictionary[identifier]) {
1801 | return BrowserWindow.fromPanel(threadDictionary[identifier], identifier)
1802 | }
1803 |
1804 | return undefined
1805 | }
1806 |
1807 | BrowserWindow.fromPanel = function(panel, identifier) {
1808 | var browserWindow = new EventEmitter()
1809 | browserWindow.id = identifier
1810 |
1811 | if (!panel || !panel.contentView) {
1812 | throw new Error('needs to pass an NSPanel')
1813 | }
1814 |
1815 | var webView = panel.contentView().subviews()[0]
1816 |
1817 | if (!webView) {
1818 | throw new Error('The NSPanel needs to have a webview')
1819 | }
1820 |
1821 | buildBrowserAPI(browserWindow, panel, webView)
1822 | buildWebAPI(browserWindow, panel, webView)
1823 |
1824 | return browserWindow
1825 | }
1826 |
1827 | module.exports = BrowserWindow
1828 |
1829 |
1830 | /***/ }),
1831 |
1832 | /***/ "./node_modules/sketch-module-web-view/lib/inject-client-messaging.js":
1833 | /*!****************************************************************************!*\
1834 | !*** ./node_modules/sketch-module-web-view/lib/inject-client-messaging.js ***!
1835 | \****************************************************************************/
1836 | /*! no static exports found */
1837 | /***/ (function(module, exports, __webpack_require__) {
1838 |
1839 | var CONSTANTS = __webpack_require__(/*! ./constants */ "./node_modules/sketch-module-web-view/lib/constants.js")
1840 |
1841 | module.exports = function(webView) {
1842 | var source =
1843 | 'window.originalPostMessage = window.postMessage;' +
1844 | 'window.postMessage = function(actionName) {' +
1845 | 'if (!actionName) {' +
1846 | "throw new Error('missing action name')" +
1847 | '}' +
1848 | 'window.webkit.messageHandlers.' +
1849 | CONSTANTS.JS_BRIDGE +
1850 | '.postMessage(' +
1851 | 'JSON.stringify([].slice.call(arguments))' +
1852 | ');' +
1853 | '}'
1854 | var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(
1855 | source,
1856 | 0,
1857 | true
1858 | )
1859 | webView
1860 | .configuration()
1861 | .userContentController()
1862 | .addUserScript(script)
1863 | }
1864 |
1865 |
1866 | /***/ }),
1867 |
1868 | /***/ "./node_modules/sketch-module-web-view/lib/movable-area.js":
1869 | /*!*****************************************************************!*\
1870 | !*** ./node_modules/sketch-module-web-view/lib/movable-area.js ***!
1871 | \*****************************************************************/
1872 | /*! no static exports found */
1873 | /***/ (function(module, exports, __webpack_require__) {
1874 |
1875 | var CONSTANTS = __webpack_require__(/*! ./constants */ "./node_modules/sketch-module-web-view/lib/constants.js")
1876 |
1877 | module.exports.injectScript = function(webView) {
1878 | var source =
1879 | '(function () {' +
1880 | 'var animationId = null;' +
1881 | "document.addEventListener('mousedown', onMouseDown);" +
1882 | '' +
1883 | 'function shouldDrag(target) {' +
1884 | ' if (!target || (target.dataset || {}).appRegion === "no-drag") { return false }' +
1885 | ' if ((target.dataset || {}).appRegion === "drag") { return true }' +
1886 | ' return shouldDrag(target.parentElement)' +
1887 | '};' +
1888 | '' +
1889 | 'function onMouseDown(e) {' +
1890 | ' if (e.button !== 0 || !shouldDrag(e.target)) { return }' +
1891 | ' window.postMessage("' +
1892 | CONSTANTS.START_MOVING_WINDOW +
1893 | '");' +
1894 | " document.addEventListener('mouseup', onMouseUp);" +
1895 | ' animationId = requestAnimationFrame(moveWindow);' +
1896 | '};' +
1897 | '' +
1898 | 'function onMouseUp(e) {' +
1899 | ' window.postMessage("' +
1900 | CONSTANTS.STOP_MOVING_WINDOW +
1901 | '");' +
1902 | " document.removeEventListener('mouseup', onMouseUp);" +
1903 | ' cancelAnimationFrame(animationId);' +
1904 | '};' +
1905 | '' +
1906 | 'function moveWindow(e) {' +
1907 | ' window.postMessage("' +
1908 | CONSTANTS.MOVE_WINDOW +
1909 | '");' +
1910 | ' animationId = requestAnimationFrame(moveWindow);' +
1911 | '}' +
1912 | '})()'
1913 | var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(
1914 | source,
1915 | 0,
1916 | true
1917 | )
1918 | webView
1919 | .configuration()
1920 | .userContentController()
1921 | .addUserScript(script)
1922 | }
1923 |
1924 | module.exports.setupHandler = function(browserWindow) {
1925 | var initialMouseLocation = null
1926 | var initialWindowPosition = null
1927 |
1928 | browserWindow.webContents.on(CONSTANTS.START_MOVING_WINDOW, function() {
1929 | initialMouseLocation = NSEvent.mouseLocation()
1930 | var position = browserWindow.getPosition()
1931 | initialWindowPosition = {
1932 | x: position[0],
1933 | y: position[1],
1934 | }
1935 | })
1936 |
1937 | browserWindow.webContents.on(CONSTANTS.STOP_MOVING_WINDOW, function() {
1938 | initialMouseLocation = null
1939 | initialWindowPosition = null
1940 | })
1941 |
1942 | browserWindow.webContents.on(CONSTANTS.MOVE_WINDOW, function() {
1943 | if (!initialWindowPosition) {
1944 | return
1945 | }
1946 | const mouse = NSEvent.mouseLocation()
1947 | browserWindow.setPosition(
1948 | initialWindowPosition.x + (mouse.x - initialMouseLocation.x),
1949 | initialWindowPosition.y + (initialMouseLocation.y - mouse.y), // y is inverted
1950 | false
1951 | )
1952 | })
1953 | }
1954 |
1955 |
1956 | /***/ }),
1957 |
1958 | /***/ "./node_modules/sketch-module-web-view/lib/parseWebArguments.js":
1959 | /*!**********************************************************************!*\
1960 | !*** ./node_modules/sketch-module-web-view/lib/parseWebArguments.js ***!
1961 | \**********************************************************************/
1962 | /*! no static exports found */
1963 | /***/ (function(module, exports) {
1964 |
1965 | module.exports = function(webArguments) {
1966 | var args = null
1967 | try {
1968 | args = JSON.parse(webArguments)
1969 | } catch (e) {
1970 | // malformed arguments
1971 | }
1972 |
1973 | if (
1974 | !args ||
1975 | !args.constructor ||
1976 | args.constructor !== Array ||
1977 | args.length == 0
1978 | ) {
1979 | return null
1980 | }
1981 |
1982 | return args
1983 | }
1984 |
1985 |
1986 | /***/ }),
1987 |
1988 | /***/ "./node_modules/sketch-module-web-view/lib/set-delegates.js":
1989 | /*!******************************************************************!*\
1990 | !*** ./node_modules/sketch-module-web-view/lib/set-delegates.js ***!
1991 | \******************************************************************/
1992 | /*! no static exports found */
1993 | /***/ (function(module, exports, __webpack_require__) {
1994 |
1995 | var ObjCClass = __webpack_require__(/*! cocoascript-class */ "./node_modules/cocoascript-class/lib/index.js").default
1996 | var parseWebArguments = __webpack_require__(/*! ./parseWebArguments */ "./node_modules/sketch-module-web-view/lib/parseWebArguments.js")
1997 | var CONSTANTS = __webpack_require__(/*! ./constants */ "./node_modules/sketch-module-web-view/lib/constants.js")
1998 |
1999 | // We create one ObjC class for ourselves here
2000 | var WindowDelegateClass
2001 | var NavigationDelegateClass
2002 | var WebScriptHandlerClass
2003 |
2004 | // TODO: events
2005 | // - 'page-favicon-updated'
2006 | // - 'new-window'
2007 | // - 'did-navigate-in-page'
2008 | // - 'will-prevent-unload'
2009 | // - 'crashed'
2010 | // - 'unresponsive'
2011 | // - 'responsive'
2012 | // - 'destroyed'
2013 | // - 'before-input-event'
2014 | // - 'certificate-error'
2015 | // - 'found-in-page'
2016 | // - 'media-started-playing'
2017 | // - 'media-paused'
2018 | // - 'did-change-theme-color'
2019 | // - 'update-target-url'
2020 | // - 'cursor-changed'
2021 | // - 'context-menu'
2022 | // - 'select-bluetooth-device'
2023 | // - 'paint'
2024 | // - 'console-message'
2025 |
2026 | module.exports = function(browserWindow, panel, webview, options) {
2027 | if (!WindowDelegateClass) {
2028 | WindowDelegateClass = ObjCClass({
2029 | classname: 'WindowDelegateClass',
2030 | utils: null,
2031 | panel: null,
2032 |
2033 | 'windowDidResize:': function() {
2034 | this.utils.emit('resize')
2035 | },
2036 |
2037 | 'windowDidMiniaturize:': function() {
2038 | this.utils.emit('minimize')
2039 | },
2040 |
2041 | 'windowDidDeminiaturize:': function() {
2042 | this.utils.emit('restore')
2043 | },
2044 |
2045 | 'windowDidEnterFullScreen:': function() {
2046 | this.utils.emit('enter-full-screen')
2047 | },
2048 |
2049 | 'windowDidExitFullScreen:': function() {
2050 | this.utils.emit('leave-full-screen')
2051 | },
2052 |
2053 | 'windowDidMove:': function() {
2054 | this.utils.emit('move')
2055 | this.utils.emit('moved')
2056 | },
2057 |
2058 | 'windowShouldClose:': function() {
2059 | var shouldClose = true
2060 | this.utils.emit('close', {
2061 | get defaultPrevented() {
2062 | return !shouldClose
2063 | },
2064 | preventDefault: function() {
2065 | shouldClose = false
2066 | },
2067 | })
2068 | return shouldClose
2069 | },
2070 |
2071 | 'windowWillClose:': function() {
2072 | this.utils.emit('closed')
2073 | },
2074 |
2075 | 'windowDidBecomeKey:': function() {
2076 | this.utils.emit('focus', this.panel.currentEvent())
2077 | },
2078 |
2079 | 'windowDidResignKey:': function() {
2080 | this.utils.emit('blur')
2081 | },
2082 | })
2083 | }
2084 |
2085 | if (!NavigationDelegateClass) {
2086 | NavigationDelegateClass = ObjCClass({
2087 | classname: 'NavigationDelegateClass',
2088 | state: NSMutableDictionary.dictionaryWithDictionary({
2089 | wasReady: 0,
2090 | }),
2091 | utils: null,
2092 |
2093 | // // Called when the web view begins to receive web content.
2094 | 'webView:didCommitNavigation:': function(webView) {
2095 | this.utils.emit('will-navigate', {}, String(String(webView.URL())))
2096 | },
2097 |
2098 | // // Called when web content begins to load in a web view.
2099 | 'webView:didStartProvisionalNavigation:': function() {
2100 | this.utils.emit('did-start-navigation')
2101 | this.utils.emit('did-start-loading')
2102 | },
2103 |
2104 | // Called when a web view receives a server redirect.
2105 | 'webView:didReceiveServerRedirectForProvisionalNavigation:': function() {
2106 | this.utils.emit('did-get-redirect-request')
2107 | },
2108 |
2109 | // // Called when the web view needs to respond to an authentication challenge.
2110 | // 'webView:didReceiveAuthenticationChallenge:completionHandler:': function(
2111 | // webView,
2112 | // challenge,
2113 | // completionHandler
2114 | // ) {
2115 | // function callback(username, password) {
2116 | // completionHandler(
2117 | // 0,
2118 | // NSURLCredential.credentialWithUser_password_persistence(
2119 | // username,
2120 | // password,
2121 | // 1
2122 | // )
2123 | // )
2124 | // }
2125 | // var protectionSpace = challenge.protectionSpace()
2126 | // this.utils.emit(
2127 | // 'login',
2128 | // {},
2129 | // {
2130 | // method: String(protectionSpace.authenticationMethod()),
2131 | // url: 'not implemented', // TODO:
2132 | // referrer: 'not implemented', // TODO:
2133 | // },
2134 | // {
2135 | // isProxy: !!protectionSpace.isProxy(),
2136 | // scheme: String(protectionSpace.protocol()),
2137 | // host: String(protectionSpace.host()),
2138 | // port: Number(protectionSpace.port()),
2139 | // realm: String(protectionSpace.realm()),
2140 | // },
2141 | // callback
2142 | // )
2143 | // },
2144 |
2145 | // Called when an error occurs during navigation.
2146 | // 'webView:didFailNavigation:withError:': function(
2147 | // webView,
2148 | // navigation,
2149 | // error
2150 | // ) {},
2151 |
2152 | // Called when an error occurs while the web view is loading content.
2153 | 'webView:didFailProvisionalNavigation:withError:': function(
2154 | webView,
2155 | navigation,
2156 | error
2157 | ) {
2158 | this.utils.emit('did-fail-load', error)
2159 | },
2160 |
2161 | // Called when the navigation is complete.
2162 | 'webView:didFinishNavigation:': function() {
2163 | if (this.state.wasReady == 0) {
2164 | this.state.setObject_forKey(1, 'wasReady')
2165 | this.utils.emitBrowserEvent('ready-to-show')
2166 | }
2167 | this.utils.emit('did-navigate')
2168 | this.utils.emit('did-frame-navigate')
2169 | this.utils.emit('did-stop-loading')
2170 | this.utils.emit('did-finish-load')
2171 | this.utils.emit('did-frame-finish-load')
2172 | },
2173 |
2174 | // Called when the web view’s web content process is terminated.
2175 | 'webViewWebContentProcessDidTerminate:': function() {
2176 | this.utils.emit('dom-ready')
2177 | },
2178 |
2179 | // Decides whether to allow or cancel a navigation.
2180 | // webView:decidePolicyForNavigationAction:decisionHandler:
2181 |
2182 | // Decides whether to allow or cancel a navigation after its response is known.
2183 | // webView:decidePolicyForNavigationResponse:decisionHandler:
2184 | })
2185 | }
2186 |
2187 | if (!WebScriptHandlerClass) {
2188 | WebScriptHandlerClass = ObjCClass({
2189 | classname: 'WebScriptHandlerClass',
2190 | utils: null,
2191 | 'userContentController:didReceiveScriptMessage:': function(_, message) {
2192 | var args = this.utils.parseWebArguments(String(message.body()))
2193 | if (!args) {
2194 | return
2195 | }
2196 | if (!args[0] || typeof args[0] !== 'string') {
2197 | return
2198 | }
2199 | args[0] = String(args[0])
2200 |
2201 | this.utils.emit.apply(this, args)
2202 | },
2203 | })
2204 | }
2205 |
2206 | var navigationDelegate = NavigationDelegateClass.new()
2207 | navigationDelegate.utils = NSDictionary.dictionaryWithDictionary({
2208 | setTitle: browserWindow.setTitle.bind(browserWindow),
2209 | emitBrowserEvent() {
2210 | try {
2211 | browserWindow.emit.apply(browserWindow, arguments)
2212 | } catch (err) {
2213 | console.error(err)
2214 | throw err
2215 | }
2216 | },
2217 | emit() {
2218 | try {
2219 | browserWindow.webContents.emit.apply(
2220 | browserWindow.webContents,
2221 | arguments
2222 | )
2223 | } catch (err) {
2224 | console.error(err)
2225 | throw err
2226 | }
2227 | },
2228 | })
2229 | // reset state as well
2230 | navigationDelegate.state = NSMutableDictionary.dictionaryWithDictionary({
2231 | wasReady: 0,
2232 | })
2233 |
2234 | webview.setNavigationDelegate(navigationDelegate)
2235 |
2236 | var webScriptHandler = WebScriptHandlerClass.new()
2237 | webScriptHandler.utils = NSDictionary.dictionaryWithDictionary({
2238 | emit() {
2239 | try {
2240 | browserWindow.webContents.emit.apply(
2241 | browserWindow.webContents,
2242 | arguments
2243 | )
2244 | } catch (err) {
2245 | console.error(err)
2246 | throw err
2247 | }
2248 | },
2249 | parseWebArguments: parseWebArguments,
2250 | })
2251 |
2252 | webview
2253 | .configuration()
2254 | .userContentController()
2255 | .addScriptMessageHandler_name(webScriptHandler, CONSTANTS.JS_BRIDGE)
2256 |
2257 | var windowDelegate = WindowDelegateClass.new()
2258 | var utils = {
2259 | emit() {
2260 | try {
2261 | browserWindow.emit.apply(browserWindow, arguments)
2262 | } catch (err) {
2263 | console.error(err)
2264 | throw err
2265 | }
2266 | },
2267 | }
2268 | if (options.modal) {
2269 | // find the window of the document
2270 | var msdocument
2271 | if (options.parent.type === 'Document') {
2272 | msdocument = options.parent.sketchObject
2273 | } else {
2274 | msdocument = options.parent
2275 | }
2276 | if (msdocument && String(msdocument.class()) === 'MSDocumentData') {
2277 | // we only have an MSDocumentData instead of a MSDocument
2278 | // let's try to get back to the MSDocument
2279 | msdocument = msdocument.delegate()
2280 | }
2281 | utils.parentWindow = msdocument.windowForSheet()
2282 | }
2283 |
2284 | windowDelegate.utils = NSDictionary.dictionaryWithDictionary(utils)
2285 | windowDelegate.panel = panel
2286 |
2287 | panel.setDelegate(windowDelegate)
2288 | }
2289 |
2290 |
2291 | /***/ }),
2292 |
2293 | /***/ "./node_modules/sketch-module-web-view/lib/webview-api.js":
2294 | /*!****************************************************************!*\
2295 | !*** ./node_modules/sketch-module-web-view/lib/webview-api.js ***!
2296 | \****************************************************************/
2297 | /*! no static exports found */
2298 | /***/ (function(module, exports, __webpack_require__) {
2299 |
2300 | var EventEmitter = __webpack_require__(/*! events */ "events")
2301 | var executeJavaScript = __webpack_require__(/*! ./execute-javascript */ "./node_modules/sketch-module-web-view/lib/execute-javascript.js")
2302 |
2303 | // let's try to match https://github.com/electron/electron/blob/master/docs/api/web-contents.md
2304 | module.exports = function buildAPI(browserWindow, panel, webview) {
2305 | var webContents = new EventEmitter()
2306 |
2307 | webContents.loadURL = browserWindow.loadURL
2308 |
2309 | webContents.loadFile = function(/* filePath */) {
2310 | // TODO:
2311 | console.warn(
2312 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2313 | )
2314 | }
2315 |
2316 | webContents.downloadURL = function(/* filePath */) {
2317 | // TODO:
2318 | console.warn(
2319 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2320 | )
2321 | }
2322 |
2323 | webContents.getURL = function() {
2324 | return String(webview.url())
2325 | }
2326 |
2327 | webContents.getTitle = function() {
2328 | return String(webview.title())
2329 | }
2330 |
2331 | webContents.isDestroyed = function() {
2332 | // TODO:
2333 | console.warn(
2334 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2335 | )
2336 | }
2337 |
2338 | webContents.focus = browserWindow.focus
2339 | webContents.isFocused = browserWindow.isFocused
2340 |
2341 | webContents.isLoading = function() {
2342 | return !!webview.loading()
2343 | }
2344 |
2345 | webContents.isLoadingMainFrame = function() {
2346 | // TODO:
2347 | return !!webview.loading()
2348 | }
2349 |
2350 | webContents.isWaitingForResponse = function() {
2351 | return !webview.loading()
2352 | }
2353 |
2354 | webContents.stop = function() {
2355 | webview.stopLoading()
2356 | }
2357 | webContents.reload = function() {
2358 | webview.reload()
2359 | }
2360 | webContents.reloadIgnoringCache = function() {
2361 | webview.reloadFromOrigin()
2362 | }
2363 | webContents.canGoBack = function() {
2364 | return !!webview.canGoBack()
2365 | }
2366 | webContents.canGoForward = function() {
2367 | return !!webview.canGoForward()
2368 | }
2369 | webContents.canGoToOffset = function(offset) {
2370 | return !!webview.backForwardList().itemAtIndex(offset)
2371 | }
2372 | webContents.clearHistory = function() {
2373 | // TODO:
2374 | console.warn(
2375 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2376 | )
2377 | }
2378 | webContents.goBack = function() {
2379 | webview.goBack()
2380 | }
2381 | webContents.goForward = function() {
2382 | webview.goForward()
2383 | }
2384 | webContents.goToIndex = function(index) {
2385 | var backForwardList = webview.backForwardList()
2386 | var backList = backForwardList.backList()
2387 | var backListLength = backList.count()
2388 | if (backListLength > index) {
2389 | webview.loadRequest(NSURLRequest.requestWithURL(backList[index]))
2390 | return
2391 | }
2392 | var forwardList = backForwardList.forwardList()
2393 | if (forwardList.count() > index - backListLength) {
2394 | webview.loadRequest(
2395 | NSURLRequest.requestWithURL(forwardList[index - backListLength])
2396 | )
2397 | return
2398 | }
2399 | throw new Error('Cannot go to index ' + index)
2400 | }
2401 | webContents.goToOffset = function(offset) {
2402 | if (!webContents.canGoToOffset(offset)) {
2403 | throw new Error('Cannot go to offset ' + offset)
2404 | }
2405 | webview.loadRequest(
2406 | NSURLRequest.requestWithURL(webview.backForwardList().itemAtIndex(offset))
2407 | )
2408 | }
2409 | webContents.isCrashed = function() {
2410 | // TODO:
2411 | console.warn(
2412 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2413 | )
2414 | }
2415 | webContents.setUserAgent = function(/* userAgent */) {
2416 | // TODO:
2417 | console.warn(
2418 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2419 | )
2420 | }
2421 | webContents.getUserAgent = function() {
2422 | const userAgent = webview.customUserAgent()
2423 | return userAgent ? String(userAgent) : undefined
2424 | }
2425 | webContents.insertCSS = function(css) {
2426 | var source =
2427 | "var style = document.createElement('style'); style.innerHTML = " +
2428 | css.replace(/"/, '\\"') +
2429 | '; document.head.appendChild(style);'
2430 | var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(
2431 | source,
2432 | 0,
2433 | true
2434 | )
2435 | webview
2436 | .configuration()
2437 | .userContentController()
2438 | .addUserScript(script)
2439 | }
2440 | webContents.insertJS = function(source) {
2441 | var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(
2442 | source,
2443 | 0,
2444 | true
2445 | )
2446 | webview
2447 | .configuration()
2448 | .userContentController()
2449 | .addUserScript(script)
2450 | }
2451 | webContents.executeJavaScript = executeJavaScript(webview, browserWindow)
2452 | webContents.setIgnoreMenuShortcuts = function() {
2453 | // TODO:??
2454 | console.warn(
2455 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2456 | )
2457 | }
2458 | webContents.setAudioMuted = function(/* muted */) {
2459 | // TODO:??
2460 | console.warn(
2461 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2462 | )
2463 | }
2464 | webContents.isAudioMuted = function() {
2465 | // TODO:??
2466 | console.warn(
2467 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2468 | )
2469 | }
2470 | webContents.setZoomFactor = function(factor) {
2471 | webview.setMagnification_centeredAtPoint(factor, CGPointMake(0, 0))
2472 | }
2473 | webContents.getZoomFactor = function(callback) {
2474 | callback(Number(webview.magnification()))
2475 | }
2476 | webContents.setZoomLevel = function(level) {
2477 | // eslint-disable-next-line no-restricted-properties
2478 | webContents.setZoomFactor(Math.pow(1.2, level))
2479 | }
2480 | webContents.getZoomLevel = function(callback) {
2481 | // eslint-disable-next-line no-restricted-properties
2482 | callback(Math.log(Number(webview.magnification())) / Math.log(1.2))
2483 | }
2484 | webContents.setVisualZoomLevelLimits = function(/* minimumLevel, maximumLevel */) {
2485 | // TODO:??
2486 | console.warn(
2487 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2488 | )
2489 | }
2490 | webContents.setLayoutZoomLevelLimits = function(/* minimumLevel, maximumLevel */) {
2491 | // TODO:??
2492 | console.warn(
2493 | 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'
2494 | )
2495 | }
2496 |
2497 | // TODO:
2498 | // webContents.undo = function() {
2499 | // webview.undoManager().undo()
2500 | // }
2501 | // webContents.redo = function() {
2502 | // webview.undoManager().redo()
2503 | // }
2504 | // webContents.cut = webview.cut
2505 | // webContents.copy = webview.copy
2506 | // webContents.paste = webview.paste
2507 | // webContents.pasteAndMatchStyle = webview.pasteAsRichText
2508 | // webContents.delete = webview.delete
2509 | // webContents.replace = webview.replaceSelectionWithText
2510 |
2511 | webContents.send = function() {
2512 | const script =
2513 | 'window.postMessage({' +
2514 | 'isSketchMessage: true,' +
2515 | "origin: '" +
2516 | String(__command.identifier()) +
2517 | "'," +
2518 | 'args: ' +
2519 | JSON.stringify([].slice.call(arguments)) +
2520 | '}, "*")'
2521 | webview.evaluateJavaScript_completionHandler(script, null)
2522 | }
2523 |
2524 | webContents.getNativeWebview = function() {
2525 | return webview
2526 | }
2527 |
2528 | browserWindow.webContents = webContents
2529 | }
2530 |
2531 |
2532 | /***/ }),
2533 |
2534 | /***/ "./resources/webview/webview.html":
2535 | /*!****************************************!*\
2536 | !*** ./resources/webview/webview.html ***!
2537 | \****************************************/
2538 | /*! no static exports found */
2539 | /***/ (function(module, exports) {
2540 |
2541 | module.exports = "file://" + context.plugin.urlForResourceNamed("_webpack_resources/43aa738f582ce37c61cb81dcdf421b63.html").path();
2542 |
2543 | /***/ }),
2544 |
2545 | /***/ "./src/actions/resize.js":
2546 | /*!*******************************!*\
2547 | !*** ./src/actions/resize.js ***!
2548 | \*******************************/
2549 | /*! exports provided: default */
2550 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
2551 |
2552 | "use strict";
2553 | __webpack_require__.r(__webpack_exports__);
2554 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sketch */ "sketch");
2555 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sketch__WEBPACK_IMPORTED_MODULE_0__);
2556 | // resize logic
2557 |
2558 | var resize = function resize(selection, dimensions) {
2559 | var _iteratorNormalCompletion = true;
2560 | var _didIteratorError = false;
2561 | var _iteratorError = undefined;
2562 |
2563 | try {
2564 | for (var _iterator = selection.layers[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
2565 | var layer = _step.value;
2566 | var frame = layer.frame;
2567 | var finalDimensions = process(dimensions, frame.width, frame.height);
2568 | frame.width = finalDimensions.width;
2569 | frame.height = finalDimensions.height;
2570 | }
2571 | } catch (err) {
2572 | _didIteratorError = true;
2573 | _iteratorError = err;
2574 | } finally {
2575 | try {
2576 | if (!_iteratorNormalCompletion && _iterator.return != null) {
2577 | _iterator.return();
2578 | }
2579 | } finally {
2580 | if (_didIteratorError) {
2581 | throw _iteratorError;
2582 | }
2583 | }
2584 | }
2585 |
2586 | sketch__WEBPACK_IMPORTED_MODULE_0___default.a.UI.message("Resized ".concat(selection.length, " layer(s)"));
2587 | }; // process dimensions, and replace %w, and %h
2588 |
2589 |
2590 | var process = function process(dimensions, originalWidth, originalHeight) {
2591 | return {
2592 | width: eval(sanitize(dimensions.width, originalWidth, originalHeight)),
2593 | height: eval(sanitize(dimensions.height, originalWidth, originalHeight))
2594 | };
2595 | };
2596 |
2597 | var sanitize = function sanitize(string, w, h) {
2598 | return string.replace(/%w/gi, w).replace(/%h/gi, h);
2599 | };
2600 |
2601 | /* harmony default export */ __webpack_exports__["default"] = (resize);
2602 |
2603 | /***/ }),
2604 |
2605 | /***/ "./src/main.js":
2606 | /*!*********************!*\
2607 | !*** ./src/main.js ***!
2608 | \*********************/
2609 | /*! exports provided: default */
2610 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
2611 |
2612 | "use strict";
2613 | __webpack_require__.r(__webpack_exports__);
2614 | /* harmony import */ var sketch_module_web_view__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! sketch-module-web-view */ "./node_modules/sketch-module-web-view/lib/index.js");
2615 | /* harmony import */ var sketch_module_web_view__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(sketch_module_web_view__WEBPACK_IMPORTED_MODULE_0__);
2616 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! sketch */ "sketch");
2617 | /* harmony import */ var sketch__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(sketch__WEBPACK_IMPORTED_MODULE_1__);
2618 | /* harmony import */ var _actions_resize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./actions/resize */ "./src/actions/resize.js");
2619 |
2620 |
2621 | // main function
2622 |
2623 | var main = function main() {
2624 | var document = sketch__WEBPACK_IMPORTED_MODULE_1___default.a.getSelectedDocument();
2625 | var selection = document.selectedLayers; // return error message if selection is empty
2626 |
2627 | if (selection.isEmpty) {
2628 | sketch__WEBPACK_IMPORTED_MODULE_1___default.a.UI.message('No layer(s) selected!');
2629 | return;
2630 | } // define the webview, its options, and its content
2631 |
2632 |
2633 | var options = {
2634 | identifier: 'sketch.resize',
2635 | width: 480,
2636 | height: 316,
2637 | center: true,
2638 | show: false,
2639 | backgroundColor: '#181818',
2640 | titleBarStyle: 'hiddenInset',
2641 | alwaysOnTop: true,
2642 | resizable: false,
2643 | fullscreenable: false,
2644 | maximizable: false,
2645 | minimizable: false
2646 | };
2647 | var webview = new sketch_module_web_view__WEBPACK_IMPORTED_MODULE_0___default.a(options);
2648 | var webcontent = webview.webContents; // when loaded, show the webview
2649 |
2650 | webview.once('ready-to-show', function () {
2651 | return webview.show();
2652 | }); // cancel the overall process
2653 |
2654 | webcontent.on('cancel', function () {
2655 | return close(webview);
2656 | }); // process input, and trigger resize
2657 |
2658 | webcontent.on('submit', function (dimensions) {
2659 | Object(_actions_resize__WEBPACK_IMPORTED_MODULE_2__["default"])(selection, dimensions);
2660 | close(webview);
2661 | }); // show the webview
2662 |
2663 | webview.loadURL(__webpack_require__(/*! ../resources/webview/webview.html */ "./resources/webview/webview.html"));
2664 | }; // close the window
2665 |
2666 |
2667 | var close = function close(webview) {
2668 | webview.close();
2669 | webview = null;
2670 | };
2671 |
2672 | /* harmony default export */ __webpack_exports__["default"] = (main);
2673 |
2674 | /***/ }),
2675 |
2676 | /***/ "events":
2677 | /*!*************************!*\
2678 | !*** external "events" ***!
2679 | \*************************/
2680 | /*! no static exports found */
2681 | /***/ (function(module, exports) {
2682 |
2683 | module.exports = require("events");
2684 |
2685 | /***/ }),
2686 |
2687 | /***/ "sketch":
2688 | /*!*************************!*\
2689 | !*** external "sketch" ***!
2690 | \*************************/
2691 | /*! no static exports found */
2692 | /***/ (function(module, exports) {
2693 |
2694 | module.exports = require("sketch");
2695 |
2696 | /***/ })
2697 |
2698 | /******/ });
2699 | if (key === 'default' && typeof exports === 'function') {
2700 | exports(context);
2701 | } else {
2702 | exports[key](context);
2703 | }
2704 | }
2705 | that['onRun'] = __skpm_run.bind(this, 'default')
2706 |
2707 | //# sourceMappingURL=main.js.map
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Sketch/main.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack://exports/webpack/bootstrap","webpack://exports/./node_modules/@skpm/timers/immediate.js","webpack://exports/./node_modules/@skpm/timers/test-if-fiber.js","webpack://exports/./node_modules/@skpm/timers/timeout.js","webpack://exports/./node_modules/cocoascript-class/lib/index.js","webpack://exports/./node_modules/cocoascript-class/lib/runtime.js","webpack://exports/./node_modules/promise-polyfill/lib/index.js","webpack://exports/./node_modules/sketch-module-web-view/lib/browser-api.js","webpack://exports/./node_modules/sketch-module-web-view/lib/constants.js","webpack://exports/./node_modules/sketch-module-web-view/lib/dispatch-first-click.js","webpack://exports/./node_modules/sketch-module-web-view/lib/execute-javascript.js","webpack://exports/./node_modules/sketch-module-web-view/lib/fitSubview.js","webpack://exports/./node_modules/sketch-module-web-view/lib/index.js","webpack://exports/./node_modules/sketch-module-web-view/lib/inject-client-messaging.js","webpack://exports/./node_modules/sketch-module-web-view/lib/movable-area.js","webpack://exports/./node_modules/sketch-module-web-view/lib/parseWebArguments.js","webpack://exports/./node_modules/sketch-module-web-view/lib/set-delegates.js","webpack://exports/./node_modules/sketch-module-web-view/lib/webview-api.js","webpack://exports/./resources/webview/webview.html","webpack://exports/./src/actions/resize.js","webpack://exports/./src/main.js","webpack://exports/external \"events\"","webpack://exports/external \"sketch\""],"names":["resize","selection","dimensions","layers","layer","frame","finalDimensions","process","width","height","sketch","UI","message","length","originalWidth","originalHeight","eval","sanitize","string","w","h","replace","main","document","getSelectedDocument","selectedLayers","isEmpty","options","identifier","center","show","backgroundColor","titleBarStyle","alwaysOnTop","resizable","fullscreenable","maximizable","minimizable","webview","BrowserWindow","webcontent","webContents","once","on","close","loadURL","require"],"mappings":";;;;;;AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,kDAA0C,gCAAgC;AAC1E;AACA;;AAEA;AACA;AACA;AACA,gEAAwD,kBAAkB;AAC1E;AACA,yDAAiD,cAAc;AAC/D;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,iDAAyC,iCAAiC;AAC1E,wHAAgH,mBAAmB,EAAE;AACrI;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;;AAGA;AACA;;;;;;;;;;;;AClFA;AACA,cAAc,mBAAO,CAAC,yDAAW;;AAEjC;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;;;;;;ACdA;AACA;AACA;;;;;;;;;;;;ACFA;AACA,qBAAqB,mBAAO,CAAC,qEAAiB;;AAE9C;AACA;;AAEA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AACD;AACA;AACA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA;AACA;AACA,yCAAyC,cAAc,IAAI;AAC3D;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;;;;;;;;AC1Da;;AAEb;AACA;AACA,CAAC;AACD;AACA;;AAEA,eAAe,mBAAO,CAAC,qEAAc;;AAErC;;AAEA;AACA;;AAEA,6EAA6E,YAAY;;AAEzF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA,OAAO;AACP;AACA,KAAK;AACL;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA,C;;;;;;;;;;;;AC7Da;;AAEb;AACA;AACA,CAAC;AACD;AACA;AACA,kCAAkC,qCAAqC;;AAEvE;AACA;AACA,4CAA4C,sCAAsC,GAAG,YAAY;AACjG;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;;AAEA;AACA,iEAAiE;AACjE;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,oBAAoB,QAAQ,YAAY,WAAW;AACnD;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA,8GAA8G,YAAY,GAAG,YAAY,GAAG,aAAa,IAAI,UAAU,WAAW,GAAG;AACrL;AACA,8GAA8G,YAAY,GAAG,YAAY,GAAG,YAAY,IAAI,UAAU,WAAW,GAAG;;AAEpL;AACA,wCAAwC,gCAAgC,E;;;;;;;;;;;;ACvGxE,gEAAa;;AAEb;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;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,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;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,wCAAwC,SAAS;AACjD;AACA;AACA,GAAG;AACH;;AAEA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA,+DAA+D;AAC/D;AACA;;AAEA;;;;;;;;;;;;;AClQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA,mBAAmB,OAAO;AAC1B;AACA;AACA;AACA,GAAG;AACH;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA,SAAS;AACT,OAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA,oCAAoC,+BAA+B;AACnE;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO,+BAA+B;AACtC;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;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA,OAAO;AACP;AACA;AACA,OAAO;AACP;AACA;AACA;;AAEA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA,oCAAoC,aAAa;AACjD;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA;AACA;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA,KAAK;AACL;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;;;;;;AC5lBA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACRA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA,QAAQ;AACR,gBAAgB;AAChB,MAAM,eAAe;AACrB,0CAA0C,cAAc;AACxD,MAAM;AACN;AACA;;;;;;;;;;;;ACvBA,+DAAgB,mBAAO,CAAC,2EAAa;;AAErC;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS;AACT,OAAO;AACP;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA,8BAA8B;AAC9B,YAAY;AACZ,gCAAgC;AAChC,wFAAwF;AACxF,qCAAqC;AACrC;AACA;AACA,mBAAmB;AACnB,YAAY;AACZ,kCAAkC;AAClC;AACA;AACA,kBAAkB;AAClB,YAAY;AACZ,UAAU,OAAO;AACjB;AACA;AACA,kBAAkB;AAClB,UAAU;AACV,QAAQ,cAAc;AACtB;AACA;AACA,kBAAkB;AAClB,QAAQ;AACR,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;AC9GA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACrBA;AACA;AACA,mBAAmB,mBAAO,CAAC,sBAAQ;AACnC,sBAAsB,mBAAO,CAAC,+EAAe;AAC7C,kBAAkB,mBAAO,CAAC,+EAAe;AACzC,uBAAuB,mBAAO,CAAC,6EAAc;AAC7C,yBAAyB,mBAAO,CAAC,iGAAwB;AACzD,4BAA4B,mBAAO,CAAC,uGAA2B;AAC/D,kBAAkB,mBAAO,CAAC,iFAAgB;AAC1C,wBAAwB,mBAAO,CAAC,6FAAsB;AACtD,mBAAmB,mBAAO,CAAC,mFAAiB;;AAE5C;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;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;;AAEA;;AAEA;AACA;AACA;AACA,GAAG;AACH;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,yBAAyB;AACzB;AACA,KAAK;AACL;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,GAAG;;AAEH;;AAEA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;;;;;;;;;;;;ACzUA,gBAAgB,mBAAO,CAAC,2EAAa;;AAErC;AACA;AACA,qDAAqD;AACrD,gDAAgD;AAChD,uBAAuB;AACvB;AACA,MAAM;AACN;AACA;AACA;AACA;AACA,OAAO;AACP,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;ACxBA,gBAAgB,mBAAO,CAAC,2EAAa;;AAErC;AACA;AACA,mBAAmB;AACnB,4BAA4B;AAC5B,yDAAyD;AACzD;AACA,kCAAkC;AAClC,2CAA2C,4BAA4B,eAAe;AACtF,gCAAgC,yBAAyB,cAAc;AACvE;AACA,OAAO;AACP;AACA,8BAA8B;AAC9B,qDAAqD,SAAS;AAC9D;AACA;AACA,QAAQ;AACR,uDAAuD;AACvD,uDAAuD;AACvD,OAAO;AACP;AACA,4BAA4B;AAC5B;AACA;AACA,QAAQ;AACR,0DAA0D;AAC1D,yCAAyC;AACzC,OAAO;AACP;AACA,6BAA6B;AAC7B;AACA;AACA,QAAQ;AACR,uDAAuD;AACvD,MAAM;AACN,MAAM;AACN;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA,GAAG;;AAEH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,GAAG;AACH;;;;;;;;;;;;AC9EA;AACA;AACA;AACA;AACA,GAAG;AACH;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;;;;;;;;;;;AClBA,gBAAgB,mBAAO,CAAC,wEAAmB;AAC3C,wBAAwB,mBAAO,CAAC,2FAAqB;AACrD,gBAAgB,mBAAO,CAAC,2EAAa;;AAErC;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,OAAO;;AAEP;AACA;AACA,OAAO;;AAEP;AACA;AACA,OAAO;;AAEP;AACA;AACA,OAAO;;AAEP;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA,WAAW;AACX;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA,OAAO;;AAEP;AACA;AACA,OAAO;;AAEP;AACA;AACA,OAAO;;AAEP;AACA;AACA,OAAO;AACP,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;;AAEA;AACA;AACA,2CAA2C;AAC3C,OAAO;;AAEP;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA;AACA,cAAc;AACd;AACA;AACA,UAAU;;AAEV;AACA;AACA;AACA;AACA;AACA,aAAa;;AAEb;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;;AAEP;AACA;AACA;AACA,OAAO;;AAEP;AACA;;AAEA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,OAAO;AACP,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;AACL,GAAG;AACH;AACA;AACA;AACA,GAAG;;AAEH;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;AACL;AACA,GAAG;;AAEH;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;;;;;;ACrSA,mBAAmB,mBAAO,CAAC,sBAAQ;AACnC,wBAAwB,mBAAO,CAAC,6FAAsB;;AAEtD;AACA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;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;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;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;AACA;AACA;AACA;AACA,mDAAmD;AACnD;AACA,QAAQ,kCAAkC;AAC1C;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;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;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,2BAA2B;AAC3B;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;;;;;;;;;;;ACrOA,mI;;;;;;;;;;;;ACAA;AAAA;AAAA;CAEA;;AACA,IAAMA,MAAM,GAAG,SAATA,MAAS,CAACC,SAAD,EAAYC,UAAZ,EAA2B;AAAA;AAAA;AAAA;;AAAA;AACxC,yBAAkBD,SAAS,CAACE,MAA5B,8HAAoC;AAAA,UAA3BC,KAA2B;AAClC,UAAMC,KAAK,GAAGD,KAAK,CAACC,KAApB;AACA,UAAMC,eAAe,GAAGC,OAAO,CAACL,UAAD,EAAaG,KAAK,CAACG,KAAnB,EAA0BH,KAAK,CAACI,MAAhC,CAA/B;AACAJ,WAAK,CAACG,KAAN,GAAcF,eAAe,CAACE,KAA9B;AACAH,WAAK,CAACI,MAAN,GAAeH,eAAe,CAACG,MAA/B;AACD;AANuC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAQxCC,+CAAM,CAACC,EAAP,CAAUC,OAAV,mBAA6BX,SAAS,CAACY,MAAvC;AACD,CATD,C,CAWA;;;AACA,IAAMN,OAAO,GAAG,SAAVA,OAAU,CAACL,UAAD,EAAaY,aAAb,EAA4BC,cAA5B;AAAA,SAAgD;AAC9DP,SAAK,EAAEQ,IAAI,CAACC,QAAQ,CAACf,UAAU,CAACM,KAAZ,EAAmBM,aAAnB,EAAkCC,cAAlC,CAAT,CADmD;AAE9DN,UAAM,EAAEO,IAAI,CAACC,QAAQ,CAACf,UAAU,CAACO,MAAZ,EAAoBK,aAApB,EAAmCC,cAAnC,CAAT;AAFkD,GAAhD;AAAA,CAAhB;;AAKA,IAAME,QAAQ,GAAG,SAAXA,QAAW,CAACC,MAAD,EAASC,CAAT,EAAYC,CAAZ;AAAA,SAAkBF,MAAM,CAACG,OAAP,CAAe,MAAf,EAAuBF,CAAvB,EAA0BE,OAA1B,CAAkC,MAAlC,EAA0CD,CAA1C,CAAlB;AAAA,CAAjB;;AAEepB,qEAAf,E;;;;;;;;;;;;ACtBA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA;CAGA;;AACA,IAAMsB,IAAI,GAAG,SAAPA,IAAO,GAAM;AACjB,MAAMC,QAAQ,GAAGb,6CAAM,CAACc,mBAAP,EAAjB;AACA,MAAMvB,SAAS,GAAGsB,QAAQ,CAACE,cAA3B,CAFiB,CAIjB;;AACA,MAAIxB,SAAS,CAACyB,OAAd,EAAuB;AACrBhB,iDAAM,CAACC,EAAP,CAAUC,OAAV,CAAkB,uBAAlB;AACA;AACD,GARgB,CAUjB;;;AACA,MAAMe,OAAO,GAAG;AACdC,cAAU,EAAE,eADE;AAEdpB,SAAK,EAAE,GAFO;AAGdC,UAAM,EAAE,GAHM;AAIdoB,UAAM,EAAE,IAJM;AAKdC,QAAI,EAAE,KALQ;AAMdC,mBAAe,EAAE,SANH;AAOdC,iBAAa,EAAE,aAPD;AAQdC,eAAW,EAAE,IARC;AASdC,aAAS,EAAE,KATG;AAUdC,kBAAc,EAAE,KAVF;AAWdC,eAAW,EAAE,KAXC;AAYdC,eAAW,EAAE;AAZC,GAAhB;AAeA,MAAIC,OAAO,GAAG,IAAIC,6DAAJ,CAAkBZ,OAAlB,CAAd;AACA,MAAMa,UAAU,GAAGF,OAAO,CAACG,WAA3B,CA3BiB,CA6BjB;;AACAH,SAAO,CAACI,IAAR,CAAa,eAAb,EAA8B;AAAA,WAAMJ,OAAO,CAACR,IAAR,EAAN;AAAA,GAA9B,EA9BiB,CAgCjB;;AACAU,YAAU,CAACG,EAAX,CAAc,QAAd,EAAwB;AAAA,WAAMC,KAAK,CAACN,OAAD,CAAX;AAAA,GAAxB,EAjCiB,CAmCjB;;AACAE,YAAU,CAACG,EAAX,CAAc,QAAd,EAAwB,UAAAzC,UAAU,EAAI;AACpCF,mEAAM,CAACC,SAAD,EAAYC,UAAZ,CAAN;AACA0C,SAAK,CAACN,OAAD,CAAL;AACD,GAHD,EApCiB,CAyCjB;;AACAA,SAAO,CAACO,OAAR,CAAgBC,mBAAO,CAAC,2EAAD,CAAvB;AACD,CA3CD,C,CA6CA;;;AACA,IAAMF,KAAK,GAAG,SAARA,KAAQ,CAAAN,OAAO,EAAI;AACvBA,SAAO,CAACM,KAAR;AACAN,SAAO,GAAG,IAAV;AACD,CAHD;;AAKehB,mEAAf,E;;;;;;;;;;;ACxDA,mC;;;;;;;;;;;ACAA,mC","file":"main.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/main.js\");\n","/* globals coscript, sketch */\nvar timeout = require('./timeout')\n\nfunction setImmediate(func, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) {\n return timeout.setTimeout(func, 0, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)\n}\n\nfunction clearImmediate(id) {\n return timeout.clearTimeout(id)\n}\n\nmodule.exports = {\n setImmediate: setImmediate,\n clearImmediate: clearImmediate\n}\n","module.exports = function () {\n return typeof coscript !== 'undefined' && coscript.createFiber\n}\n","/* globals coscript, sketch */\nvar fiberAvailable = require('./test-if-fiber')\n\nvar setTimeout\nvar clearTimeout\n\nvar fibers = []\n\nif (fiberAvailable()) {\n var fibers = []\n\n setTimeout = function (func, delay, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) {\n // fibers takes care of keeping coscript around\n var id = fibers.length\n fibers.push(coscript.scheduleWithInterval_jsFunction(\n (delay || 0) / 1000,\n function () {\n func(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)\n }\n ))\n return id\n }\n\n clearTimeout = function (id) {\n var timeout = fibers[id]\n if (timeout) {\n timeout.cancel() // fibers takes care of keeping coscript around\n fibers[id] = undefined // garbage collect the fiber\n }\n }\n} else {\n setTimeout = function (func, delay, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10) {\n coscript.shouldKeepAround = true\n var id = fibers.length\n fibers.push(true)\n coscript.scheduleWithInterval_jsFunction(\n (delay || 0) / 1000,\n function () {\n if (fibers[id]) { // if not cleared\n func(param1, param2, param3, param4, param5, param6, param7, param8, param9, param10)\n }\n clearTimeout(id)\n if (fibers.every(function (_id) { return !_id })) { // if everything is cleared\n coscript.shouldKeepAround = false\n }\n }\n )\n return id\n }\n\n clearTimeout = function (id) {\n fibers[id] = false\n }\n}\n\nmodule.exports = {\n setTimeout: setTimeout,\n clearTimeout: clearTimeout\n}\n","\"use strict\";\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.SuperCall = undefined;\nexports.default = ObjCClass;\n\nvar _runtime = require(\"./runtime.js\");\n\nexports.SuperCall = _runtime.SuperCall;\n\n// super when returnType is id and args are void\n// id objc_msgSendSuper(struct objc_super *super, SEL op, void)\n\nconst SuperInit = (0, _runtime.SuperCall)(NSStringFromSelector(\"init\"), [], { type: \"@\" });\n\n// Returns a real ObjC class. No need to use new.\nfunction ObjCClass(defn) {\n const superclass = defn.superclass || NSObject;\n const className = (defn.className || defn.classname || \"ObjCClass\") + NSUUID.UUID().UUIDString();\n const reserved = new Set(['className', 'classname', 'superclass']);\n var cls = MOClassDescription.allocateDescriptionForClassWithName_superclass_(className, superclass);\n // Add each handler to the class description\n const ivars = [];\n for (var key in defn) {\n const v = defn[key];\n if (typeof v == 'function' && key !== 'init') {\n var selector = NSSelectorFromString(key);\n cls.addInstanceMethodWithSelector_function_(selector, v);\n } else if (!reserved.has(key)) {\n ivars.push(key);\n cls.addInstanceVariableWithName_typeEncoding(key, \"@\");\n }\n }\n\n cls.addInstanceMethodWithSelector_function_(NSSelectorFromString('init'), function () {\n const self = SuperInit.call(this);\n ivars.map(name => {\n Object.defineProperty(self, name, {\n get() {\n return getIvar(self, name);\n },\n set(v) {\n (0, _runtime.object_setInstanceVariable)(self, name, v);\n }\n });\n self[name] = defn[name];\n });\n // If there is a passsed-in init funciton, call it now.\n if (typeof defn.init == 'function') defn.init.call(this);\n return self;\n });\n\n return cls.registerClass();\n};\n\nfunction getIvar(obj, name) {\n const retPtr = MOPointer.new();\n (0, _runtime.object_getInstanceVariable)(obj, name, retPtr);\n return retPtr.value().retain().autorelease();\n}","'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.SuperCall = SuperCall;\nexports.CFunc = CFunc;\nconst objc_super_typeEncoding = '{objc_super=\"receiver\"@\"super_class\"#}';\n\n// You can store this to call your function. this must be bound to the current instance.\nfunction SuperCall(selector, argTypes, returnType) {\n const func = CFunc(\"objc_msgSendSuper\", [{ type: '^' + objc_super_typeEncoding }, { type: \":\" }, ...argTypes], returnType);\n return function (...args) {\n const struct = make_objc_super(this, this.superclass());\n const structPtr = MOPointer.alloc().initWithValue_(struct);\n return func(structPtr, selector, ...args);\n };\n}\n\n// Recursively create a MOStruct\nfunction makeStruct(def) {\n if (typeof def !== 'object' || Object.keys(def).length == 0) {\n return def;\n }\n const name = Object.keys(def)[0];\n const values = def[name];\n\n const structure = MOStruct.structureWithName_memberNames_runtime(name, Object.keys(values), Mocha.sharedRuntime());\n\n Object.keys(values).map(member => {\n structure[member] = makeStruct(values[member]);\n });\n\n return structure;\n}\n\nfunction make_objc_super(self, cls) {\n return makeStruct({\n objc_super: {\n receiver: self,\n super_class: cls\n }\n });\n}\n\n// Due to particularities of the JS bridge, we can't call into MOBridgeSupport objects directly\n// But, we can ask key value coding to do the dirty work for us ;)\nfunction setKeys(o, d) {\n const funcDict = NSMutableDictionary.dictionary();\n funcDict.o = o;\n Object.keys(d).map(k => funcDict.setValue_forKeyPath(d[k], \"o.\" + k));\n}\n\n// Use any C function, not just ones with BridgeSupport\nfunction CFunc(name, args, retVal) {\n function makeArgument(a) {\n if (!a) return null;\n const arg = MOBridgeSupportArgument.alloc().init();\n setKeys(arg, {\n type64: a.type\n });\n return arg;\n }\n const func = MOBridgeSupportFunction.alloc().init();\n setKeys(func, {\n name: name,\n arguments: args.map(makeArgument),\n returnValue: makeArgument(retVal)\n });\n return func;\n}\n\n/*\n@encode(char*) = \"*\"\n@encode(id) = \"@\"\n@encode(Class) = \"#\"\n@encode(void*) = \"^v\"\n@encode(CGRect) = \"{CGRect={CGPoint=dd}{CGSize=dd}}\"\n@encode(SEL) = \":\"\n*/\n\nfunction addStructToBridgeSupport(key, structDef) {\n // OK, so this is probably the nastiest hack in this file.\n // We go modify MOBridgeSupportController behind its back and use kvc to add our own definition\n // There isn't another API for this though. So the only other way would be to make a real bridgesupport file.\n const symbols = MOBridgeSupportController.sharedController().valueForKey('symbols');\n if (!symbols) throw Error(\"Something has changed within bridge support so we can't add our definitions\");\n // If someone already added this definition, don't re-register it.\n if (symbols[key] !== null) return;\n const def = MOBridgeSupportStruct.alloc().init();\n setKeys(def, {\n name: key,\n type: structDef.type\n });\n symbols[key] = def;\n};\n\n// This assumes the ivar is an object type. Return value is pretty useless.\nconst object_getInstanceVariable = exports.object_getInstanceVariable = CFunc(\"object_getInstanceVariable\", [{ type: \"@\" }, { type: '*' }, { type: \"^@\" }], { type: \"^{objc_ivar=}\" });\n// Again, ivar is of object type\nconst object_setInstanceVariable = exports.object_setInstanceVariable = CFunc(\"object_setInstanceVariable\", [{ type: \"@\" }, { type: '*' }, { type: \"@\" }], { type: \"^{objc_ivar=}\" });\n\n// We need Mocha to understand what an objc_super is so we can use it as a function argument\naddStructToBridgeSupport('objc_super', { type: objc_super_typeEncoding });","'use strict';\n\n/**\n * @this {Promise}\n */\nfunction finallyConstructor(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\n// Store setTimeout reference so promise-polyfill will be unaffected by\n// other code modifying setTimeout (like sinon.useFakeTimers())\nvar setTimeoutFunc = setTimeout;\n\nfunction noop() {}\n\n// Polyfill for Function.prototype.bind\nfunction bind(fn, thisArg) {\n return function() {\n fn.apply(thisArg, arguments);\n };\n}\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(bind(then, 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);\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) return;\n done = true;\n resolve(self, value);\n },\n function(reason) {\n if (done) return;\n done = true;\n reject(self, reason);\n }\n );\n } catch (ex) {\n if (done) return;\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'] = finallyConstructor;\n\nPromise.all = function(arr) {\n return new Promise(function(resolve, reject) {\n if (!arr || typeof arr.length === 'undefined')\n throw new TypeError('Promise.all accepts an array');\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(values) {\n return new Promise(function(resolve, reject) {\n for (var i = 0, len = values.length; i < len; i++) {\n values[i].then(resolve, reject);\n }\n });\n};\n\n// Use polyfill for setImmediate for performance gains\nPromise._immediateFn =\n (typeof setImmediate === 'function' &&\n function(fn) {\n setImmediate(fn);\n }) ||\n function(fn) {\n setTimeoutFunc(fn, 0);\n };\n\nPromise._unhandledRejectionFn = function _unhandledRejectionFn(err) {\n if (typeof console !== 'undefined' && console) {\n console.warn('Possible Unhandled Promise Rejection:', err); // eslint-disable-line no-console\n }\n};\n\nmodule.exports = Promise;\n","function parseHexColor(color) {\n // Check the string for incorrect formatting.\n if (!color || color[0] !== '#') {\n if (\n color &&\n typeof color.isKindOfClass === 'function' &&\n color.isKindOfClass(NSColor)\n ) {\n return color\n }\n throw new Error(\n 'Incorrect color formating. It should be an hex color: #RRGGBBAA'\n )\n }\n\n // append FF if alpha channel is not specified.\n var source = color.substr(1)\n if (source.length === 3) {\n source += 'F'\n } else if (source.length === 6) {\n source += 'FF'\n }\n // Convert the string from #FFF format to #FFFFFF format.\n var hex\n if (source.length === 4) {\n for (var i = 0; i < 4; i += 1) {\n hex += source[i]\n hex += source[i]\n }\n } else if (source.length === 8) {\n hex = source\n } else {\n return NSColor.whiteColor()\n }\n\n var r = parseInt(hex.slice(0, 2), 16)\n var g = parseInt(hex.slice(2, 4), 16)\n var b = parseInt(hex.slice(4, 6), 16)\n var a = parseInt(hex.slice(6, 8), 16)\n\n return NSColor.colorWithSRGBRed_green_blue_alpha(r, g, b, a)\n}\n\nmodule.exports = function(browserWindow, panel, webview) {\n // keep reference to the subviews\n browserWindow._panel = panel\n browserWindow._webview = webview\n browserWindow._destroyed = false\n\n browserWindow.destroy = function() {\n return panel.close()\n }\n\n browserWindow.close = function() {\n if (panel.delegate().utils.parentWindow) {\n var shouldClose = true\n browserWindow.emit('close', {\n get defaultPrevented() {\n return !shouldClose\n },\n preventDefault: function() {\n shouldClose = false\n },\n })\n if (shouldClose) {\n panel.delegate().utils.parentWindow.endSheet(panel)\n }\n return\n }\n\n if (!browserWindow.isClosable()) {\n return\n }\n\n panel.performClose(null)\n }\n\n function focus(focused) {\n if (browserWindow.isVisible()) {\n return\n }\n if (focused) {\n NSApplication.sharedApplication().activateIgnoringOtherApps(true)\n panel.makeKeyAndOrderFront(null)\n } else {\n panel.orderBack(null)\n }\n }\n\n browserWindow.focus = focus.bind(this, true)\n browserWindow.blur = focus.bind(this, false)\n\n browserWindow.isFocused = function() {\n return panel.isKeyWindow()\n }\n\n browserWindow.isDestroyed = function() {\n return browserWindow._destroyed\n }\n\n browserWindow.show = function() {\n // This method is supposed to put focus on window, however if the app does not\n // have focus then \"makeKeyAndOrderFront\" will only show the window.\n NSApp.activateIgnoringOtherApps(true)\n\n if (panel.delegate().utils.parentWindow) {\n return panel.delegate().utils.parentWindow.beginSheet_completionHandler(\n panel,\n __mocha__.createBlock_function('v16@?0q8', function() {\n browserWindow.emit('closed')\n })\n )\n }\n\n return panel.makeKeyAndOrderFront(null)\n }\n\n browserWindow.showInactive = function() {\n return panel.orderFrontRegardless()\n }\n\n browserWindow.hide = function() {\n return panel.orderOut(null)\n }\n\n browserWindow.isVisible = function() {\n return panel.isVisible()\n }\n\n browserWindow.isModal = function() {\n return false\n }\n\n browserWindow.maximize = function() {\n if (!browserWindow.isMaximized()) {\n panel.zoom(null)\n }\n }\n browserWindow.unmaximize = function() {\n if (browserWindow.isMaximized()) {\n panel.zoom(null)\n }\n }\n\n browserWindow.isMaximized = function() {\n if ((panel.styleMask() & NSResizableWindowMask) !== 0) {\n return panel.isZoomed()\n }\n var rectScreen = NSScreen.mainScreen().visibleFrame()\n var rectWindow = panel.frame()\n return (\n rectScreen.origin.x == rectWindow.origin.x &&\n rectScreen.origin.y == rectWindow.origin.y &&\n rectScreen.size.width == rectWindow.size.width &&\n rectScreen.size.height == rectWindow.size.height\n )\n }\n\n browserWindow.minimize = function() {\n return panel.miniaturize(null)\n }\n\n browserWindow.restore = function() {\n return panel.deminiaturize(null)\n }\n\n browserWindow.isMinimized = function() {\n return panel.isMiniaturized()\n }\n\n browserWindow.setFullScreen = function(fullscreen) {\n if (fullscreen !== browserWindow.isFullscreen()) {\n panel.toggleFullScreen(null)\n }\n }\n\n browserWindow.isFullscreen = function() {\n return panel.styleMask() & NSFullScreenWindowMask\n }\n\n browserWindow.setAspectRatio = function(aspectRatio /* , extraSize */) {\n // Reset the behaviour to default if aspect_ratio is set to 0 or less.\n if (aspectRatio > 0.0) {\n panel.setAspectRatio(NSMakeSize(aspectRatio, 1.0))\n } else {\n panel.setResizeIncrements(NSMakeSize(1.0, 1.0))\n }\n }\n\n browserWindow.setBounds = function(bounds, animate) {\n if (!bounds) {\n return\n }\n\n // Do nothing if in fullscreen mode.\n if (browserWindow.isFullscreen()) {\n return\n }\n\n const newBounds = Object.assign(browserWindow.getBounds(), bounds)\n\n // TODO: Check size constraints since setFrame does not check it.\n // var size = bounds.size\n // size.SetToMax(GetMinimumSize());\n // gfx::Size max_size = GetMaximumSize();\n // if (!max_size.IsEmpty())\n // size.SetToMin(max_size);\n\n var cocoaBounds = NSMakeRect(\n newBounds.x,\n 0,\n newBounds.width,\n newBounds.height\n )\n // Flip Y coordinates based on the primary screen\n var screen = NSScreen.screens().firstObject()\n cocoaBounds.origin.y = NSHeight(screen.frame()) - newBounds.y\n\n panel.setFrame_display_animate(cocoaBounds, true, animate)\n }\n\n browserWindow.getBounds = function() {\n const cocoaBounds = panel.frame()\n var mainScreenRect = NSScreen.screens()\n .firstObject()\n .frame()\n return {\n x: cocoaBounds.origin.x,\n y: Math.round(NSHeight(mainScreenRect) - cocoaBounds.origin.y),\n width: cocoaBounds.size.width,\n height: cocoaBounds.size.height,\n }\n }\n\n browserWindow.setContentBounds = function(bounds, animate) {\n // TODO:\n browserWindow.setBounds(bounds, animate)\n }\n\n browserWindow.getContentBounds = function() {\n // TODO:\n return browserWindow.getBounds()\n }\n\n browserWindow.setSize = function(width, height, animate) {\n // TODO: handle resizing around center\n return browserWindow.setBounds({ width: width, height: height }, animate)\n }\n\n browserWindow.getSize = function() {\n var bounds = browserWindow.getBounds()\n return [bounds.width, bounds.height]\n }\n\n browserWindow.setContentSize = function(width, height, animate) {\n // TODO: handle resizing around center\n return browserWindow.setContentBounds(\n { width: width, height: height },\n animate\n )\n }\n\n browserWindow.getContentSize = function() {\n var bounds = browserWindow.getContentBounds()\n return [bounds.width, bounds.height]\n }\n\n browserWindow.setMinimumSize = function(width, height) {\n const minSize = CGSizeMake(width, height)\n panel.setContentMinSize(minSize)\n }\n\n browserWindow.getMinimumSize = function() {\n const size = panel.contentMinSize()\n return [size.width, size.height]\n }\n\n browserWindow.setMaximumSize = function(width, height) {\n const maxSize = CGSizeMake(width, height)\n panel.setContentMaxSize(maxSize)\n }\n\n browserWindow.getMaximumSize = function() {\n const size = panel.contentMaxSize()\n return [size.width, size.height]\n }\n\n browserWindow.setResizable = function(resizable) {\n return browserWindow._setStyleMask(resizable, NSResizableWindowMask)\n }\n\n browserWindow.isResizable = function() {\n return panel.styleMask() & NSResizableWindowMask\n }\n\n browserWindow.setMovable = function(movable) {\n return panel.setMovable(movable)\n }\n browserWindow.isMovable = function() {\n return panel.isMovable()\n }\n\n browserWindow.setMinimizable = function(minimizable) {\n return browserWindow._setStyleMask(minimizable, NSMiniaturizableWindowMask)\n }\n\n browserWindow.isMinimizable = function() {\n return panel.styleMask() & NSMiniaturizableWindowMask\n }\n\n browserWindow.setMaximizable = function(maximizable) {\n if (panel.standardWindowButton(NSWindowZoomButton)) {\n panel.standardWindowButton(NSWindowZoomButton).setEnabled(maximizable)\n }\n }\n\n browserWindow.isMaximizable = function() {\n return (\n panel.standardWindowButton(NSWindowZoomButton) &&\n panel.standardWindowButton(NSWindowZoomButton).isEnabled()\n )\n }\n\n browserWindow.setFullScreenable = function(fullscreenable) {\n browserWindow._setCollectionBehavior(\n fullscreenable,\n NSWindowCollectionBehaviorFullScreenPrimary\n )\n // On EL Capitan this flag is required to hide fullscreen button.\n browserWindow._setCollectionBehavior(\n !fullscreenable,\n NSWindowCollectionBehaviorFullScreenAuxiliary\n )\n }\n\n browserWindow.isFullScreenable = function() {\n var collectionBehavior = panel.collectionBehavior()\n return collectionBehavior & NSWindowCollectionBehaviorFullScreenPrimary\n }\n\n browserWindow.setClosable = function(closable) {\n browserWindow._setStyleMask(closable, NSClosableWindowMask)\n }\n\n browserWindow.isClosable = function() {\n return panel.styleMask() & NSClosableWindowMask\n }\n\n browserWindow.setAlwaysOnTop = function(top, level, relativeLevel) {\n var windowLevel = NSNormalWindowLevel\n var maxWindowLevel = CGWindowLevelForKey(kCGMaximumWindowLevelKey)\n var minWindowLevel = CGWindowLevelForKey(kCGMinimumWindowLevelKey)\n\n if (top) {\n if (level === 'normal') {\n windowLevel = NSNormalWindowLevel\n } else if (level === 'torn-off-menu') {\n windowLevel = NSTornOffMenuWindowLevel\n } else if (level === 'modal-panel') {\n windowLevel = NSModalPanelWindowLevel\n } else if (level === 'main-menu') {\n windowLevel = NSMainMenuWindowLevel\n } else if (level === 'status') {\n windowLevel = NSStatusWindowLevel\n } else if (level === 'pop-up-menu') {\n windowLevel = NSPopUpMenuWindowLevel\n } else if (level === 'screen-saver') {\n windowLevel = NSScreenSaverWindowLevel\n } else if (level === 'dock') {\n // Deprecated by macOS, but kept for backwards compatibility\n windowLevel = NSDockWindowLevel\n } else {\n windowLevel = NSFloatingWindowLevel\n }\n }\n\n var newLevel = windowLevel + (relativeLevel || 0)\n if (newLevel >= minWindowLevel && newLevel <= maxWindowLevel) {\n panel.setLevel(newLevel)\n } else {\n throw new Error(\n 'relativeLevel must be between ' +\n minWindowLevel +\n ' and ' +\n maxWindowLevel\n )\n }\n }\n\n browserWindow.isAlwaysOnTop = function() {\n return panel.level() !== NSNormalWindowLevel\n }\n\n browserWindow.moveTop = function() {\n return panel.orderFrontRegardless()\n }\n\n browserWindow.center = function() {\n panel.center()\n }\n\n browserWindow.setPosition = function(x, y, animate) {\n return browserWindow.setBounds({ x: x, y: y }, animate)\n }\n\n browserWindow.getPosition = function() {\n var bounds = browserWindow.getBounds()\n return [bounds.x, bounds.y]\n }\n\n browserWindow.setTitle = function(title) {\n panel.setTitle(title)\n }\n\n browserWindow.getTitle = function() {\n return String(panel.title())\n }\n\n var attentionRequestId = 0\n browserWindow.flashFrame = function(flash) {\n if (flash) {\n attentionRequestId = NSApp.requestUserAttention(NSInformationalRequest)\n } else {\n NSApp.cancelUserAttentionRequest(attentionRequestId)\n attentionRequestId = 0\n }\n }\n\n browserWindow.getNativeWindowHandle = function() {\n return panel\n }\n\n browserWindow.getNativeWebViewHandle = function() {\n return webview\n }\n\n browserWindow.loadURL = function(url) {\n // When frameLocation is a file, prefix it with the Sketch Resources path\n if (/^(?!https?|file).*\\.html?$/.test(url)) {\n if (typeof __command !== 'undefined' && __command.pluginBundle()) {\n url =\n 'file://' +\n __command\n .pluginBundle()\n .urlForResourceNamed(url)\n .path()\n }\n }\n\n if (/^file:\\/\\/.*\\.html?$/.test(url)) {\n webview.loadFileURL_allowingReadAccessToURL(\n NSURL.fileURLWithPath(url),\n NSURL.fileURLWithPath('file:///')\n )\n return\n }\n\n const properURL = NSURL.URLWithString(url)\n const urlRequest = NSURLRequest.requestWithURL(properURL)\n\n webview.loadRequest(urlRequest)\n }\n\n browserWindow.reload = function() {\n webview.reload()\n }\n\n browserWindow.setHasShadow = function(hasShadow) {\n return panel.setHasShadow(hasShadow)\n }\n\n browserWindow.hasShadow = function() {\n return panel.hasShadow()\n }\n\n browserWindow.setOpacity = function(opacity) {\n return panel.setAlphaValue(opacity)\n }\n\n browserWindow.getOpacity = function() {\n return panel.alphaValue()\n }\n\n browserWindow.setVisibleOnAllWorkspaces = function(visible) {\n return browserWindow._setCollectionBehavior(\n visible,\n NSWindowCollectionBehaviorCanJoinAllSpaces\n )\n }\n\n browserWindow.isVisibleOnAllWorkspaces = function() {\n var collectionBehavior = panel.collectionBehavior()\n return collectionBehavior & NSWindowCollectionBehaviorCanJoinAllSpaces\n }\n\n browserWindow.setIgnoreMouseEvents = function(ignore) {\n return panel.setIgnoresMouseEvents(ignore)\n }\n\n browserWindow.setContentProtection = function(enable) {\n panel.setSharingType(enable ? NSWindowSharingNone : NSWindowSharingReadOnly)\n }\n\n browserWindow.setAutoHideCursor = function(autoHide) {\n panel.setDisableAutoHideCursor(autoHide)\n }\n\n browserWindow.setVibrancy = function(type) {\n var effectView = browserWindow._vibrantView\n\n if (!type) {\n if (effectView == null) {\n return\n }\n\n effectView.removeFromSuperview()\n panel.setVibrantView(null)\n return\n }\n\n if (effectView == null) {\n var contentView = panel.contentView()\n effectView = NSVisualEffectView.alloc().initWithFrame(\n contentView.bounds()\n )\n browserWindow._vibrantView = effectView\n\n effectView.setAutoresizingMask(NSViewWidthSizable | NSViewHeightSizable)\n effectView.setBlendingMode(NSVisualEffectBlendingModeBehindWindow)\n effectView.setState(NSVisualEffectStateActive)\n effectView.setFrame(contentView.bounds())\n contentView.addSubview_positioned_relativeTo(\n effectView,\n NSWindowBelow,\n null\n )\n }\n\n var vibrancyType = NSVisualEffectMaterialLight\n\n if (type === 'appearance-based') {\n vibrancyType = NSVisualEffectMaterialAppearanceBased\n } else if (type === 'light') {\n vibrancyType = NSVisualEffectMaterialLight\n } else if (type === 'dark') {\n vibrancyType = NSVisualEffectMaterialDark\n } else if (type === 'titlebar') {\n vibrancyType = NSVisualEffectMaterialTitlebar\n } else if (type === 'selection') {\n vibrancyType = NSVisualEffectMaterialSelection\n } else if (type === 'menu') {\n vibrancyType = NSVisualEffectMaterialMenu\n } else if (type === 'popover') {\n vibrancyType = NSVisualEffectMaterialPopover\n } else if (type === 'sidebar') {\n vibrancyType = NSVisualEffectMaterialSidebar\n } else if (type === 'medium-light') {\n vibrancyType = NSVisualEffectMaterialMediumLight\n } else if (type === 'ultra-dark') {\n vibrancyType = NSVisualEffectMaterialUltraDark\n }\n\n effectView.setMaterial(vibrancyType)\n }\n\n browserWindow._setBackgroundColor = function(colorName) {\n var color = parseHexColor(colorName)\n webview.setValue_forKey(false, 'drawsBackground')\n panel.backgroundColor = color\n }\n\n browserWindow._invalidate = function() {\n panel.flushWindow()\n panel.contentView().setNeedsDisplay(true)\n }\n\n browserWindow._setStyleMask = function(on, flag) {\n var wasMaximizable = browserWindow.isMaximizable()\n if (on) {\n panel.setStyleMask(panel.styleMask() | flag)\n } else {\n panel.setStyleMask(panel.styleMask() & ~flag)\n }\n // Change style mask will make the zoom button revert to default, probably\n // a bug of Cocoa or macOS.\n browserWindow.setMaximizable(wasMaximizable)\n }\n\n browserWindow._setCollectionBehavior = function(on, flag) {\n var wasMaximizable = browserWindow.isMaximizable()\n if (on) {\n panel.setCollectionBehavior(panel.collectionBehavior() | flag)\n } else {\n panel.setCollectionBehavior(panel.collectionBehavior() & ~flag)\n }\n // Change collectionBehavior will make the zoom button revert to default,\n // probably a bug of Cocoa or macOS.\n browserWindow.setMaximizable(wasMaximizable)\n }\n\n browserWindow._showWindowButton = function(button) {\n var view = panel.standardWindowButton(button)\n view.superview().addSubview_positioned_relative(view, NSWindowAbove, null)\n }\n}\n","module.exports = {\n JS_BRIDGE: '__skpm_sketchBridge',\n START_MOVING_WINDOW: '__skpm_startMovingWindow',\n STOP_MOVING_WINDOW: '__skpm_stopMovingWindow',\n MOVE_WINDOW: '__skpm_moveWindow',\n EXECUTE_JAVASCRIPT: '__skpm_executeJS',\n EXECUTE_JAVASCRIPT_SUCCESS: '__skpm_executeJS_success_',\n EXECUTE_JAVASCRIPT_ERROR: '__skpm_executeJS_error_',\n}\n","var tagsToFocus =\n '[\"text\", \"textarea\", \"date\", \"datetime-local\", \"email\", \"number\", \"month\", \"password\", \"search\", \"tel\", \"time\", \"url\", \"week\" ]'\n\nmodule.exports = function(webView, event) {\n var point = webView.convertPoint_fromView(event.locationInWindow(), null)\n var x = point.x\n var y = webView.frame().size.height - point.y // the coord start from the bottom instead of the top\n return (\n 'var el = document.elementFromPoint(' + // get the DOM element that match the event\n x +\n ', ' +\n y +\n '); ' +\n 'if (el && ' + // some tags need to be focused instead of clicked\n tagsToFocus +\n '.indexOf(el.type) >= 0 && ' +\n 'el.focus' +\n ') {' +\n 'el.focus();' + // so focus them\n '} else if (el) {' +\n 'el.dispatchEvent(new Event(\"click\", {bubbles: true}))' + // click the others\n '}'\n )\n}\n","var CONSTANTS = require('./constants')\n\nmodule.exports = function(webview, browserWindow) {\n function executeJavaScript(script, userGesture, callback) {\n if (typeof userGesture === 'function') {\n callback = userGesture\n userGesture = false\n }\n var fiber = coscript.createFiber()\n\n // if the webview is not ready yet, defer the execution until it is\n if (webview.navigationDelegate().valueForKey('state').wasReady == 0) {\n return new Promise(function(resolve, reject) {\n browserWindow.once('ready-to-show', function() {\n executeJavaScript(script, userGesture, callback)\n .then(resolve)\n .catch(reject)\n fiber.cleanup()\n })\n })\n }\n\n return new Promise(function(resolve, reject) {\n var requestId = Math.random()\n\n browserWindow.webContents.on(\n CONSTANTS.EXECUTE_JAVASCRIPT_SUCCESS + requestId,\n function(res) {\n try {\n if (callback) {\n callback(null, res)\n }\n resolve(res)\n } catch (_) {\n // /shrug\n }\n fiber.cleanup()\n }\n )\n browserWindow.webContents.on(\n CONSTANTS.EXECUTE_JAVASCRIPT_ERROR + requestId,\n function(err) {\n try {\n if (callback) {\n callback(err)\n resolve()\n } else {\n reject(err)\n }\n } catch (_) {\n // /shrug\n }\n fiber.cleanup()\n }\n )\n\n webview.evaluateJavaScript_completionHandler(\n 'window.' +\n CONSTANTS.EXECUTE_JAVASCRIPT +\n '(' +\n requestId +\n ', \"' +\n script.replace(/\"/g, '\\\\\"') +\n '\")',\n null\n )\n })\n }\n\n return executeJavaScript\n}\n\nmodule.exports.injectScript = function(webView) {\n var source =\n 'window.' +\n CONSTANTS.EXECUTE_JAVASCRIPT +\n ' = function(id, script) {' +\n ' try {' +\n ' var res = eval(script);' +\n ' if (res && typeof res.then === \"function\" && typeof res.catch === \"function\") {' +\n ' res.then(function (res2) {' +\n ' window.postMessage(\"' +\n CONSTANTS.EXECUTE_JAVASCRIPT_SUCCESS +\n '\" + id, res2);' +\n ' })' +\n ' .catch(function (err) {' +\n ' window.postMessage(\"' +\n CONSTANTS.EXECUTE_JAVASCRIPT_ERROR +\n '\" + id, err);' +\n ' })' +\n ' } else {' +\n ' window.postMessage(\"' +\n CONSTANTS.EXECUTE_JAVASCRIPT_SUCCESS +\n '\" + id, res);' +\n ' }' +\n ' } catch (err) {' +\n ' window.postMessage(\"' +\n CONSTANTS.EXECUTE_JAVASCRIPT_ERROR +\n '\" + id, err);' +\n ' }' +\n '}'\n var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(\n source,\n 0,\n true\n )\n webView\n .configuration()\n .userContentController()\n .addUserScript(script)\n}\n","function addEdgeConstraint(edge, subview, view, constant) {\n view.addConstraint(\n NSLayoutConstraint.constraintWithItem_attribute_relatedBy_toItem_attribute_multiplier_constant(\n subview,\n edge,\n NSLayoutRelationEqual,\n view,\n edge,\n 1,\n constant\n )\n )\n}\nmodule.exports = function fitSubviewToView(subview, view, constants) {\n constants = constants || []\n subview.setTranslatesAutoresizingMaskIntoConstraints(false)\n\n addEdgeConstraint(NSLayoutAttributeLeft, subview, view, constants[0] || 0)\n addEdgeConstraint(NSLayoutAttributeTop, subview, view, constants[1] || 0)\n addEdgeConstraint(NSLayoutAttributeRight, subview, view, constants[2] || 0)\n addEdgeConstraint(NSLayoutAttributeBottom, subview, view, constants[3] || 0)\n}\n","/* let's try to match the API from Electron's Browser window\n(https://github.com/electron/electron/blob/master/docs/api/browser-window.md) */\nvar EventEmitter = require('events')\nvar buildBrowserAPI = require('./browser-api')\nvar buildWebAPI = require('./webview-api')\nvar fitSubviewToView = require('./fitSubview')\nvar dispatchFirstClick = require('./dispatch-first-click')\nvar injectClientMessaging = require('./inject-client-messaging')\nvar movableArea = require('./movable-area')\nvar executeJavaScript = require('./execute-javascript')\nvar setDelegates = require('./set-delegates')\n\nfunction BrowserWindow(options) {\n options = options || {}\n\n var identifier = options.identifier || NSUUID.UUID().UUIDString()\n var threadDictionary = NSThread.mainThread().threadDictionary()\n\n var existingBrowserWindow = BrowserWindow.fromId(identifier)\n\n // if we already have a window opened, reuse it\n if (existingBrowserWindow) {\n return existingBrowserWindow\n }\n\n var browserWindow = new EventEmitter()\n browserWindow.id = identifier\n\n if (options.modal && !options.parent) {\n throw new Error('A modal needs to have a parent.')\n }\n\n // Long-running script\n var fiber = coscript.createFiber()\n\n // Window size\n var width = options.width || 800\n var height = options.height || 600\n var mainScreenRect = NSScreen.screens()\n .firstObject()\n .frame()\n var cocoaBounds = NSMakeRect(\n typeof options.x !== 'undefined'\n ? options.x\n : Math.round((NSWidth(mainScreenRect) - width) / 2),\n typeof options.y !== 'undefined'\n ? NSHeight(mainScreenRect) - options.y\n : Math.round((NSHeight(mainScreenRect) - height) / 2),\n width,\n height\n )\n\n if (options.titleBarStyle && options.titleBarStyle !== 'default') {\n options.frame = false\n }\n\n var useStandardWindow = options.windowType !== 'textured'\n var styleMask = NSTitledWindowMask\n\n // this is commented out because the toolbar doesn't appear otherwise :thinking-face:\n // if (!useStandardWindow || options.frame === false) {\n // styleMask = NSFullSizeContentViewWindowMask\n // }\n if (options.minimizable !== false) {\n styleMask |= NSMiniaturizableWindowMask\n }\n if (options.closable !== false) {\n styleMask |= NSClosableWindowMask\n }\n if (options.resizable !== false) {\n styleMask |= NSResizableWindowMask\n }\n if (!useStandardWindow || options.transparent || options.frame === false) {\n styleMask |= NSTexturedBackgroundWindowMask\n }\n\n var panel = NSPanel.alloc().initWithContentRect_styleMask_backing_defer(\n cocoaBounds,\n styleMask,\n NSBackingStoreBuffered,\n true\n )\n\n var wkwebviewConfig = WKWebViewConfiguration.alloc().init()\n var webView = WKWebView.alloc().initWithFrame_configuration(\n CGRectMake(0, 0, options.width || 800, options.height || 600),\n wkwebviewConfig\n )\n injectClientMessaging(webView)\n webView.setAutoresizingMask(NSViewWidthSizable | NSViewHeightSizable)\n\n buildBrowserAPI(browserWindow, panel, webView)\n buildWebAPI(browserWindow, panel, webView)\n setDelegates(browserWindow, panel, webView, options)\n\n if (options.windowType === 'desktop') {\n panel.setLevel(kCGDesktopWindowLevel - 1)\n // panel.setCanBecomeKeyWindow(false)\n panel.setCollectionBehavior(\n NSWindowCollectionBehaviorCanJoinAllSpaces |\n NSWindowCollectionBehaviorStationary |\n NSWindowCollectionBehaviorIgnoresCycle\n )\n }\n\n if (\n typeof options.minWidth !== 'undefined' ||\n typeof options.minHeight !== 'undefined'\n ) {\n browserWindow.setMinimumSize(options.minWidth || 0, options.minHeight || 0)\n }\n\n if (\n typeof options.maxWidth !== 'undefined' ||\n typeof options.maxHeight !== 'undefined'\n ) {\n browserWindow.setMaximumSize(\n options.maxWidth || 10000,\n options.maxHeight || 10000\n )\n }\n\n // if (options.focusable === false) {\n // panel.setCanBecomeKeyWindow(false)\n // }\n\n if (options.transparent || options.frame === false) {\n panel.titlebarAppearsTransparent = true\n panel.titleVisibility = NSWindowTitleHidden\n panel.setOpaque(0)\n panel.isMovableByWindowBackground = true\n var toolbar2 = NSToolbar.alloc().initWithIdentifier(\n 'titlebarStylingToolbar'\n )\n toolbar2.setShowsBaselineSeparator(false)\n panel.setToolbar(toolbar2)\n }\n\n if (options.titleBarStyle === 'hiddenInset') {\n var toolbar = NSToolbar.alloc().initWithIdentifier('titlebarStylingToolbar')\n toolbar.setShowsBaselineSeparator(false)\n panel.setToolbar(toolbar)\n }\n\n if (options.frame === false || !options.useContentSize) {\n browserWindow.setSize(width, height)\n }\n\n if (options.center) {\n browserWindow.center()\n }\n\n if (options.alwaysOnTop) {\n browserWindow.setAlwaysOnTop(true)\n }\n\n if (options.fullscreen) {\n browserWindow.setFullScreen(true)\n }\n browserWindow.setFullScreenable(!!options.fullscreenable)\n\n const title =\n options.title ||\n (typeof __command !== 'undefined' && __command.pluginBundle()\n ? __command.pluginBundle().name()\n : undefined)\n if (title) {\n browserWindow.setTitle(title)\n }\n\n var backgroundColor = options.backgroundColor\n if (options.transparent) {\n backgroundColor = NSColor.clearColor()\n }\n if (!backgroundColor && options.frame === false && options.vibrancy) {\n backgroundColor = NSColor.clearColor()\n }\n\n browserWindow._setBackgroundColor(\n backgroundColor || NSColor.windowBackgroundColor()\n )\n\n if (options.hasShadow === false) {\n browserWindow.setHasShadow(false)\n }\n\n if (typeof options.opacity !== 'undefined') {\n browserWindow.setOpacity(options.opacity)\n }\n\n options.webPreferences = options.webPreferences || {}\n\n webView\n .configuration()\n .preferences()\n .setValue_forKey(\n options.webPreferences.devTools !== false,\n 'developerExtrasEnabled'\n )\n webView\n .configuration()\n .preferences()\n .setValue_forKey(\n options.webPreferences.javascript !== false,\n 'javaScriptEnabled'\n )\n webView\n .configuration()\n .preferences()\n .setValue_forKey(!!options.webPreferences.plugins, 'plugInsEnabled')\n webView\n .configuration()\n .preferences()\n .setValue_forKey(\n options.webPreferences.minimumFontSize || 0,\n 'minimumFontSize'\n )\n\n if (options.webPreferences.zoomFactor) {\n webView.setMagnification(options.webPreferences.zoomFactor)\n }\n\n var contentView = panel.contentView()\n\n if (options.frame !== false) {\n webView.setFrame(contentView.bounds())\n contentView.addSubview(webView)\n } else {\n // In OSX 10.10, adding subviews to the root view for the NSView hierarchy\n // produces warnings. To eliminate the warnings, we resize the contentView\n // to fill the window, and add subviews to that.\n // http://crbug.com/380412\n contentView.setAutoresizingMask(NSViewWidthSizable | NSViewHeightSizable)\n fitSubviewToView(contentView, contentView.superview())\n\n webView.setFrame(contentView.bounds())\n contentView.addSubview(webView)\n\n // The fullscreen button should always be hidden for frameless window.\n if (panel.standardWindowButton(NSWindowFullScreenButton)) {\n panel.standardWindowButton(NSWindowFullScreenButton).setHidden(true)\n }\n\n if (!options.titleBarStyle || options.titleBarStyle === 'default') {\n // Hide the window buttons.\n panel.standardWindowButton(NSWindowZoomButton).setHidden(true)\n panel.standardWindowButton(NSWindowMiniaturizeButton).setHidden(true)\n panel.standardWindowButton(NSWindowCloseButton).setHidden(true)\n\n // Some third-party macOS utilities check the zoom button's enabled state to\n // determine whether to show custom UI on hover, so we disable it here to\n // prevent them from doing so in a frameless app window.\n panel.standardWindowButton(NSWindowZoomButton).setEnabled(false)\n }\n }\n\n if (options.vibrancy) {\n browserWindow.setVibrancy(options.vibrancy)\n }\n\n // Set maximizable state last to ensure zoom button does not get reset\n // by calls to other APIs.\n browserWindow.setMaximizable(options.maximizable !== false)\n\n if (options.acceptsFirstMouse) {\n browserWindow.on('focus', function(event) {\n if (event.type() === NSEventTypeLeftMouseDown) {\n browserWindow.webContents\n .executeJavaScript(dispatchFirstClick(webView, event))\n .catch(() => {})\n }\n })\n }\n\n executeJavaScript.injectScript(webView)\n movableArea.injectScript(webView)\n movableArea.setupHandler(browserWindow)\n\n if (options.show !== false) {\n browserWindow.show()\n }\n\n browserWindow.on('closed', function() {\n browserWindow._destroyed = true\n threadDictionary.removeObjectForKey(identifier)\n fiber.cleanup()\n })\n\n threadDictionary[identifier] = panel\n\n fiber.onCleanup(function() {\n if (!browserWindow._destroyed) {\n browserWindow.destroy()\n }\n })\n\n return browserWindow\n}\n\nBrowserWindow.fromId = function(identifier) {\n var threadDictionary = NSThread.mainThread().threadDictionary()\n\n if (threadDictionary[identifier]) {\n return BrowserWindow.fromPanel(threadDictionary[identifier], identifier)\n }\n\n return undefined\n}\n\nBrowserWindow.fromPanel = function(panel, identifier) {\n var browserWindow = new EventEmitter()\n browserWindow.id = identifier\n\n if (!panel || !panel.contentView) {\n throw new Error('needs to pass an NSPanel')\n }\n\n var webView = panel.contentView().subviews()[0]\n\n if (!webView) {\n throw new Error('The NSPanel needs to have a webview')\n }\n\n buildBrowserAPI(browserWindow, panel, webView)\n buildWebAPI(browserWindow, panel, webView)\n\n return browserWindow\n}\n\nmodule.exports = BrowserWindow\n","var CONSTANTS = require('./constants')\n\nmodule.exports = function(webView) {\n var source =\n 'window.originalPostMessage = window.postMessage;' +\n 'window.postMessage = function(actionName) {' +\n 'if (!actionName) {' +\n \"throw new Error('missing action name')\" +\n '}' +\n 'window.webkit.messageHandlers.' +\n CONSTANTS.JS_BRIDGE +\n '.postMessage(' +\n 'JSON.stringify([].slice.call(arguments))' +\n ');' +\n '}'\n var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(\n source,\n 0,\n true\n )\n webView\n .configuration()\n .userContentController()\n .addUserScript(script)\n}\n","var CONSTANTS = require('./constants')\n\nmodule.exports.injectScript = function(webView) {\n var source =\n '(function () {' +\n 'var animationId = null;' +\n \"document.addEventListener('mousedown', onMouseDown);\" +\n '' +\n 'function shouldDrag(target) {' +\n ' if (!target || (target.dataset || {}).appRegion === \"no-drag\") { return false }' +\n ' if ((target.dataset || {}).appRegion === \"drag\") { return true }' +\n ' return shouldDrag(target.parentElement)' +\n '};' +\n '' +\n 'function onMouseDown(e) {' +\n ' if (e.button !== 0 || !shouldDrag(e.target)) { return }' +\n ' window.postMessage(\"' +\n CONSTANTS.START_MOVING_WINDOW +\n '\");' +\n \" document.addEventListener('mouseup', onMouseUp);\" +\n ' animationId = requestAnimationFrame(moveWindow);' +\n '};' +\n '' +\n 'function onMouseUp(e) {' +\n ' window.postMessage(\"' +\n CONSTANTS.STOP_MOVING_WINDOW +\n '\");' +\n \" document.removeEventListener('mouseup', onMouseUp);\" +\n ' cancelAnimationFrame(animationId);' +\n '};' +\n '' +\n 'function moveWindow(e) {' +\n ' window.postMessage(\"' +\n CONSTANTS.MOVE_WINDOW +\n '\");' +\n ' animationId = requestAnimationFrame(moveWindow);' +\n '}' +\n '})()'\n var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(\n source,\n 0,\n true\n )\n webView\n .configuration()\n .userContentController()\n .addUserScript(script)\n}\n\nmodule.exports.setupHandler = function(browserWindow) {\n var initialMouseLocation = null\n var initialWindowPosition = null\n\n browserWindow.webContents.on(CONSTANTS.START_MOVING_WINDOW, function() {\n initialMouseLocation = NSEvent.mouseLocation()\n var position = browserWindow.getPosition()\n initialWindowPosition = {\n x: position[0],\n y: position[1],\n }\n })\n\n browserWindow.webContents.on(CONSTANTS.STOP_MOVING_WINDOW, function() {\n initialMouseLocation = null\n initialWindowPosition = null\n })\n\n browserWindow.webContents.on(CONSTANTS.MOVE_WINDOW, function() {\n if (!initialWindowPosition) {\n return\n }\n const mouse = NSEvent.mouseLocation()\n browserWindow.setPosition(\n initialWindowPosition.x + (mouse.x - initialMouseLocation.x),\n initialWindowPosition.y + (initialMouseLocation.y - mouse.y), // y is inverted\n false\n )\n })\n}\n","module.exports = function(webArguments) {\n var args = null\n try {\n args = JSON.parse(webArguments)\n } catch (e) {\n // malformed arguments\n }\n\n if (\n !args ||\n !args.constructor ||\n args.constructor !== Array ||\n args.length == 0\n ) {\n return null\n }\n\n return args\n}\n","var ObjCClass = require('cocoascript-class').default\nvar parseWebArguments = require('./parseWebArguments')\nvar CONSTANTS = require('./constants')\n\n// We create one ObjC class for ourselves here\nvar WindowDelegateClass\nvar NavigationDelegateClass\nvar WebScriptHandlerClass\n\n// TODO: events\n// - 'page-favicon-updated'\n// - 'new-window'\n// - 'did-navigate-in-page'\n// - 'will-prevent-unload'\n// - 'crashed'\n// - 'unresponsive'\n// - 'responsive'\n// - 'destroyed'\n// - 'before-input-event'\n// - 'certificate-error'\n// - 'found-in-page'\n// - 'media-started-playing'\n// - 'media-paused'\n// - 'did-change-theme-color'\n// - 'update-target-url'\n// - 'cursor-changed'\n// - 'context-menu'\n// - 'select-bluetooth-device'\n// - 'paint'\n// - 'console-message'\n\nmodule.exports = function(browserWindow, panel, webview, options) {\n if (!WindowDelegateClass) {\n WindowDelegateClass = ObjCClass({\n classname: 'WindowDelegateClass',\n utils: null,\n panel: null,\n\n 'windowDidResize:': function() {\n this.utils.emit('resize')\n },\n\n 'windowDidMiniaturize:': function() {\n this.utils.emit('minimize')\n },\n\n 'windowDidDeminiaturize:': function() {\n this.utils.emit('restore')\n },\n\n 'windowDidEnterFullScreen:': function() {\n this.utils.emit('enter-full-screen')\n },\n\n 'windowDidExitFullScreen:': function() {\n this.utils.emit('leave-full-screen')\n },\n\n 'windowDidMove:': function() {\n this.utils.emit('move')\n this.utils.emit('moved')\n },\n\n 'windowShouldClose:': function() {\n var shouldClose = true\n this.utils.emit('close', {\n get defaultPrevented() {\n return !shouldClose\n },\n preventDefault: function() {\n shouldClose = false\n },\n })\n return shouldClose\n },\n\n 'windowWillClose:': function() {\n this.utils.emit('closed')\n },\n\n 'windowDidBecomeKey:': function() {\n this.utils.emit('focus', this.panel.currentEvent())\n },\n\n 'windowDidResignKey:': function() {\n this.utils.emit('blur')\n },\n })\n }\n\n if (!NavigationDelegateClass) {\n NavigationDelegateClass = ObjCClass({\n classname: 'NavigationDelegateClass',\n state: NSMutableDictionary.dictionaryWithDictionary({\n wasReady: 0,\n }),\n utils: null,\n\n // // Called when the web view begins to receive web content.\n 'webView:didCommitNavigation:': function(webView) {\n this.utils.emit('will-navigate', {}, String(String(webView.URL())))\n },\n\n // // Called when web content begins to load in a web view.\n 'webView:didStartProvisionalNavigation:': function() {\n this.utils.emit('did-start-navigation')\n this.utils.emit('did-start-loading')\n },\n\n // Called when a web view receives a server redirect.\n 'webView:didReceiveServerRedirectForProvisionalNavigation:': function() {\n this.utils.emit('did-get-redirect-request')\n },\n\n // // Called when the web view needs to respond to an authentication challenge.\n // 'webView:didReceiveAuthenticationChallenge:completionHandler:': function(\n // webView,\n // challenge,\n // completionHandler\n // ) {\n // function callback(username, password) {\n // completionHandler(\n // 0,\n // NSURLCredential.credentialWithUser_password_persistence(\n // username,\n // password,\n // 1\n // )\n // )\n // }\n // var protectionSpace = challenge.protectionSpace()\n // this.utils.emit(\n // 'login',\n // {},\n // {\n // method: String(protectionSpace.authenticationMethod()),\n // url: 'not implemented', // TODO:\n // referrer: 'not implemented', // TODO:\n // },\n // {\n // isProxy: !!protectionSpace.isProxy(),\n // scheme: String(protectionSpace.protocol()),\n // host: String(protectionSpace.host()),\n // port: Number(protectionSpace.port()),\n // realm: String(protectionSpace.realm()),\n // },\n // callback\n // )\n // },\n\n // Called when an error occurs during navigation.\n // 'webView:didFailNavigation:withError:': function(\n // webView,\n // navigation,\n // error\n // ) {},\n\n // Called when an error occurs while the web view is loading content.\n 'webView:didFailProvisionalNavigation:withError:': function(\n webView,\n navigation,\n error\n ) {\n this.utils.emit('did-fail-load', error)\n },\n\n // Called when the navigation is complete.\n 'webView:didFinishNavigation:': function() {\n if (this.state.wasReady == 0) {\n this.state.setObject_forKey(1, 'wasReady')\n this.utils.emitBrowserEvent('ready-to-show')\n }\n this.utils.emit('did-navigate')\n this.utils.emit('did-frame-navigate')\n this.utils.emit('did-stop-loading')\n this.utils.emit('did-finish-load')\n this.utils.emit('did-frame-finish-load')\n },\n\n // Called when the web view’s web content process is terminated.\n 'webViewWebContentProcessDidTerminate:': function() {\n this.utils.emit('dom-ready')\n },\n\n // Decides whether to allow or cancel a navigation.\n // webView:decidePolicyForNavigationAction:decisionHandler:\n\n // Decides whether to allow or cancel a navigation after its response is known.\n // webView:decidePolicyForNavigationResponse:decisionHandler:\n })\n }\n\n if (!WebScriptHandlerClass) {\n WebScriptHandlerClass = ObjCClass({\n classname: 'WebScriptHandlerClass',\n utils: null,\n 'userContentController:didReceiveScriptMessage:': function(_, message) {\n var args = this.utils.parseWebArguments(String(message.body()))\n if (!args) {\n return\n }\n if (!args[0] || typeof args[0] !== 'string') {\n return\n }\n args[0] = String(args[0])\n\n this.utils.emit.apply(this, args)\n },\n })\n }\n\n var navigationDelegate = NavigationDelegateClass.new()\n navigationDelegate.utils = NSDictionary.dictionaryWithDictionary({\n setTitle: browserWindow.setTitle.bind(browserWindow),\n emitBrowserEvent() {\n try {\n browserWindow.emit.apply(browserWindow, arguments)\n } catch (err) {\n console.error(err)\n throw err\n }\n },\n emit() {\n try {\n browserWindow.webContents.emit.apply(\n browserWindow.webContents,\n arguments\n )\n } catch (err) {\n console.error(err)\n throw err\n }\n },\n })\n // reset state as well\n navigationDelegate.state = NSMutableDictionary.dictionaryWithDictionary({\n wasReady: 0,\n })\n\n webview.setNavigationDelegate(navigationDelegate)\n\n var webScriptHandler = WebScriptHandlerClass.new()\n webScriptHandler.utils = NSDictionary.dictionaryWithDictionary({\n emit() {\n try {\n browserWindow.webContents.emit.apply(\n browserWindow.webContents,\n arguments\n )\n } catch (err) {\n console.error(err)\n throw err\n }\n },\n parseWebArguments: parseWebArguments,\n })\n\n webview\n .configuration()\n .userContentController()\n .addScriptMessageHandler_name(webScriptHandler, CONSTANTS.JS_BRIDGE)\n\n var windowDelegate = WindowDelegateClass.new()\n var utils = {\n emit() {\n try {\n browserWindow.emit.apply(browserWindow, arguments)\n } catch (err) {\n console.error(err)\n throw err\n }\n },\n }\n if (options.modal) {\n // find the window of the document\n var msdocument\n if (options.parent.type === 'Document') {\n msdocument = options.parent.sketchObject\n } else {\n msdocument = options.parent\n }\n if (msdocument && String(msdocument.class()) === 'MSDocumentData') {\n // we only have an MSDocumentData instead of a MSDocument\n // let's try to get back to the MSDocument\n msdocument = msdocument.delegate()\n }\n utils.parentWindow = msdocument.windowForSheet()\n }\n\n windowDelegate.utils = NSDictionary.dictionaryWithDictionary(utils)\n windowDelegate.panel = panel\n\n panel.setDelegate(windowDelegate)\n}\n","var EventEmitter = require('events')\nvar executeJavaScript = require('./execute-javascript')\n\n// let's try to match https://github.com/electron/electron/blob/master/docs/api/web-contents.md\nmodule.exports = function buildAPI(browserWindow, panel, webview) {\n var webContents = new EventEmitter()\n\n webContents.loadURL = browserWindow.loadURL\n\n webContents.loadFile = function(/* filePath */) {\n // TODO:\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n\n webContents.downloadURL = function(/* filePath */) {\n // TODO:\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n\n webContents.getURL = function() {\n return String(webview.url())\n }\n\n webContents.getTitle = function() {\n return String(webview.title())\n }\n\n webContents.isDestroyed = function() {\n // TODO:\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n\n webContents.focus = browserWindow.focus\n webContents.isFocused = browserWindow.isFocused\n\n webContents.isLoading = function() {\n return !!webview.loading()\n }\n\n webContents.isLoadingMainFrame = function() {\n // TODO:\n return !!webview.loading()\n }\n\n webContents.isWaitingForResponse = function() {\n return !webview.loading()\n }\n\n webContents.stop = function() {\n webview.stopLoading()\n }\n webContents.reload = function() {\n webview.reload()\n }\n webContents.reloadIgnoringCache = function() {\n webview.reloadFromOrigin()\n }\n webContents.canGoBack = function() {\n return !!webview.canGoBack()\n }\n webContents.canGoForward = function() {\n return !!webview.canGoForward()\n }\n webContents.canGoToOffset = function(offset) {\n return !!webview.backForwardList().itemAtIndex(offset)\n }\n webContents.clearHistory = function() {\n // TODO:\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n webContents.goBack = function() {\n webview.goBack()\n }\n webContents.goForward = function() {\n webview.goForward()\n }\n webContents.goToIndex = function(index) {\n var backForwardList = webview.backForwardList()\n var backList = backForwardList.backList()\n var backListLength = backList.count()\n if (backListLength > index) {\n webview.loadRequest(NSURLRequest.requestWithURL(backList[index]))\n return\n }\n var forwardList = backForwardList.forwardList()\n if (forwardList.count() > index - backListLength) {\n webview.loadRequest(\n NSURLRequest.requestWithURL(forwardList[index - backListLength])\n )\n return\n }\n throw new Error('Cannot go to index ' + index)\n }\n webContents.goToOffset = function(offset) {\n if (!webContents.canGoToOffset(offset)) {\n throw new Error('Cannot go to offset ' + offset)\n }\n webview.loadRequest(\n NSURLRequest.requestWithURL(webview.backForwardList().itemAtIndex(offset))\n )\n }\n webContents.isCrashed = function() {\n // TODO:\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n webContents.setUserAgent = function(/* userAgent */) {\n // TODO:\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n webContents.getUserAgent = function() {\n const userAgent = webview.customUserAgent()\n return userAgent ? String(userAgent) : undefined\n }\n webContents.insertCSS = function(css) {\n var source =\n \"var style = document.createElement('style'); style.innerHTML = \" +\n css.replace(/\"/, '\\\\\"') +\n '; document.head.appendChild(style);'\n var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(\n source,\n 0,\n true\n )\n webview\n .configuration()\n .userContentController()\n .addUserScript(script)\n }\n webContents.insertJS = function(source) {\n var script = WKUserScript.alloc().initWithSource_injectionTime_forMainFrameOnly(\n source,\n 0,\n true\n )\n webview\n .configuration()\n .userContentController()\n .addUserScript(script)\n }\n webContents.executeJavaScript = executeJavaScript(webview, browserWindow)\n webContents.setIgnoreMenuShortcuts = function() {\n // TODO:??\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n webContents.setAudioMuted = function(/* muted */) {\n // TODO:??\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n webContents.isAudioMuted = function() {\n // TODO:??\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n webContents.setZoomFactor = function(factor) {\n webview.setMagnification_centeredAtPoint(factor, CGPointMake(0, 0))\n }\n webContents.getZoomFactor = function(callback) {\n callback(Number(webview.magnification()))\n }\n webContents.setZoomLevel = function(level) {\n // eslint-disable-next-line no-restricted-properties\n webContents.setZoomFactor(Math.pow(1.2, level))\n }\n webContents.getZoomLevel = function(callback) {\n // eslint-disable-next-line no-restricted-properties\n callback(Math.log(Number(webview.magnification())) / Math.log(1.2))\n }\n webContents.setVisualZoomLevelLimits = function(/* minimumLevel, maximumLevel */) {\n // TODO:??\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n webContents.setLayoutZoomLevelLimits = function(/* minimumLevel, maximumLevel */) {\n // TODO:??\n console.warn(\n 'Not implemented yet, please open a PR on https://github.com/skpm/sketch-module-web-view :)'\n )\n }\n\n // TODO:\n // webContents.undo = function() {\n // webview.undoManager().undo()\n // }\n // webContents.redo = function() {\n // webview.undoManager().redo()\n // }\n // webContents.cut = webview.cut\n // webContents.copy = webview.copy\n // webContents.paste = webview.paste\n // webContents.pasteAndMatchStyle = webview.pasteAsRichText\n // webContents.delete = webview.delete\n // webContents.replace = webview.replaceSelectionWithText\n\n webContents.send = function() {\n const script =\n 'window.postMessage({' +\n 'isSketchMessage: true,' +\n \"origin: '\" +\n String(__command.identifier()) +\n \"',\" +\n 'args: ' +\n JSON.stringify([].slice.call(arguments)) +\n '}, \"*\")'\n webview.evaluateJavaScript_completionHandler(script, null)\n }\n\n webContents.getNativeWebview = function() {\n return webview\n }\n\n browserWindow.webContents = webContents\n}\n","module.exports = \"file://\" + context.plugin.urlForResourceNamed(\"_webpack_resources/43aa738f582ce37c61cb81dcdf421b63.html\").path();","import sketch from 'sketch';\n\n// resize logic\nconst resize = (selection, dimensions) => {\n for (let layer of selection.layers) {\n const frame = layer.frame;\n const finalDimensions = process(dimensions, frame.width, frame.height);\n frame.width = finalDimensions.width;\n frame.height = finalDimensions.height;\n }\n\n sketch.UI.message(`Resized ${selection.length} layer(s)`);\n};\n\n// process dimensions, and replace %w, and %h\nconst process = (dimensions, originalWidth, originalHeight) => ({\n width: eval(sanitize(dimensions.width, originalWidth, originalHeight)),\n height: eval(sanitize(dimensions.height, originalWidth, originalHeight)),\n});\n\nconst sanitize = (string, w, h) => string.replace(/%w/gi, w).replace(/%h/gi, h);\n\nexport default resize;\n","import BrowserWindow from 'sketch-module-web-view';\nimport sketch from 'sketch';\nimport resize from './actions/resize';\n\n// main function\nconst main = () => {\n const document = sketch.getSelectedDocument();\n const selection = document.selectedLayers;\n\n // return error message if selection is empty\n if (selection.isEmpty) {\n sketch.UI.message('No layer(s) selected!');\n return;\n }\n\n // define the webview, its options, and its content\n const options = {\n identifier: 'sketch.resize',\n width: 480,\n height: 316,\n center: true,\n show: false,\n backgroundColor: '#181818',\n titleBarStyle: 'hiddenInset',\n alwaysOnTop: true,\n resizable: false,\n fullscreenable: false,\n maximizable: false,\n minimizable: false,\n };\n\n let webview = new BrowserWindow(options);\n const webcontent = webview.webContents;\n\n // when loaded, show the webview\n webview.once('ready-to-show', () => webview.show());\n\n // cancel the overall process\n webcontent.on('cancel', () => close(webview));\n\n // process input, and trigger resize\n webcontent.on('submit', dimensions => {\n resize(selection, dimensions);\n close(webview);\n });\n\n // show the webview\n webview.loadURL(require('../resources/webview/webview.html'));\n};\n\n// close the window\nconst close = webview => {\n webview.close();\n webview = null;\n};\n\nexport default main;\n","module.exports = require(\"events\");","module.exports = require(\"sketch\");"],"sourceRoot":""}
--------------------------------------------------------------------------------
/Sketch Resize.sketchplugin/Contents/Sketch/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Luca Orio",
3 | "name": "Resize",
4 | "compatibleVersion": 3,
5 | "bundleVersion": 1,
6 | "identifier": "com.sketch.resize",
7 | "icon": "sketch-icon.png",
8 | "appcast": "https://raw.githubusercontent.com/lucaorio/sketch-resize/master/appcast.xml",
9 | "commands": [
10 | {
11 | "name": "Resize Elements",
12 | "identifier": "main",
13 | "script": "main.js",
14 | "description": "Resize (not scale) multiple layers at once via shortcut",
15 | "icon": "resize.png",
16 | "shortcut": "ctrl cmd k"
17 | }
18 | ],
19 | "menu": {
20 | "title": "Resize",
21 | "items": [
22 | "main"
23 | ]
24 | },
25 | "version": "2.1.0",
26 | "description": "Resize (not scale) multiple layers at once via shortcut",
27 | "homepage": "https://github.com/lucaorio/sketch-resize#readme",
28 | "disableCocoaScriptPreprocessor": true
29 | }
--------------------------------------------------------------------------------
/appcast.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Sketch Resize
5 | https://github.com/lucaorio/sketch-resize
6 | Resize (not scale) multiple layers at once via shortcut.
7 | en
8 | -
9 |
Sketch Resize 1.0.0
10 |
11 |
13 | First Release
14 |
15 | ]]>
16 |
17 |
18 |
19 | -
20 |
Sketch Resize 1.0.1
21 |
22 |
24 | Changed plugin description
25 | Changed dialog description
26 |
27 | ]]>
28 |
29 |
30 |
31 | -
32 |
Sketch Resize 1.0.2
33 |
34 |
36 | Various bugfixes
37 |
38 | ]]>
39 |
40 |
41 |
42 | -
43 |
Sketch Resize 2.0.0
44 |
45 |
47 | Total rewrite
48 |
49 | ]]>
50 |
51 |
52 |
53 | -
54 |
Sketch Resize 2.1.0
55 |
56 |
58 | Added regular icon
59 |
60 | ]]>
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/assets/resize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/assets/resize.png
--------------------------------------------------------------------------------
/assets/sketch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/assets/sketch-icon.png
--------------------------------------------------------------------------------
/images/img-header.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/images/img-header.jpg
--------------------------------------------------------------------------------
/images/img-sketch-resize.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/images/img-sketch-resize.jpg
--------------------------------------------------------------------------------
/images/img-sketch-reverse.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/images/img-sketch-reverse.jpg
--------------------------------------------------------------------------------
/images/img-sketch-runner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/images/img-sketch-runner.jpg
--------------------------------------------------------------------------------
/images/img-sketch-styles-generator.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/images/img-sketch-styles-generator.jpg
--------------------------------------------------------------------------------
/images/img-usage.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lucaorio/sketch-resize/b2babc188b7e6e362588c971807f75bf48b4dcd0/images/img-usage.gif
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Luca Orio (lucaorio.com)
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
13 | all 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
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sketch-resize",
3 | "version": "2.1.0",
4 | "description": "Resize (not scale) multiple layers at once via shortcut",
5 | "author": "Luca Orio ",
6 | "homepage": "https://github.com/lucaorio/sketch-resize#readme",
7 | "license": "MIT",
8 | "repository": {
9 | "type": "git",
10 | "url": "git+https://github.com/lucaorio/sketch-resize.git"
11 | },
12 | "keywords": [
13 | "sketch",
14 | "sketchapp",
15 | "plugin",
16 | "resize",
17 | "scale",
18 | "unproportional",
19 | "unproportional resize",
20 | "unproportional scale"
21 | ],
22 | "engines": {
23 | "sketch": ">=54.0"
24 | },
25 | "bugs": {
26 | "url": "https://github.com/lucaorio/sketch-resize/issues"
27 | },
28 | "scripts": {
29 | "watch": "skpm-build --watch",
30 | "lint": "eslint src/**/*.js && prettier --write src/**/*.js",
31 | "build": "yarn lint && skpm-build",
32 | "postinstall": "yarn build && skpm-link"
33 | },
34 | "assets": [
35 | "assets/**/*.*"
36 | ],
37 | "resources": [
38 | "resources/webview/**/*.js"
39 | ],
40 | "skpm": {
41 | "name": "Sketch Resize",
42 | "manifest": "src/manifest.json",
43 | "main": "Sketch Resize.sketchplugin"
44 | },
45 | "devDependencies": {
46 | "@skpm/builder": "^0.5.11",
47 | "@skpm/extract-loader": "^2.0.2",
48 | "babel-eslint": "^10.0.1",
49 | "css-loader": "^1.0.0",
50 | "eslint": "^5.11.1",
51 | "eslint-plugin-import": "^2.14.0",
52 | "html-loader": "^0.5.1",
53 | "prettier": "^1.16.4",
54 | "sketch-module-web-view": "^3.0.1"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | # Sketch Resize
2 |
3 | 
4 |
5 | > Resize (not scale) multiple layers at once via shortcut
6 |
7 | **Sketch Resize** is a plugin made for [Sketch](http://sketchapp.com). It provides unproportional, unconstrained resize for multiple selected layer. It's triggered via shortcut, and doesn't require to reach nor focus the inspector panel.
8 |
9 | Given a selection containing multiple layers, _Resize_ tries to avoid the following limitations:
10 |
11 | - The **scale layers** feature (`cmd+k`) affects width, height, and some other properties at once, proportionally
12 | - After focusing the inspector panel via shortcut (`alt+tab`), in order to resize anything we need to tab twice, enter the width, tab once, enter the height, blur the panel (or press enter)
13 | - The inspector panel could be very far away from the current position of the mouse cursor
14 | - Nudging and dragging could be slow, or imprecise
15 |
16 | Follow me on Twitter [@lucaorio\_](https://twitter.com/lucaorio_) for updates, help and other stuff! 🎉
17 |
18 | _Looking for other plugins? Give these a try!_ 😎
19 |
20 | [ ](https://github.com/lucaorio/sketch-styles-generator)
21 | [ ](https://github.com/lucaorio/sketch-reverse)
22 |
23 | ## Contents
24 |
25 | - [Installation](#installation)
26 | - [Usage](#usage)
27 | - [Integrations](#integrations)
28 | - [License](#license)
29 | - [Contacts](#contacts)
30 |
31 | ## Installation
32 |
33 | #### Manual
34 |
35 | - [Download](https://github.com/lucaorio/sketch-resize/releases/latest) the latest release of the plugin [`sketch-resize.zip`](https://github.com/lucaorio/sketch-resize/releases/latest)
36 | - Uncompress the downloaded file
37 | - Double-click `Sketch Resize.sketchplugin` to install
38 |
39 | #### Via Sketch Runner
40 |
41 | - Trigger [Sketch Runner](http://bit.ly/SketchRunnerWebsite) (`cmd+'`)
42 | - Move to the _Install_ tab
43 | - Search for _Resize_, and install
44 |
45 | ## Usage
46 |
47 | - **Select** layer(s)
48 | - **Run** the plugin by clicking `Plugins->Resize->Resize Elements`, or by using the `ctrl+cmd+k` shortcut
49 | - Specify the new **dimension(s)**, and press `enter` to confirm
50 |
51 | #### Some additional notes
52 |
53 | - The plugin can be used on _single layers_, too
54 | - Width/height can be both _declared at once_. Leaving a field empty, or in its default state (%w/%h) will _skip_ the related dimension
55 | - Width/height input fields accepts _basic math operations_ (ie.`%w+%h+(10+20)-8/4*2`), where %w/%h are references to the _original size of each layer_
56 | - Press `tab` to _focus_ between the width/height input fields, and cancel/confirm buttons
57 | - Press `esc` to _close the panel_ and leave the dimensions unchanged
58 | - Pressing `enter` will always trigger the _confirm_ button, no matter the focused element
59 |
60 | 
61 |
62 | ## Integrations
63 |
64 | _Sketch Resize_ is fully integrated with [Sketch Runner](http://bit.ly/SketchRunnerWebsite), the ultimate tool to speed up your Sketch workflow. You can trigger the plugin by simply typing its name.
65 |
66 | 
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | ## License
77 |
78 | 
79 |
80 | ---
81 |
82 | ## Contacts
83 |
84 | - 🐦 Twitter [@lucaorio\_](http://twitter.com/@lucaorio_)
85 | - 🕸 Website [lucaorio.com](http://lucaorio.com)
86 | - 📬 Email [luca.o@me.com](mailto:luca.o@me.com)
87 |
--------------------------------------------------------------------------------
/resources/webview/script.js:
--------------------------------------------------------------------------------
1 | // disable context menu
2 | document.addEventListener('contextmenu', event => {
3 | event.preventDefault();
4 | });
5 |
6 | // cancel button
7 | document.getElementById('cancel').addEventListener('click', event => {
8 | event.preventDefault();
9 | window.postMessage('cancel');
10 | });
11 |
12 | // submit on enter
13 | document.addEventListener('keypress', event => {
14 | if (event.keyCode !== 13) return;
15 | event.preventDefault();
16 | window.postMessage('submit', getValues());
17 | });
18 |
19 | // submit button
20 | document.getElementById('submit').addEventListener('click', event => {
21 | event.preventDefault();
22 | window.postMessage('submit', getValues());
23 | });
24 |
25 | // get inputs value
26 | const getValues = () => ({
27 | width: document.getElementById('width').value,
28 | height: document.getElementById('height').value
29 | });
30 |
--------------------------------------------------------------------------------
/resources/webview/styles.css:
--------------------------------------------------------------------------------
1 | html {
2 | box-sizing: border-box;
3 | overflow: hidden;
4 | padding: 1px;
5 | color: #9c9c9c;
6 | background: #171717;
7 | font-family: -apple-system;
8 | font-size: 13px;
9 | line-height: 20px;
10 | cursor: default;
11 | }
12 |
13 | *,
14 | *:before,
15 | *:after {
16 | position: relative;
17 | box-sizing: inherit;
18 | margin: 0;
19 | padding: 0;
20 | -webkit-user-select: none;
21 | user-select: none;
22 | }
23 |
24 | input,
25 | textarea {
26 | -webkit-user-select: auto;
27 | user-select: auto;
28 | }
29 |
30 | /* -------------------------------- */
31 | /* header/menubar */
32 | /* -------------------------------- */
33 |
34 | header {
35 | border-bottom: 1px solid #000000;
36 | height: 37px;
37 | color: rgba(255, 255, 255, 0.7);
38 | background-color: #242424;
39 | font-weight: 600;
40 | line-height: 37px;
41 | text-align: center;
42 | }
43 |
44 | /* -------------------------------- */
45 | /* section/content */
46 | /* -------------------------------- */
47 |
48 | section {
49 | padding: 24px;
50 | }
51 |
52 | section > p.info {
53 | margin-bottom: 16px;
54 | font-weight: 400;
55 | color: rgba(255, 255, 255, 0.7);
56 | }
57 |
58 | section > p.info > strong {
59 | color: #ffffff;
60 | }
61 |
62 | section > div {
63 | font-size: 0;
64 | }
65 |
66 | section > div > input {
67 | display: inline-block;
68 | margin-bottom: 16px;
69 | border: 2px solid #242424;
70 | border-radius: 4px;
71 | padding: 12px;
72 | width: calc(50% - 4px);
73 | background-color: #242424;
74 | color: #ffffff;
75 | font-size: 13px;
76 | }
77 |
78 | section > div > input:focus {
79 | outline: 0;
80 | border: 2px solid #1c7ed5;
81 | }
82 |
83 | section > div > input::placeholder {
84 | color: rgba(255, 255, 255, 0.4);
85 | }
86 |
87 | section > div > input#width {
88 | margin-right: 8px;
89 | }
90 |
91 | section > p.tip {
92 | font-size: 12px;
93 | font-weight: 400;
94 | color: rgba(255, 255, 255, 0.4);
95 | }
96 |
97 | /* -------------------------------- */
98 | /* footer/actions */
99 | /* -------------------------------- */
100 |
101 | footer {
102 | border-top: 1px solid rgba(255, 255, 255, 0.1);
103 | padding: 16px 24px;
104 | background-color: #242424;
105 | font-size: 0;
106 | text-align: right;
107 | }
108 |
109 | footer > button {
110 | display: inline-block;
111 | height: 40px;
112 | border: 0;
113 | border-radius: 4px;
114 | padding: 0 12px;
115 | color: #ffffff;
116 | font-size: 13px;
117 | line-height: 16px;
118 | font-weight: 600;
119 | }
120 |
121 | footer > button:focus {
122 | outline: 0;
123 | }
124 |
125 | footer > button:focus:after {
126 | content: '';
127 | display: block;
128 | position: absolute;
129 | top: -5px;
130 | left: -5px;
131 | width: calc(100% + 10px);
132 | height: calc(100% + 10px);
133 | border: 2px solid #1c7ed5;
134 | border-radius: 6px;
135 | }
136 |
137 | footer > button#cancel {
138 | margin-right: 8px;
139 | border: 1px solid rgba(255, 255, 255, 0.4);
140 | background-color: transparent;
141 | }
142 |
143 | footer > button#cancel:hover {
144 | background-color: rgba(255, 255, 255, 0.1);
145 | }
146 |
147 | footer > button#submit {
148 | border: 1px solid #1c7ed5;
149 | background-color: #1c7ed5;
150 | }
151 |
152 | footer > button#submit:hover {
153 | background-color: #186bb5;
154 | }
155 |
--------------------------------------------------------------------------------
/resources/webview/webview.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Sketch Resize
7 |
8 |
9 |
10 |
11 |
12 | Resize Element(s)
13 |
14 |
15 |
26 |
27 |
28 | Cancel
29 | Confirm and Resize
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/actions/resize.js:
--------------------------------------------------------------------------------
1 | import sketch from 'sketch';
2 |
3 | // resize logic
4 | const resize = (selection, dimensions) => {
5 | for (let layer of selection.layers) {
6 | const frame = layer.frame;
7 | const finalDimensions = process(dimensions, frame.width, frame.height);
8 | frame.width = finalDimensions.width;
9 | frame.height = finalDimensions.height;
10 | }
11 |
12 | sketch.UI.message(`Resized ${selection.length} layer(s)`);
13 | };
14 |
15 | // process dimensions, and replace %w, and %h
16 | const process = (dimensions, originalWidth, originalHeight) => ({
17 | width: eval(sanitize(dimensions.width, originalWidth, originalHeight)),
18 | height: eval(sanitize(dimensions.height, originalWidth, originalHeight)),
19 | });
20 |
21 | const sanitize = (string, w, h) => string.replace(/%w/gi, w).replace(/%h/gi, h);
22 |
23 | export default resize;
24 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | import BrowserWindow from 'sketch-module-web-view';
2 | import sketch from 'sketch';
3 | import resize from './actions/resize';
4 |
5 | // main function
6 | const main = () => {
7 | const document = sketch.getSelectedDocument();
8 | const selection = document.selectedLayers;
9 |
10 | // return error message if selection is empty
11 | if (selection.isEmpty) {
12 | sketch.UI.message('No layer(s) selected!');
13 | return;
14 | }
15 |
16 | // define the webview, its options, and its content
17 | const options = {
18 | identifier: 'sketch.resize',
19 | width: 480,
20 | height: 316,
21 | center: true,
22 | show: false,
23 | backgroundColor: '#181818',
24 | titleBarStyle: 'hiddenInset',
25 | alwaysOnTop: true,
26 | resizable: false,
27 | fullscreenable: false,
28 | maximizable: false,
29 | minimizable: false,
30 | };
31 |
32 | let webview = new BrowserWindow(options);
33 | const webcontent = webview.webContents;
34 |
35 | // when loaded, show the webview
36 | webview.once('ready-to-show', () => webview.show());
37 |
38 | // cancel the overall process
39 | webcontent.on('cancel', () => close(webview));
40 |
41 | // process input, and trigger resize
42 | webcontent.on('submit', dimensions => {
43 | resize(selection, dimensions);
44 | close(webview);
45 | });
46 |
47 | // show the webview
48 | webview.loadURL(require('../resources/webview/webview.html'));
49 | };
50 |
51 | // close the window
52 | const close = webview => {
53 | webview.close();
54 | webview = null;
55 | };
56 |
57 | export default main;
58 |
--------------------------------------------------------------------------------
/src/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Luca Orio",
3 | "name": "Resize",
4 | "compatibleVersion": 3,
5 | "bundleVersion": 1,
6 | "identifier": "com.sketch.resize",
7 | "icon": "sketch-icon.png",
8 | "appcast": "https://raw.githubusercontent.com/lucaorio/sketch-resize/master/appcast.xml",
9 | "commands": [
10 | {
11 | "name": "Resize Elements",
12 | "identifier": "main",
13 | "script": "./main.js",
14 | "description": "Resize (not scale) multiple layers at once via shortcut",
15 | "icon": "resize.png",
16 | "shortcut": "ctrl cmd k"
17 | }
18 | ],
19 | "menu": {
20 | "title": "Resize",
21 | "items": ["main"]
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/webpack.skpm.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function(config) {
2 | config.module.rules.push({
3 | test: /\.(html)$/,
4 | use: [
5 | {
6 | loader: '@skpm/extract-loader',
7 | },
8 | {
9 | loader: 'html-loader',
10 | options: {
11 | attrs: ['img:src', 'link:href'],
12 | interpolate: true,
13 | },
14 | },
15 | ],
16 | });
17 | config.module.rules.push({
18 | test: /\.(css)$/,
19 | use: [
20 | {
21 | loader: '@skpm/extract-loader',
22 | },
23 | {
24 | loader: 'css-loader',
25 | },
26 | ],
27 | });
28 | };
29 |
--------------------------------------------------------------------------------