├── .gitignore ├── README.md ├── bin ├── csxs.js └── ucf.jar ├── docs └── configuration.md ├── hosts.json ├── package.json ├── project ├── .actionScriptProperties ├── .gitignore ├── HISTORY.md ├── README.md ├── assets │ ├── icon-dark-disabled.png │ ├── icon-dark-hover.png │ ├── icon-dark.png │ ├── icon-disabled.png │ ├── icon-hover.png │ ├── icon-mxi.png │ ├── icon.png │ └── icon@2x.psd ├── changes │ └── 0.0.1.txt ├── csxs.json └── src │ ├── ID.jsx │ ├── ID.mxi │ ├── ID.mxml │ ├── manifest.cc.xml │ ├── manifest.cs5.xml │ ├── manifest.cs6.xml │ └── update.xml ├── schema.json └── src ├── build.js ├── csxs.js ├── lib ├── git.js ├── hosts.js ├── project.js ├── prompt.js └── uuid.js ├── targets ├── certificate.js ├── changelogs.js ├── compile.js ├── configure.js ├── create.js ├── debug.js ├── package.js └── publish.js └── tasks ├── amxmlc.js ├── config.js ├── fdb.js ├── fs.js ├── git.js └── ucf.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | What is this? A command line tool written in [node.js](http://nodejs.org/) for creating, compiling, packaging, 4 | debugging, and deploying extensions for Adobe® Creative Suite®. It's easy as to use and as it is powerful. 5 | 6 | It is designed to solve workflow problems and constraints that come from using [Flash Builder](http://www.adobe.com/devnet/flash-builder.html). 7 | As an added bonus, projects created with this tool contain boilerplate to resolve strange platform bugs we've encountered. 8 | 9 | We used to it to build our [Creative Market Photoshop Extension](https://creativemarket.com/photoshop-extension). 10 | 11 | ### Advantages 12 | 13 | * Use any editor you want! 14 | * All project settings live in a single JSON file ([documentation](docs/configuration.md)). 15 | * Automated signing, deploys to S3, changelog management, git tagging, etc. 16 | * Open source! 17 | 18 | ### Requirements 19 | 20 | * [Build and Install Node.js](https://github.com/joyent/node/wiki/Installation) 21 | * Install [NPM](http://npmjs.org/): `curl http://npmjs.org/install.sh | sh` 22 | * Install [csxs](https://github.com/creativemarket/csxs): `npm install -g csxs` 23 | 24 | ## Getting Started 25 | 26 | To create a new project, make an empty folder and use the "create" target to set up 27 | an empty project that's ready to go for development. To compile a debug version and add 28 | it to Photoshop, use the "debug" target. 29 | 30 | ```sh 31 | # create a folder for a project 32 | $ mkdir my-extension 33 | $ cd my-extension 34 | 35 | # create the project & start it 36 | $ csxs create 37 | $ csxs debug --launch 38 | ``` 39 | 40 | More information about building and publishing the extension will be 41 | listed in the ["README.md"](project/README.md) created with the project. 42 | 43 | ## Project Structure 44 | 45 | ### Configuration 46 | 47 | All project settings live in **"csxs.json"** ([guide](docs/configuration.md)). The settings in this file are synthesized to various 48 | XML files needed by the Flex Compiler and Signing Tool during the build process. 49 | 50 | ### Folders 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 |
assets/Icons for the panel and Adobe Extension Manager.
changes/A directory containing individual changelog files, by version.
src/Extension source code.
README.mdGetting started guide.
HISTORY.mdAn aggregated list of changes generated by the "changelogs" target.
csxs.jsonAll project settings (in lieu of *.xml files).
78 | 79 | ## Advanced Topics 80 | 81 | ### Conditional Compilation 82 | 83 | The following [conditional compilation](http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_21.html) variables are automatically provided: 84 | 85 | * `CONFIG::version` (string) 86 | * `CONFIG::debug` (boolean) 87 | * `CONFIG::release` (boolean) 88 | 89 | #### Adding Custom Variables 90 | 91 | Custom variables can be set by adding them to the "properties" object in "csxs.json". The values *must* be scalar. 92 | The one exception to this is if you want different values for debug builds and release builds. In this case, provide an 93 | object with two properties: "debug" and "release". 94 | 95 | ```json 96 | { 97 | "properties": { 98 | "url": { 99 | "debug": "http://sandbox.domain.com", 100 | "release": "http://domain.com" 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | ### Editing XML and MXI Files 107 | 108 | XML and MXI files in the project are populated by the properties in ["csxs.json"](docs/configuration.md) at build time. 109 | For complicated extensions, it might be necessary to make changes in these files. Any of the files in 110 | the "src/" folder can be safely edited. Template variables should follow [handlebars syntax](http://handlebarsjs.com/). 111 | 112 | ### Automated S3 Deployment 113 | 114 | Automated deployment of releases is done with the "publish" target. The build tool will compile a release build, 115 | package it as a *.zxp installer, and place it on [S3](http://aws.amazon.com/s3/) (along with a history of changes). 116 | All that's needed is an S3 account. See the [documentation on the `"s3"` property](docs/configuration.md#s3) to see how to 117 | add S3 configuration. 118 | 119 | ```sh 120 | $ csxs publish 121 | ``` 122 | 123 | #### Deployed Files & Folders 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 |
changes/Contains changelogs by version and a "master.txt" file (an aggregated list).
update.xmlUpdate info read by Adobe Extension Manager.
update.jsonUpdate info in JSON format.
MyExtension.zxpLatest version.
MyExtension.0.0.1.zxpArchival version.
147 | 148 | ### Automated Git Tagging 149 | 150 | When running "publish", HEAD will be tagged with the version being deployed for reference. It is the equivalent of running: 151 | 152 | ```sh 153 | $ git tag vX.X.X 154 | $ git push origin --tags 155 | ``` 156 | 157 | ### Multiple Configurations 158 | 159 | In the rare case that a project needs multiple configurations (i.e. multiple "csxs.json" files), you can specify the configuration file to use from the command line with the `--config` option. 160 | 161 | ```sh 162 | $ csxs target --config=csxs_free.json 163 | $ csxs target --config=csxs_paid.json 164 | ``` 165 | 166 | If this option is not provided, "csxs.json" will be read by default. 167 | 168 | ## Footnotes 169 | 170 | * 100% compatible with Mac OSX. Windows support is partial / spotty right now. 171 | * If your project needs host adapters, they have to be extracted manually from Extension Builder ([Adobe Forums thread](http://forums.adobe.com/message/5245782)). 172 | 173 | ## License 174 | 175 | Copyright © 2013 Creative Market 176 | 177 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: http://www.apache.org/licenses/LICENSE-2.0 178 | 179 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 180 | 181 | #### Copyrights & Trademarks 182 | 183 | The included ["bin/ucf.jar"](bin/ucf.jar) binary is copyright Adobe Systems Incorporated. The license can be found [here](http://www.adobe.com/devnet/creativesuite/sdk/eula_cs6-signing-toolkit.html). "Creative Suite" is a registered trademark of Adobe Systems Incorporated. 184 | -------------------------------------------------------------------------------- /bin/csxs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Command Line Interface 5 | * 6 | * Copyright (c) 2013 Creative Market 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 9 | * file except in compliance with the License. You may obtain a copy of the License at: 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software distributed under 13 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 14 | * ANY KIND, either express or implied. See the License for the specific language 15 | * governing permissions and limitations under the License. 16 | * 17 | * @author Brian Reavis 18 | */ 19 | 20 | var path = require('path'); 21 | var fs = require('fs'); 22 | var roto = require('roto'); 23 | var colorize = roto.colorize; 24 | var optimist = require('optimist'); 25 | 26 | optimist.usage('Usage: $0 [target] [options]') 27 | 28 | var i, n, key; 29 | 30 | // load build targets 31 | // ------------------------------------------------------------------------------------ 32 | 33 | require('../src/build.js')(roto); 34 | 35 | // extract global options & target 36 | // ------------------------------------------------------------------------------------ 37 | 38 | var argv = optimist.argv; 39 | var target = argv._.length ? argv._[0] : null; 40 | var blacklist = ['_', '$0']; 41 | var options = {}; 42 | for (key in argv) { 43 | if (argv.hasOwnProperty(key) && blacklist.indexOf(key) === -1) { 44 | options[key] = argv[key]; 45 | } 46 | } 47 | for (i = 1; i < argv._.length; i++) { 48 | options[argv._[i]] = true; 49 | } 50 | 51 | // display help 52 | // ------------------------------------------------------------------------------------ 53 | 54 | if (options['help']) { 55 | var print_target = function(name, options) { 56 | if (options && options.hidden) return; 57 | var selected = name === roto.defaultTarget; 58 | var bullet = selected ? '■' : '□'; 59 | process.stdout.write(colorize(' ' + bullet, 'gray') + ' ' + name); 60 | if (selected) { 61 | process.stdout.write(colorize(' (default)', 'blue')); 62 | } 63 | if (options && options.description) { 64 | process.stdout.write(colorize(': ' + options.description + '', 'gray')); 65 | } 66 | process.stdout.write('\n'); 67 | }; 68 | 69 | process.stdout.write('\n' + optimist.help()); 70 | 71 | // defined targets 72 | process.stdout.write(colorize('Available Targets:\n', 'white')); 73 | for (var key in roto._project.targets) { 74 | if (roto._project.targets.hasOwnProperty(key)) { 75 | print_target(key, roto._project.targets[key].options); 76 | } 77 | } 78 | 79 | process.stdout.write('\nFor more information, find the documentation at:\n'); 80 | process.stdout.write(colorize('http://github.com/creativemarket/csxs', 'underline') + '\n\n'); 81 | process.exit(0); 82 | } 83 | 84 | // execute build 85 | // ------------------------------------------------------------------------------------ 86 | 87 | if (target === 'compile') { 88 | process.stderr.write(colorize('ERROR: ', 'red') + ' The "compile" target cannot be run explicitly.\n'); 89 | process.exit(1); 90 | } else { 91 | roto.run(target, options, function(success) { 92 | process.exit(success !== false ? 0 : 1); 93 | }); 94 | } -------------------------------------------------------------------------------- /bin/ucf.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/bin/ucf.jar -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ### csxs.json 4 | 5 | All project settings live in ["csxs.json"](../project/csxs.json). The settings are synthesized to the following files at build-time: 6 | 7 | - [".actionScriptProperties"](../project/.actionScriptProperties) 8 | - ["src/manifest.cs5.xml"](../project/src/manifest.cs5.xml) 9 | - ["src/manifest.cs6.xml"](../project/src/manifest.cs6.xml) 10 | - ["src/update.xml"](../project/src/update.xml) 11 | - ["src/ProjectID.mxi"](../project/src/ID.mxi) 12 | 13 | ## Properties 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 87 | 88 | 89 | 90 | 115 | 116 | 117 | 118 | 135 | 136 | 137 | 138 | 155 | 156 | 157 | 158 | 188 | 189 |
PropertyDescription
"uuid"A random globally-unique id to the project. Used by Flash Builder.
"version"The current version number of the extension. This should be in the format of "0.0.0".
"id"Unique identifier to represent the extension.
"name"Extension name. Used in Extension Manager and is shown in the panel header.
"author"Your name or your company name.
"description"A description of the extension (shown in Extension Manager).
"filename"The name of the file (excluding the extension) to create when packaging.
"license-agreement"Legal jargon to display when the user installs the extension.
"ui-access"A description of how to access the extension.
"flex-version"Flex version to compile against. This can be overridden by the --flex-version flag.
"compiler-arguments"An array of additional arguments to provide the Flex compiler.
"properties"An object containing custom conditional compilation variables. Note: values must be scalar.
"certificate" 71 | Code signing certificate settings. For more information on code signing, see "Packaging and Signing an Extension for Distribution". 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
PropertyDescription
"location"Path to the *.p12 code signing certificate (relative to the project root).
"password"Certificate password.
86 |
"s3" 91 | Amazon S3 configuration for automated deploys via the "publish" target. 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 |
PropertyDescription
"bucket"S3 bucket name.
"key"S3 account key.
"secret"S3 account secret.
"path"The path to the folder within the bucket to place the files.
114 |
"icons" 119 | An object containing paths to extension icon assets. 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 |
PropertyDescription
"light"An object containing "normal", "hover", and "disabled" image paths.
"dark"An object containing "normal", "hover", and "disabled" image paths.
134 |
"flex" 139 | An object containing arrays of libraries to link by Flex version. 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 |
PropertyDescription
"4.5.0"An array of paths to libraries used when compiling with the Flex 4 compiler.
"3.4.0"An array of paths to libraries used when compiling with the Flex 3 compiler.
154 |
"builds" 159 | An array containing the configuration for the individual builds that make up the *.zxp package. 160 | Each item in the array extends the base project configuration and must have the following properties defined: 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 |
PropertyDescription
"manifest"The filename of the XML manifest in the "src" folder to compile from.
"flex-version"Flex compiler version.
"cs-products"An array containing the Creative Suite products to target. Possible items: "photoshop", "illustrator", "indesign", "flash", "fireworks", "dreamweaver", "premiere", "prelude".
"cs-versions"An array containing all Creative Suite versions to target. Possible items: "6.0", "5.5", "5.0".
"cc-products"An object mapping Creative Cloud products to target. Each key ("photoshop", "illustrator", "indesign", "flash", "fireworks", "dreamweaver", "premiere", "prelude") should point to an array of version ranges (objects containing "min" and "max" version properties).
187 |
-------------------------------------------------------------------------------- /hosts.json: -------------------------------------------------------------------------------- 1 | { 2 | "CC": { 3 | "photoshop": { 4 | "familyname": "Photoshop", 5 | "name": "Photoshop", 6 | "ids": ["PHXS", "PHSP"], 7 | "version": {"min": "14.0", "max": "14.9"} 8 | }, 9 | "illustrator": { 10 | "familyname": "Illustrator", 11 | "name": "Illustrator", 12 | "ids": ["ILST"], 13 | "version": {"min": "17.0", "max": "17.9"} 14 | }, 15 | "indesign": { 16 | "familyname": "InDesign", 17 | "name": "InDesign", 18 | "ids": ["IDSN"], 19 | "version": {"min": "9.0", "max": "9.9"} 20 | }, 21 | "flash": { 22 | "familyname": "Flash", 23 | "name": "Flash", 24 | "ids": ["FLPR"], 25 | "version": {"min": "13.0", "max": "13.9"} 26 | }, 27 | "dreamweaver": { 28 | "familyname": "Dreamweaver", 29 | "name": "Dreamweaver", 30 | "ids": ["DRWV"], 31 | "version": {"min": "13.0", "max": "13.9"} 32 | }, 33 | "premiere": { 34 | "familyname": "Premiere", 35 | "name": "Premiere Pro", 36 | "ids": ["PPRO"], 37 | "version": {"min": "7.0", "max": "7.9"} 38 | }, 39 | "prelude": { 40 | "familyname": "Prelude", 41 | "name": "Prelude", 42 | "ids": ["PRLD"], 43 | "version": {"min": "2.0", "max": "2.9"} 44 | } 45 | }, 46 | "6.0": { 47 | "photoshop": { 48 | "familyname": "Photoshop", 49 | "name": "Photoshop", 50 | "ids": ["PHXS", "PHSP"], 51 | "version": {"min": "13.0", "max": "13.9"} 52 | }, 53 | "illustrator": { 54 | "familyname": "Illustrator", 55 | "name": "Illustrator", 56 | "ids": ["ILST"], 57 | "version": {"min": "16.0", "max": "16.9"} 58 | }, 59 | "indesign": { 60 | "familyname": "InDesign", 61 | "name": "InDesign", 62 | "ids": ["IDSN"], 63 | "version": {"min": "8.0", "max": "8.9"} 64 | }, 65 | "flash": { 66 | "familyname": "Flash", 67 | "name": "Flash", 68 | "ids": ["FLPR"], 69 | "version": {"min": "12.0", "max": "12.9"} 70 | }, 71 | "fireworks": { 72 | "familyname": "Fireworks", 73 | "name": "Fireworks", 74 | "ids": ["FWKS"], 75 | "version": {"min": "12.0", "max": "12.9"} 76 | }, 77 | "dreamweaver": { 78 | "familyname": "Dreamweaver", 79 | "name": "Dreamweaver", 80 | "ids": ["DRWV"], 81 | "version": {"min": "12.0", "max": "12.9"} 82 | }, 83 | "premiere": { 84 | "familyname": "Premiere", 85 | "name": "Premiere Pro", 86 | "ids": ["PPRO"], 87 | "version": {"min": "6.0", "max": "6.9"} 88 | }, 89 | "prelude": { 90 | "familyname": "Prelude", 91 | "name": "Prelude", 92 | "ids": ["PRLD"], 93 | "version": {"min": "1.0", "max": "1.9"} 94 | } 95 | }, 96 | "5.5": { 97 | "photoshop": { 98 | "familyname": "Photoshop", 99 | "name": "Photoshop", 100 | "ids": ["PHXS", "PHSP"], 101 | "version": {"min": "12.1", "max": "12.9"} 102 | }, 103 | "illustrator": { 104 | "familyname": "Illustrator", 105 | "name": "Illustrator", 106 | "ids": ["ILST"], 107 | "version": {"min": "15.1", "max": "15.9"} 108 | }, 109 | "indesign": { 110 | "familyname": "InDesign", 111 | "name": "InDesign", 112 | "ids": ["IDSN"], 113 | "version": {"min": "7.5", "max": "7.9"} 114 | }, 115 | "flash": { 116 | "familyname": "Flash", 117 | "name": "Flash", 118 | "ids": ["FLPR"], 119 | "version": {"min": "11.5", "max": "11.9"} 120 | }, 121 | "fireworks": { 122 | "familyname": "Fireworks", 123 | "name": "Fireworks", 124 | "ids": ["FWKS"], 125 | "version": {"min": "11.1", "max": "11.9"} 126 | }, 127 | "dreamweaver": { 128 | "familyname": "Dreamweaver", 129 | "name": "Dreamweaver", 130 | "ids": ["DRWV"], 131 | "version": {"min": "11.5", "max": "11.9"} 132 | }, 133 | "premiere": { 134 | "familyname": "Premiere", 135 | "name": "Premiere Pro", 136 | "ids": ["PPRO"], 137 | "version": {"min": "5.5", "max": "5.9"} 138 | } 139 | }, 140 | "5.0": { 141 | "photoshop": { 142 | "familyname": "Photoshop", 143 | "name": "Photoshop", 144 | "ids": ["PHXS", "PHSP"], 145 | "version": {"min": "12.0", "max": "12.0"} 146 | }, 147 | "illustrator": { 148 | "familyname": "Illustrator", 149 | "name": "Illustrator", 150 | "ids": ["ILST"], 151 | "version": {"min": "15.0", "max": "15.0"} 152 | }, 153 | "indesign": { 154 | "familyname": "InDesign", 155 | "name": "InDesign", 156 | "ids": ["IDSN"], 157 | "version": {"min": "7.0", "max": "7.4"} 158 | }, 159 | "flash": { 160 | "familyname": "Flash", 161 | "name": "Flash", 162 | "ids": ["FLPR"], 163 | "version": {"min": "11.0", "max": "11.4"} 164 | }, 165 | "fireworks": { 166 | "familyname": "Fireworks", 167 | "name": "Fireworks", 168 | "ids": ["FWKS"], 169 | "version": {"min": "11.0", "max": "11.0"} 170 | }, 171 | "dreamweaver": { 172 | "familyname": "Dreamweaver", 173 | "name": "Dreamweaver", 174 | "ids": ["DRWV"], 175 | "version": {"min": "11.0", "max": "11.4"} 176 | }, 177 | "premiere": { 178 | "familyname": "Premiere", 179 | "name": "Premiere Pro", 180 | "ids": ["PPRO"], 181 | "version": {"min": "5.0", "max": "5.4"} 182 | } 183 | } 184 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "csxs", 3 | "version": "0.2.0", 4 | "description": "A build tool for Adobe® Creative Suite® and Creative Cloud® extensions. Create, compile, debug, package, and deploy to S3 with ease!", 5 | "keywords": ["adobe","creative suite","creative cloud","extension","plugin","csxs","build","zxp","photoshop","illustrator","indesign","cs"], 6 | "homepage": "https://github.com/creativemarket/csxs", 7 | "author": "Brian Reavis ", 8 | "bugs": "https://github.com/creativemarket/csxs/issues", 9 | "license": { 10 | "name": "Apache License, Version 2.0", 11 | "url": "http://www.apache.org/licenses/LICENSE-2.0.html" 12 | }, 13 | "preferGlobal": true, 14 | "bin": {"csxs": "./bin/csxs.js"}, 15 | "main": "./lib/csxs.js", 16 | "repository": { 17 | "type": "git", 18 | "url": "git://github.com/creativemarket/csxs.git" 19 | }, 20 | "dependencies": { 21 | "async": "0.2.X", 22 | "roto": "0.3.X", 23 | "lodash": "1.1.X", 24 | "optimist": "0.3.X", 25 | "jsonschema": "git://github.com/brianreavis/jsonschema.git", 26 | "jsmin": "1.0.X" 27 | }, 28 | "engines": {"node": ">= 0.8"}, 29 | "os": ["win32","darwin"] 30 | } -------------------------------------------------------------------------------- /project/.actionScriptProperties: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{{libraries}}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /project/.gitignore: -------------------------------------------------------------------------------- 1 | /temp 2 | /package 3 | /build/* 4 | /.certificate-self.p12 5 | /*.jsx 6 | /*.mxi 7 | .DS_Store 8 | .staged-extension 9 | Thumbs.db 10 | bin-release 11 | bin-debug 12 | .mxi 13 | *.swp 14 | *.zxp 15 | *.sublime-workspace -------------------------------------------------------------------------------- /project/HISTORY.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/HISTORY.md -------------------------------------------------------------------------------- /project/README.md: -------------------------------------------------------------------------------- 1 | # {{name}} 2 | 3 | ### Requirements 4 | 5 | With the [CSXS](https://github.com/creativemarket/csxs) automated build system, [Flash Builder](http://www.adobe.com/products/flash-builder.html) 6 | and the [CS Extension Builder Plugin](http://www.adobe.com/devnet/creativesuite/cs-extension-builder.html) 7 | are not needed to compile, test, or package the extension. This means you can use Sublime Text or any other 8 | editor for development. 9 | 10 | * Download the [Creative Suite SDK](http://www.adobe.com/devnet/creativesuite.html) 11 | * Set the SDK path: `export CSSDK=[location]` 12 | * [Build and Install Node.js](https://github.com/joyent/node/wiki/Installation) 13 | * Install [NPM](http://npmjs.org/): `curl http://npmjs.org/install.sh | sh` 14 | * Install [csxs](https://github.com/creativemarket/csxs): `npm install -g csxs` 15 | 16 | ## Development 17 | 18 | ```sh 19 | # compiles, installs, and puts photoshop into debug mode 20 | $ csxs debug --cs-version=6 --cs-product=photoshop 21 | ``` 22 | 23 | ### Available Options 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
--helpDisplays all available build targets.
--launchLaunches a new instance of the selected Creative Suite application.
--cs-versionCreative Suite version (e.g. "5", "5.5", "6").
--cs-productCreative Suite application (e.g. "photoshop", "illustrator", etc).
--fdbUse Flex Debugger instead of live display of "flashlog.txt" contents.
--no-compileDisables the compilation step.
51 | 52 | ## Packaging 53 | 54 | To build a *.zxp installer without publishing the extension, run: 55 | 56 | ```sh 57 | $ csxs package 58 | ``` 59 | 60 | ## Public Releases 61 | 62 | First update ["csxs.json"](https://github.com/creativemarket/csxs/blob/master/docs/configuration.md) 63 | with a new version number. Next, create a changelog file in ["changes/"](changes/) that outlines 64 | what has changed since the previous version (this description is user-facing, so don't be too 65 | technical). When that's all set, run `csxs changelogs` to update aggregated changelogs, commit 66 | your changes, and run: 67 | 68 | ```sh 69 | # compiles, packages, and deploys to S3: 70 | $ csxs publish 71 | ``` 72 | 73 | ## Footnotes 74 | 75 | Though not required, Flash Builder can be used for extension development. 76 | 77 | * http://www.adobe.com/products/flash-builder.html 78 | * http://www.adobe.com/devnet/creativesuite/cs-extension-builder.html 79 | 80 | Before starting Flash Builder, run `csxs configure` to generate necessary project files. -------------------------------------------------------------------------------- /project/assets/icon-dark-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon-dark-disabled.png -------------------------------------------------------------------------------- /project/assets/icon-dark-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon-dark-hover.png -------------------------------------------------------------------------------- /project/assets/icon-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon-dark.png -------------------------------------------------------------------------------- /project/assets/icon-disabled.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon-disabled.png -------------------------------------------------------------------------------- /project/assets/icon-hover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon-hover.png -------------------------------------------------------------------------------- /project/assets/icon-mxi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon-mxi.png -------------------------------------------------------------------------------- /project/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon.png -------------------------------------------------------------------------------- /project/assets/icon@2x.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/creativemarket/csxs/a8a1ac9a4cd03d8bb8dace74345b5b030d05ecc7/project/assets/icon@2x.psd -------------------------------------------------------------------------------- /project/changes/0.0.1.txt: -------------------------------------------------------------------------------- 1 | - Initial build. -------------------------------------------------------------------------------- /project/csxs.json: -------------------------------------------------------------------------------- 1 | /** 2 | * "{{name}}" Configuration 3 | * 4 | * Copyright (C) {{year}} {{author}} 5 | * 6 | * These settings are synthesized to various XML and MXI files when the 7 | * extension is compiled / packaged. For documention on all properties, see: 8 | * 9 | * https://github.com/creativemarket/csxs/blob/master/docs/configuration.md 10 | */ 11 | 12 | { 13 | // Extension version number (format: X.X.X) 14 | "version": "0.0.1", 15 | 16 | // Unique identifier for the extension (used by Creative Suite and Extension Manager) 17 | "id": "{{id}}", 18 | 19 | // Extension name to display in the panel's header and when installing the extension 20 | "name": "{{name}}", 21 | 22 | // Your name or your company's name 23 | "author": "{{author}}", 24 | 25 | // Globally unique identifier (only used by Flash Builder) 26 | "uuid": "{{uuid}}", 27 | 28 | // Description of the extension (HTML) 29 | "description": "", 30 | 31 | // Description of how to access the extension (HTML) 32 | "ui-access": "You can run this extension by choosing
Window > Extensions > {{name}}.", 33 | 34 | // License agreement shown when installing the extension (HTML) 35 | "license-agreement": "", 36 | 37 | // Icon to show when the panel is collapsed. Each icon should be a 23x23px PNG 38 | "icons": { 39 | "light": { 40 | "normal" : "./assets/icon.png", 41 | "hover" : "./assets/icon-hover.png", 42 | "disabled" : "./assets/icon-disabled.png" 43 | }, 44 | "dark": { 45 | "normal" : "./assets/icon-dark.png", 46 | "hover" : "./assets/icon-dark-hover.png", 47 | "disabled" : "./assets/icon-dark-disabled.png" 48 | } 49 | }, 50 | 51 | // Panel dimensions (in pixels) 52 | "size": { 53 | "normal" : {"width": 324, "height": 400}, 54 | "min" : {"width": 324, "height": 300}, 55 | "max" : {"width": 800, "height": 2400} 56 | }, 57 | 58 | // Custom conditional compilation variables to provide at compile time. 59 | // See http://livedocs.adobe.com/flex/3/html/help.html?content=compilers_21.html 60 | // for more information about how conditional compilation can be used. 61 | "properties": {}, 62 | 63 | // Custom compiler arguments 64 | "compiler-arguments": [], 65 | 66 | // Flex compiler version (must be a part of the Creative Suite SDK) 67 | "flex-version": "3.4.0", 68 | 69 | // A list of all libraries to link at compile time (by Flex version) 70 | "flex": { 71 | "4.5.0": [ 72 | "${CSSDK}/libs/CSXSLibrary-3.0-sdk-4.5-public.swc", 73 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/core.swc", 74 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/framework.swc", 75 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/rpc.swc", 76 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/air/aircore.swc", 77 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/air/airframework.swc", 78 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/air/servicemonitor.swc", 79 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/air/applicationupdater.swc", 80 | "${CSSDK}/CS Flex SDK 4.5.0/frameworks/libs/air/applicationupdater_ui.swc", 81 | "${CSSDK}/libs/cslibs/2.0/4.5/release/apedelta.swc" 82 | ], 83 | "3.4.0": [ 84 | "${CSSDK}/libs/CSXSLibrary-2.0-sdk-3.4-public.swc", 85 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/flex.swc", 86 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/framework.swc", 87 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/rpc.swc", 88 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/utilities.swc", 89 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/air/aircore.swc", 90 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/air/airglobal.swc", 91 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/air/airframework.swc", 92 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/air/servicemonitor.swc", 93 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/air/applicationupdater.swc", 94 | "${CSSDK}/CS Flex SDK 3.4.0/frameworks/libs/air/applicationupdater_ui.swc", 95 | "${CSSDK}/libs/cslibs/1.0/3.4/release/apedelta.swc" 96 | ] 97 | }, 98 | 99 | // The "package" target prepares individualized builds and bundles 100 | // them as a single *.zxp installer. This is useful for custom 101 | // configuration by product. Each object in this list extends the 102 | // main project configuration. 103 | "builds": [ 104 | { 105 | "manifest": "manifest.cc.xml", 106 | "flex-version": "3.4.0", 107 | "cc-products": {{cc-products}} 108 | }, 109 | { 110 | "manifest": "manifest.cs6.xml", 111 | "flex-version": "3.4.0", 112 | "cs-products": {{cs-products}}, 113 | "cs-versions": ["6.0"] 114 | }, 115 | { 116 | "manifest": "manifest.cs5.xml", 117 | "flex-version": "3.4.0", 118 | "cs-products": {{cs-products}}, 119 | "cs-versions": ["5.0", "5.5"] 120 | } 121 | ] 122 | } -------------------------------------------------------------------------------- /project/src/ID.jsx: -------------------------------------------------------------------------------- 1 | /**! Copyright (c) {{author}} - {{year}} */ -------------------------------------------------------------------------------- /project/src/ID.mxi: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{#if update}}{{/if}} 4 | 5 | 6 | 7 | 8 | 9 | {{{list-products}}} 10 | 11 | 12 | {{{list-files}}} 13 | 14 | 15 | -------------------------------------------------------------------------------- /project/src/ID.mxml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /project/src/manifest.cc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{{list-hosts}}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ./{{basename}}.swf 23 | ./{{basename}}.jsx 24 | 25 | 26 | true 27 | 28 | 29 | Panel 30 | {{name}} 31 | 32 | 33 | {{size.normal.height}} 34 | {{size.normal.width}} 35 | 36 | 37 | {{size.max.height}} 38 | {{size.max.width}} 39 | 40 | 41 | {{size.min.height}} 42 | {{size.min.width}} 43 | 44 | 45 | 46 | {{icons.light.normal}} 47 | {{icons.light.hover}} 48 | {{icons.light.disabled}} 49 | {{icons.dark.normal}} 50 | {{icons.dark.hover}} 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /project/src/manifest.cs5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{{list-hosts}}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ./{{basename}}.swf 23 | ./{{basename}}.jsx 24 | 25 | 26 | true 27 | 28 | 29 | Panel 30 | {{name}} 31 | 32 | 33 | {{size.normal.height}} 34 | {{size.normal.width}} 35 | 36 | 37 | {{size.max.height}} 38 | {{size.max.width}} 39 | 40 | 41 | {{size.min.height}} 42 | {{size.min.width}} 43 | 44 | 45 | 46 | {{icons.light.normal}} 47 | {{icons.light.hover}} 48 | {{icons.light.disabled}} 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /project/src/manifest.cs6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | {{{list-hosts}}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | ./{{basename}}.swf 23 | ./{{basename}}.jsx 24 | 25 | 26 | true 27 | 28 | 29 | Panel 30 | {{name}} 31 | 32 | 33 | {{size.normal.height}} 34 | {{size.normal.width}} 35 | 36 | 37 | {{size.max.height}} 38 | {{size.max.width}} 39 | 40 | 41 | {{size.min.height}} 42 | {{size.min.width}} 43 | 44 | 45 | 46 | {{icons.light.normal}} 47 | {{icons.light.hover}} 48 | {{icons.light.disabled}} 49 | {{icons.dark.normal}} 50 | {{icons.dark.hover}} 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /project/src/update.xml: -------------------------------------------------------------------------------- 1 | 2 | {{version}} 3 | {{url}} 4 | 5 | -------------------------------------------------------------------------------- /schema.json: -------------------------------------------------------------------------------- 1 | { 2 | "type": "object", 3 | "description": "Schema for 'csxs.json' configuration files.", 4 | "extends": {"$ref": "/definitions/base_properties"}, 5 | "additionalProperties": true, 6 | "properties": { 7 | "id": { 8 | "type": "string", 9 | "required": true 10 | }, 11 | "version": { 12 | "type": "string", 13 | "required": true, 14 | "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" 15 | }, 16 | "name": { 17 | "type": "string", 18 | "required": true 19 | }, 20 | "author": { 21 | "type": "string", 22 | "required": true 23 | }, 24 | "description": { 25 | "type": "string", 26 | "required": false 27 | }, 28 | "ui-access": { 29 | "type": "string", 30 | "required": false 31 | }, 32 | "license-agreement": { 33 | "type": "string", 34 | "required": false 35 | }, 36 | "icons": { 37 | "required": true 38 | }, 39 | "size": { 40 | "required": true 41 | }, 42 | "flex": { 43 | "required": true, 44 | "type": "object" 45 | }, 46 | "builds": { 47 | "type": "array", 48 | "required": true, 49 | "items": { 50 | "type": "object", 51 | "extends": {"$ref": "/definitions/base_properties"}, 52 | "properties": { 53 | "manifest": { 54 | "type": "string", 55 | "required": true 56 | }, 57 | "flex-version": { 58 | "type": "string", 59 | "required": true, 60 | "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$" 61 | }, 62 | "cs-products": { 63 | "type": "array", 64 | "required": false, 65 | "uniqueItems": true, 66 | "items": { 67 | "type": "string" 68 | } 69 | }, 70 | "cs-versions": { 71 | "type": "array", 72 | "required": false, 73 | "uniqueItems": true, 74 | "items": { 75 | "type": "string", 76 | "pattern": "^[0-9]+\\.[0-9]+$" 77 | } 78 | }, 79 | "cc-products": { 80 | "type": "object", 81 | "required": false 82 | } 83 | } 84 | } 85 | } 86 | }, 87 | "definitions": { 88 | "dimensions": { 89 | "type": "object", 90 | "additionalProperties": false, 91 | "properties": { 92 | "width": {"type": "integer", "required": true}, 93 | "height": {"type": "integer", "required": true} 94 | } 95 | }, 96 | "base_properties": { 97 | "type": "object", 98 | "properties": { 99 | "properties": { 100 | "type": "object", 101 | "patternProperties": { 102 | "^.*$": { 103 | "description": "must be a scalar value (or an object containing only \"debug\" and \"release\" properties)", 104 | "oneOf": [ 105 | {"type": "string"}, 106 | {"type": "number"}, 107 | {"type": "boolean"}, 108 | {"type": "null"}, 109 | { 110 | "type": "object", 111 | "properties": { 112 | "debug": { 113 | "required": true, 114 | "oneOf": [ 115 | {"type": "string"}, 116 | {"type": "number"}, 117 | {"type": "boolean"}, 118 | {"type": "null"} 119 | ] 120 | }, 121 | "release": { 122 | "required": true, 123 | "oneOf": [ 124 | {"type": "string"}, 125 | {"type": "number"}, 126 | {"type": "boolean"}, 127 | {"type": "null"} 128 | ] 129 | } 130 | } 131 | } 132 | ] 133 | } 134 | } 135 | }, 136 | "icons": { 137 | "type": "object", 138 | "additionalProperties": false, 139 | "properties": { 140 | "light": { 141 | "type": "object", 142 | "required": true, 143 | "additionalProperties": true, 144 | "properties": { 145 | "normal": {"type": "string", "required": false}, 146 | "hover": {"type": "string", "required": false}, 147 | "disabled": {"type": "string", "required": false} 148 | } 149 | }, 150 | "dark": { 151 | "type": "object", 152 | "required": true, 153 | "additionalProperties": true, 154 | "properties": { 155 | "normal": {"type": "string", "required": false}, 156 | "hover": {"type": "string", "required": false}, 157 | "disabled": {"type": "string", "required": false} 158 | } 159 | } 160 | } 161 | }, 162 | "size": { 163 | "type": "object", 164 | "properties": { 165 | "normal": { 166 | "type": "object", 167 | "additionalProperties": false, 168 | "properties": { 169 | "width": {"type": "integer", "required": true}, 170 | "height": {"type": "integer", "required": true} 171 | } 172 | }, 173 | "min": { 174 | "type": "object", 175 | "additionalProperties": false, 176 | "properties": { 177 | "width": {"type": "integer", "required": true}, 178 | "height": {"type": "integer", "required": true} 179 | } 180 | }, 181 | "max": { 182 | "type": "object", 183 | "additionalProperties": false, 184 | "properties": { 185 | "width": {"type": "integer", "required": true}, 186 | "height": {"type": "integer", "required": true} 187 | } 188 | } 189 | } 190 | }, 191 | "compiler-arguments": { 192 | "type": "array", 193 | "items": {"type": "string"} 194 | } 195 | } 196 | } 197 | } 198 | } -------------------------------------------------------------------------------- /src/build.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | global.IS_WINDOWS = !!process.platform.match(/^win/); 17 | global.IS_MAC = !IS_WINDOWS; 18 | global.config = null; 19 | global.roto = null; 20 | 21 | module.exports = function(roto) { 22 | global.roto = roto; 23 | roto.defaultTarget = null; 24 | roto.options.indent = true; 25 | roto.options.colorize = true; 26 | 27 | require('./tasks/config.js'); 28 | require('./tasks/git.js'); 29 | require('./tasks/fs.js'); 30 | require('./tasks/ucf.js'); 31 | require('./tasks/amxmlc.js'); 32 | require('./tasks/fdb.js'); 33 | 34 | require('./targets/certificate.js'); 35 | require('./targets/changelogs.js'); 36 | require('./targets/create.js'); 37 | require('./targets/compile.js'); 38 | require('./targets/configure.js'); 39 | require('./targets/debug.js'); 40 | require('./targets/package.js'); 41 | require('./targets/publish.js'); 42 | }; -------------------------------------------------------------------------------- /src/csxs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | module.exports = null; -------------------------------------------------------------------------------- /src/lib/git.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var spawn = require('child_process').spawn; 17 | var git = module.exports = {}; 18 | 19 | /** 20 | * Determines the current `git status` of the working 21 | * directory. Provides the callback with an object containing: 22 | * 23 | * - clean (boolean) 24 | * - branch (string) 25 | * 26 | * @param {function} callback 27 | */ 28 | git.status = function(callback) { 29 | var result = null; 30 | 31 | var proc = spawn('git', ['status']); 32 | proc.stdout.on('data', function(data) { 33 | str = data + ''; 34 | result = result || { 35 | clean: false, 36 | branch : null 37 | }; 38 | 39 | // parse branch information 40 | var branch = str.match(/On branch ([^\n]+)/); 41 | result.branch = branch && branch[1].replace(/^\s+|\s+$/, ''); 42 | 43 | // parse working directory status 44 | if (str.indexOf('working directory clean') !== -1) { 45 | result.clean = true; 46 | } 47 | }); 48 | 49 | proc.on('exit', function() { 50 | callback(result); 51 | }); 52 | }; -------------------------------------------------------------------------------- /src/lib/hosts.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var HOSTS = require('../../hosts.json'); 17 | var hosts = module.exports = {}; 18 | 19 | /** 20 | * Returns information about a Creative Suite product. 21 | * 22 | * @param {string} key 23 | * @param {string} version 24 | * @returns {object} 25 | */ 26 | hosts.getProduct = function(key, cs_version) { 27 | key = key.toLowerCase(); 28 | if (!cs_version) cs_version = '6.0'; 29 | else cs_version = parseFloat(cs_version).toFixed(1); 30 | if (!HOSTS.hasOwnProperty(cs_version)) throw new Error('Unknown CS Version "' + cs_version + '"'); 31 | if (!HOSTS[cs_version].hasOwnProperty(key)) throw new Error('Unknown CS Product "' + key + '" (CS' + cs_version + ')'); 32 | return HOSTS[cs_version][key]; 33 | }; 34 | 35 | /** 36 | * Returns the individual product version range 37 | * given a list of Creative Suite versions. 38 | * 39 | * @param {string} key 40 | * @param {array} cs_versions 41 | * @returns {object} 42 | */ 43 | hosts.getVersionRange = function(key, cs_versions) { 44 | var i, n, min, max, host; 45 | 46 | for (i = 0, n = cs_versions.length; i < n; i++) { 47 | host = hosts.getProduct(key, cs_versions[i]); 48 | if (!min || parseFloat(host.version.min) < parseFloat(min)) min = host.version.min; 49 | if (!max || parseFloat(host.version.max) > parseFloat(max)) max = host.version.max; 50 | } 51 | 52 | return {min: min, max: max}; 53 | }; -------------------------------------------------------------------------------- /src/lib/project.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var path = require('path'); 18 | var project = module.exports = {}; 19 | 20 | /** 21 | * Fetches a list of changelog paths, 22 | * sorted by version (ascending) 23 | * 24 | * @returns {array} 25 | */ 26 | project.getChangelogs = function() { 27 | var files = roto.findFiles('changes/*.txt', 'changes/master.txt'); 28 | files.sort(function(a, b) { 29 | a = path.basename(a, '.txt'); 30 | b = path.basename(b, '.txt'); 31 | var part_a, part_b; 32 | var parts_a = a.split('.'); 33 | var parts_b = b.split('.'); 34 | for (var i = 0, n = Math.max(parts_a.length, parts_b.length); i < n; i++) { 35 | part_a = parseInt(parts_a[i]); 36 | part_b = parseInt(parts_b[i]); 37 | if (part_b < part_a) return 1; 38 | if (part_b > part_a) return -1; 39 | } 40 | return 0; 41 | }); 42 | 43 | return files; 44 | }; 45 | 46 | /** 47 | * Returns arguments to use with the AXMLC compiler. 48 | * 49 | * @param {object} config 50 | * @param {object} options 51 | * @param {object} extra_properties 52 | * @returns {array} 53 | */ 54 | project.getCompilerArguments = function(config, options, extra_properties) { 55 | var i, n, key, value; 56 | var properties, custom_args; 57 | var args = []; 58 | 59 | // conditional compiler arguments 60 | properties = _.extend({ 61 | 'debug' : options.profile !== 'release', 62 | 'release' : options.profile === 'release', 63 | 'version' : config.version 64 | }, config.properties, extra_properties); 65 | 66 | // custom flags 67 | custom_args = config['compiler-arguments']; 68 | if (Array.isArray(custom_args)) { 69 | for (i = 0, n = custom_args.length; i < n; i++) { 70 | args.push(custom_args[i]); 71 | } 72 | } 73 | 74 | // user defined constants 75 | for (key in properties) { 76 | value = properties[key]; 77 | if (value && typeof value === 'object') { 78 | value = value[options.profile]; 79 | } 80 | if (properties.hasOwnProperty(key) && ((typeof value !== 'object' && typeof value !== 'array') || properties[key] === null)) { 81 | args.push('-define=CONFIG::' + key + ',' + JSON.stringify(value)); 82 | } 83 | } 84 | 85 | if (parseInt(options.ver_flex, 10) >= 4) { 86 | args.push('-includes=mx.managers.systemClasses.MarshallingSupport'); 87 | } 88 | 89 | return args; 90 | }; -------------------------------------------------------------------------------- /src/lib/prompt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var prompt = module.exports = function(schema, callback) { 17 | var delimiter = ': '; 18 | var args = arguments; 19 | var input = function() { 20 | process.stdout.write('> '); 21 | process.stdin.resume(); 22 | process.stdin.once('data', function(data) { 23 | var value = data.toString().replace(/^[\s"]+|[\s"]+$/g, ''); 24 | var err = null; 25 | 26 | if (schema.required && !value.length) { 27 | err = 'This field is required.'; 28 | } else if (schema.format) { 29 | try { value = schema.format(value); } 30 | catch (e) { err = e.message; } 31 | } else if (schema.pattern && !schema.pattern.test(value)) { 32 | err = schema.message || 'Invalid value.'; 33 | } 34 | 35 | if (err) { 36 | console.error(roto.colorize('ERROR: ', 'red') + err); 37 | return input(); 38 | } 39 | 40 | callback(null, value); 41 | }); 42 | }; 43 | 44 | console.log(roto.colorize(schema.title, 'white')); 45 | console.log(roto.colorize(schema.description, 'gray')); 46 | input(); 47 | }; -------------------------------------------------------------------------------- /src/lib/uuid.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var uuid = module.exports = (function() { 17 | var s4 = function() { 18 | return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1); 19 | }; 20 | return function() { 21 | return [s4(), s4(), '-', s4(), '-', s4(), '-', s4(), '-', s4(), s4(), s4()].join(''); 22 | } 23 | })(); -------------------------------------------------------------------------------- /src/targets/certificate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var fs = require('fs'); 18 | var spawn = require('child_process').spawn; 19 | 20 | 21 | roto.addTarget('certificate', { 22 | description: 'Generates a self-signing certificate.' 23 | }, function(options) { 24 | var subject_ca; 25 | var subject_ia; 26 | 27 | _.extend({ 28 | password: 'password', 29 | output: 'certificate-self.p12' 30 | }, options); 31 | 32 | var openssl = function(args) { 33 | roto.addTask(function(callback) { 34 | if (typeof args === 'function') { 35 | args = args(); 36 | } 37 | console.log(roto.colorize('openssl ' + args.join(' '), 'magenta')); 38 | var openssl = spawn('openssl', args, {stdio: 'inherit'}); 39 | openssl.on('exit', function(code) { 40 | if (code === 0) return callback(); 41 | console.error(roto.colorize('ERROR: ', 'red') + 'An error occurred when generating the code signing certificate.'); 42 | callback(false); 43 | }); 44 | }); 45 | }; 46 | 47 | // check for compatible operating system 48 | roto.addTask(function(callback) { 49 | if (!IS_MAC) { 50 | console.error(roto.colorize('ERROR: ', 'red') + ' Key generation is currently only supported on OSX.'); 51 | return callback(false); 52 | } 53 | console.log('Generating self-signing certificate...'); 54 | callback(); 55 | }); 56 | 57 | // load project configuration to `config` global 58 | roto.addTask('csxs.config_load'); 59 | 60 | // subject info 61 | roto.addTask(function(callback) { 62 | subject_ca = '/CN=' + config.author + ' Code Signing/O=' + config.author + '/C=US'; 63 | subject_ia = '/CN=' + config.author + '/O=' + config.author + '/C=US'; 64 | callback(); 65 | }); 66 | 67 | // openssl genrsa -out ca.key 4096 68 | openssl(['genrsa', '-out', 'ca.key', '4096']); 69 | 70 | // openssl req -new -x509 -days 1826 -key ca.key -out ca.crt 71 | openssl(function() { 72 | return ['req', '-new', '-x509', '-days', '1826', '-key', 'ca.key', '-subj', subject_ca, '-out', 'ca.crt']; 73 | }); 74 | 75 | // openssl genrsa -out ia.key 4096 76 | openssl(['genrsa', '-out', 'ia.key', '4096']); 77 | 78 | // openssl req -new -key ia.key -out ia.csr 79 | openssl(function() { 80 | return ['req', '-new', '-key', 'ia.key', '-subj', subject_ia, '-out', 'ia.csr']; 81 | }); 82 | 83 | // openssl x509 -req -days 730 -in ia.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out ia.crt 84 | openssl(['x509', '-req', '-days', '730', '-in', 'ia.csr', '-CA', 'ca.crt', '-CAkey', 'ca.key', '-set_serial', '01', '-out', 'ia.crt']); 85 | 86 | // openssl pkcs12 -export -out ia.p12 -inkey ia.key -in ia.crt -chain -CAfile ca.crt 87 | openssl(['pkcs12', '-export', '-out', options.output, '-inkey', 'ia.key', '-in', 'ia.crt', '-passout', 'pass:' + options.password, '-chain', '-CAfile', 'ca.crt']); 88 | 89 | // clean up 90 | roto.addTask(function(callback) { 91 | fs.unlinkSync('ca.key'); 92 | fs.unlinkSync('ca.crt'); 93 | fs.unlinkSync('ia.crt'); 94 | fs.unlinkSync('ia.csr'); 95 | fs.unlinkSync('ia.key'); 96 | console.log(options.output); 97 | console.log(roto.colorize('Certificate generated.', 'green')); 98 | callback(); 99 | }); 100 | 101 | }); -------------------------------------------------------------------------------- /src/targets/changelogs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var fs = require('fs'); 17 | var path = require('path'); 18 | var spawn = require('child_process').spawn; 19 | var project = require('../lib/project.js'); 20 | 21 | 22 | roto.addTarget('changelogs', { 23 | description: 'Builds new master changelogs.' 24 | }, function(options) { 25 | var files; 26 | 27 | roto.addTask(function(callback) { 28 | files = project.getChangelogs(); 29 | callback(); 30 | }); 31 | 32 | // generate changelogs/master.txt 33 | roto.addTask(function(callback) { 34 | var ver, txt = ''; 35 | for (var i = 0, n = files.length; i < n; i++) { 36 | ver = 'v' + path.basename(files[i], '.txt'); 37 | txt += ver + '\n'; 38 | txt += fs.readFileSync(files[i], 'utf8').replace(/^\s+|\s+$/g, ''); 39 | txt += '\n\n'; 40 | } 41 | txt = txt.replace(/\s+$/, '') + '\n'; 42 | roto.writeFile('changes/master.txt', txt, 'utf8'); 43 | console.log('changes/master.txt written.'); 44 | callback(); 45 | }); 46 | 47 | // generate HISTORY.md 48 | roto.addTask(function(callback) { 49 | var ver, txt; 50 | var rows = []; 51 | for (var i = 0, n = files.length; i < n; i++) { 52 | ver = 'v' + path.basename(files[i], '.txt'); 53 | rows.push('' + ver + '' + fs.readFileSync(files[i], 'utf8').replace(/^\s+|\s+$/g, '').replace(/\r?\n/g, '
') + ''); 54 | } 55 | txt = '# Version History\n\n\n' + rows.join('\n') + '\n
\n'; 56 | roto.writeFile('HISTORY.md', txt, 'utf8'); 57 | console.log('HISTORY.md written.'); 58 | callback(); 59 | }); 60 | 61 | }); -------------------------------------------------------------------------------- /src/targets/compile.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var async = require('async'); 18 | var fs = require('fs'); 19 | var path = require('path'); 20 | var spawn = require('child_process').spawn; 21 | var hosts = require('../lib/hosts.js'); 22 | 23 | 24 | roto.addTarget('compile', { 25 | description: 'Compiles SWF, ready for packaging / testing.', hidden: true 26 | }, function(options) { 27 | var profile = options.debug !== false ? 'debug' : 'release'; 28 | var ver_flex; 29 | var folder_cssdk; 30 | var folder_flex; 31 | var folder_src = './src'; 32 | var folder_build = './build/bin-' + profile; 33 | var bin_amxmlc; 34 | var paths_mxml; 35 | var path_amxmlc; 36 | var path_manifest; 37 | 38 | // find all *.mxml files 39 | paths_mxml = roto.findFiles(folder_src + '/*.mxml'); 40 | if (!paths_mxml || !paths_mxml.length) { 41 | console.error(roto.colorize('ERROR: ', 'red') + 'No *.mxml files found in "src".'); 42 | return false; 43 | } 44 | 45 | // load project configuration to `config` global 46 | roto.addTask('csxs.config_load'); 47 | 48 | // configure environment 49 | roto.addTask('target:configure', options); 50 | 51 | // compilation settings 52 | roto.addTask(function(callback) { 53 | ver_flex = options['flex-version'] || config['flex-version']; 54 | folder_cssdk = process.env.CSSDK; 55 | folder_flex = folder_cssdk + '/CS Flex SDK ' + ver_flex; 56 | bin_amxmlc = IS_WINDOWS ? 'amxmlc.exe' : 'amxmlc'; 57 | path_amxmlc = path.normalize(folder_flex + '/bin/' + bin_amxmlc); 58 | path_manifest = path.resolve('./src', options['manifest']); 59 | 60 | callback(); 61 | }); 62 | 63 | // validate manifest 64 | roto.addTask(function(callback) { 65 | if (!fs.existsSync(path_manifest)) { 66 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to read "' + path_manifest + '".'); 67 | return callback(false); 68 | } 69 | callback(); 70 | }); 71 | 72 | // resolve swc library paths 73 | roto.addTask(function(callback) { 74 | console.log('Resolving SWC dependencies...'); 75 | if (!config.flex.hasOwnProperty(ver_flex)) { 76 | console.error(roto.colorize('ERROR: ', 'red') + 'Invalid Flex version number "' + ver_flex + '".'); 77 | return callback(false); 78 | } 79 | 80 | var libs = config.flex[ver_flex]; 81 | for (var i = 0, n = libs.length; i < n; i++) { 82 | libs[i] = libs[i].replace(/\$\{([a-zA-Z_]+)\}/g, function() { 83 | var var_name = arguments[1]; 84 | var var_value = process.env[var_name] || ''; 85 | return path.normalize(var_value).replace(/\/$/, ''); 86 | }); 87 | if (!fs.existsSync(libs[i])) { 88 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to find "' + libs[i] + '"'); 89 | return callback(false); 90 | } 91 | } 92 | 93 | callback(); 94 | }); 95 | 96 | // check for compiler 97 | roto.addTask(function(callback) { 98 | console.log('Checking for compiler...'); 99 | if (!fs.existsSync(path_amxmlc)) { 100 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to find Adobe Application Compiler at:'); 101 | console.error('"' + path_amxmlc + '"'); 102 | return callback(false); 103 | } 104 | 105 | callback(); 106 | }); 107 | 108 | // prepare build directory 109 | roto.addTask('dir-remove', {path: folder_build}); 110 | roto.addTask('dir-copy', {from: './assets', to: folder_build + '/assets'}); 111 | roto.addTask('csxs.amxmlc_manifest', function() { 112 | return _.extend({}, options, { 113 | input: path_manifest, 114 | output: folder_build + '/CSXS/manifest.xml' 115 | }); 116 | }); 117 | 118 | // copy jsx scripts 119 | roto.addTask(function(callback) { 120 | if (fs.existsSync(folder_src + '/' + config.basename + '.jsx')) { 121 | console.log('Copying *.jsx scripts... '); 122 | roto.executeTask('csxs.fs_copy', { 123 | from : folder_src + '/' + config.basename + '.jsx', 124 | to : folder_build + '/' + config.basename + '.jsx' 125 | }, callback); 126 | } else { 127 | callback(); 128 | } 129 | }); 130 | 131 | // minify jsx scripts 132 | roto.addTask(function(callback) { 133 | console.log('Minifying *.jsx scripts...'); 134 | var files = roto.findFiles(folder_build + '/*.jsx'); 135 | async.each(files, function(file, callback) { 136 | roto.executeTask('uglify', { 137 | files : [path.relative(path.resolve(folder_build), file)], 138 | output : file, 139 | banner : '/** Copyright (C) ' + (new Date()).getFullYear() + ' - ' + config.author + ' */' 140 | }, function(status) { 141 | callback(status === false ? 'Unable to process "' + file + '". Check for syntax errors and try again.' : null); 142 | }); 143 | }, function(err) { 144 | if (err) { 145 | console.error(roto.colorize('ERROR: ', 'red') + err); 146 | callback(false); 147 | } else { 148 | callback(); 149 | } 150 | }); 151 | }); 152 | 153 | // compile all mxml files 154 | var compile_mxml = function(path_mxml) { 155 | roto.addTask('csxs.amxmlc', function() { 156 | return { 157 | profile : profile, 158 | ver_flex : ver_flex, 159 | path_src : folder_src, 160 | path_amxmlc : path_amxmlc, 161 | path_mxml : path_mxml, 162 | path_output : folder_build + '/' + path.basename(path_mxml, '.mxml') + '.swf', 163 | properties : options.properties 164 | }; 165 | }); 166 | }; 167 | 168 | for (var i = 0, n = paths_mxml.length; i < n; i++) { 169 | compile_mxml(paths_mxml[i]); 170 | } 171 | 172 | }); -------------------------------------------------------------------------------- /src/targets/configure.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var fs = require('fs'); 18 | var path = require('path'); 19 | var spawn = require('child_process').spawn; 20 | var project = require('../lib/project.js'); 21 | 22 | 23 | roto.addTarget('configure', { 24 | description: 'Configures build environment (Determines CS and Flex SDK locations).' 25 | }, function(options) { 26 | 27 | // load project configuration to `config` global 28 | roto.addTask('csxs.config_load'); 29 | roto.addTask(function(callback) { 30 | if (options.debug !== false) { 31 | config.id += '.debug'; 32 | config.name += ' (debug)'; 33 | } 34 | callback(); 35 | }); 36 | 37 | // check for creative suite sdk 38 | roto.addTask(function(callback) { 39 | if (!process.env.CSSDK || !fs.existsSync(process.env.CSSDK)) { 40 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to find Adobe Creative Suite SDK.'); 41 | console.error('Download it and set CSSDK to its location.'); 42 | console.error(roto.colorize('http://www.adobe.com/devnet/creativesuite.html', 'underline')); 43 | console.error(roto.colorize('export CSSDK=(path)', 'gray')); 44 | return callback(false); 45 | } else { 46 | console.log('CSSDK=' + process.env.CSSDK); 47 | } 48 | callback(); 49 | }); 50 | 51 | // generate configuration for flash builder 52 | roto.addTask(function(callback) { 53 | if (fs.existsSync('./src/' + config.basename + '.jsx')) { 54 | roto.executeTask('csxs.fs_symlink', { 55 | from: './src/' + config.basename + '.jsx', 56 | to: './' + config.basename + '.jsx' 57 | }, callback); 58 | } else { 59 | callback(); 60 | } 61 | }); 62 | 63 | roto.addTask('csxs.fs_copy', { 64 | from : path.resolve(__dirname, '../../project/.actionScriptProperties'), 65 | to : './.actionScriptProperties' 66 | }); 67 | 68 | roto.addTask('template', function() { 69 | var build = config.builds[0]; 70 | var flex_version = build['flex-version'] || config['flex-version']; 71 | var libraries = config.flex[flex_version]; 72 | var libraries_xml = []; 73 | 74 | for (var i = 0, n = libraries.length; i < n; i++) { 75 | libraries_xml.push(''); 76 | } 77 | 78 | return { 79 | files : '.actionScriptProperties', 80 | data : _.extend({}, config, { 81 | 'compiler-arguments': project.getCompilerArguments(config, options).join(' '), 82 | 'libraries': libraries_xml.join('\n\t\t\t') 83 | }) 84 | }; 85 | }); 86 | 87 | roto.addTask('csxs.amxmlc_manifest', function() { 88 | return _.extend({}, config.builds[0], { 89 | input: 'src/manifest.cs6.xml', 90 | output: '.staged-extension/CSXS/manifest.xml' 91 | }); 92 | }); 93 | 94 | }); -------------------------------------------------------------------------------- /src/targets/create.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var fs = require('fs'); 18 | var async = require('async'); 19 | var path = require('path'); 20 | var optimist = require('optimist'); 21 | var prompt = require('../lib/prompt.js'); 22 | var uuid = require('../lib/uuid.js'); 23 | var HOSTS = require('../../hosts.json'); 24 | 25 | 26 | roto.addTarget('create', { 27 | description: 'Creates a new Creative Suite project in the current directory.' 28 | }, function(options) { 29 | 30 | // check for empty working directory 31 | roto.addTask(function(callback) { 32 | var files = fs.readdirSync('.'); 33 | for (var i = 0, n = files.length; i < n; i++) { 34 | if (path.basename(files[i]).charAt(0) === '.') { 35 | continue; 36 | } 37 | console.error(roto.colorize('ERROR: ', 'red') + 'Working directory must be empty.'); 38 | return callback(false); 39 | } 40 | return callback(); 41 | }); 42 | 43 | // prompt user for project settings 44 | var settings_schemas = [ 45 | { 46 | key: 'name', 47 | title: 'Project Name', 48 | description: 'Example: "My Extension"', 49 | pattern: /^[a-zA-Z0-9\s\-]+$/, 50 | message: 'Can only contain letters, spaces, or dashes', 51 | required: true 52 | }, 53 | { 54 | key: 'id', 55 | title: 'Project Identifier (unique)', 56 | description: 'Example: "MyExtension"', 57 | pattern: /^[a-zA-Z][\.a-zA-Z]*$/, 58 | message: 'Can only contain letters, numbers, and periods. Must start with a letter.', 59 | required: true 60 | }, 61 | { 62 | key: 'author', 63 | title: 'Author Name', 64 | description: 'Example: "Nikola Tesla"', 65 | pattern: /^[a-zA-Z0-9\s]+$/, 66 | message: 'Can only contain letters, numbers, and spaces.', 67 | required: true 68 | }, 69 | { 70 | key: 'cs-products', 71 | title: 'Creative Suite Products', 72 | description: 'Please list (comma-separated). Options: photoshop, illustrator, indesign, flash, fireworks, dreamweaver, premiere, prelude', 73 | required: true, 74 | format: function(value) { 75 | var i, n; 76 | var items = _.without(_.uniq(value.toLowerCase().split(/\s*,+\s*/)), ''); 77 | for (i = 0, n = items.length; i < n; i++) { 78 | if (!HOSTS['6.0'].hasOwnProperty(items[i])) { 79 | throw new Error('Unknown item: "' + items[i] + '"'); 80 | } 81 | } 82 | return JSON.stringify(items); 83 | } 84 | }, 85 | { 86 | key: 'cc-products', 87 | title: 'Creative Cloud Products', 88 | description: 'Please list (comma-separated). Options: photoshop, illustrator, indesign, flash, fireworks, dreamweaver, premiere, prelude', 89 | required: true, 90 | format: function(value) { 91 | var i, n; 92 | var result = {}; 93 | var items = _.without(_.uniq(value.toLowerCase().split(/\s*,+\s*/)), ''); 94 | for (i = 0, n = items.length; i < n; i++) { 95 | if (!HOSTS['CC'].hasOwnProperty(items[i])) { 96 | throw new Error('Unknown item: "' + items[i] + '"'); 97 | } 98 | result[items[i]] = HOSTS['CC'].version; 99 | } 100 | return JSON.stringify(items); 101 | } 102 | } 103 | ]; 104 | 105 | var settings = {}; 106 | roto.addTask(function(callback) { 107 | var i = 0; 108 | var hr = '--------------------------------------------'; 109 | console.log(roto.colorize(hr, 'gray') + ''); 110 | console.log('Please provide the following project properties.\n'); 111 | 112 | async.mapSeries(settings_schemas, function(schema, callback) { 113 | prompt(schema, function(err, value) { 114 | if (++i < settings_schemas.length) { 115 | console.log(''); 116 | } 117 | callback(err, value); 118 | }); 119 | }, function(err, results) { 120 | for (var i = 0, n = results.length; i < n; i++) { 121 | settings[settings_schemas[i].key] = results[i]; 122 | } 123 | settings.basename = settings.id; 124 | settings.uuid = uuid(); 125 | settings.year = (new Date()).getFullYear(); 126 | console.log(roto.colorize(hr, 'gray')); 127 | callback(); 128 | }); 129 | }); 130 | 131 | roto.addTask(function(callback) { 132 | console.log('Generating project...'); 133 | callback(); 134 | }); 135 | 136 | // copy project template 137 | roto.addTask('dir-copy', { 138 | from: path.join(__dirname, '../../project'), 139 | to: './' 140 | }); 141 | 142 | // fill in templates 143 | roto.addTask(function(callback) { 144 | console.log('Populating templates...'); 145 | var files = roto.findFiles([ 146 | 'csxs.json', 147 | 'README.md', 148 | 'src/ID.jsx' 149 | ]); 150 | 151 | var queue = async.queue(function(file, callback) { 152 | async.auto({ 153 | input: function(callback) { 154 | fs.readFile(file, 'utf8', callback); 155 | }, 156 | process: ['input', function(callback, obj) { 157 | var content = obj.input; 158 | for (var key in settings) { 159 | if (settings.hasOwnProperty(key)) { 160 | var regex = new RegExp('\\{\\{' + key.replace(/\-/g, '\\-') + '\\}\\}', 'g'); 161 | content = content.replace(regex, settings[key]); 162 | } 163 | } 164 | callback(null, content); 165 | }], 166 | write: ['process', function(callback, obj) { 167 | fs.writeFile(file, obj.process, 'utf8', callback); 168 | }] 169 | }, callback); 170 | }); 171 | 172 | queue.drain = function(err) { callback(); }; 173 | queue.push(files); 174 | }); 175 | 176 | // rename files 177 | roto.addTask(function(callback) { 178 | var files = roto.findFiles('**/ID.*'); 179 | for (var i = 0, n = files.length; i < n; i++) { 180 | var dir = path.dirname(files[i]); 181 | var ext = path.extname(files[i]); 182 | fs.renameSync(files[i], path.join(dir, settings.id + ext)); 183 | } 184 | callback(); 185 | }); 186 | 187 | // finished 188 | roto.addTask(function(callback) { 189 | console.log(roto.colorize('Project created.', 'green')); 190 | callback(); 191 | }); 192 | 193 | }); -------------------------------------------------------------------------------- /src/targets/debug.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var fs = require('fs'); 18 | var path = require('path'); 19 | var spawn = require('child_process').spawn; 20 | var exec = require('child_process').exec; 21 | var hosts = require('../lib/hosts.js'); 22 | 23 | 24 | roto.addTarget('debug', { 25 | description: 'Puts CS into debug mode, installs the extension, and starts logging.' 26 | }, function(options) { 27 | var ver; 28 | var ver_max; 29 | var ver_selected = options['cs-version']; 30 | var versions = {}; 31 | var build; 32 | var path_log; 33 | var path_application; 34 | var host; 35 | var folder_apps; 36 | var folder_home; 37 | var folder_servicemgr; 38 | var folder_application; 39 | var folder_destination; 40 | var folder_source; 41 | 42 | // load project configuration to `config` global 43 | roto.addTask('csxs.config_load'); 44 | 45 | // find matching build configuration 46 | roto.addTask(function(callback) { 47 | var i, n; 48 | var index_product; 49 | var index_version; 50 | var option_product = options['cs-product']; 51 | var option_version = options['cs-version']; 52 | 53 | if (!options['cs-version'] && !options['cs-product']) { 54 | build = config.builds[0]; 55 | options['cs-version'] = options['cs-version'] || _.last(build['cs-versions']); 56 | options['cs-product'] = options['cs-product'] || build['cs-products'][0]; 57 | return callback(); 58 | } 59 | 60 | if (option_version) option_version = parseFloat(option_version).toFixed(1); 61 | for (i = 0, n = config.builds.length; i < n; i++) { 62 | index_product = !option_product || config.builds[i]['cs-products'].indexOf(option_product); 63 | index_version = !option_version || config.builds[i]['cs-versions'].indexOf(option_version); 64 | if (index_product !== -1 && index_version !== -1) { 65 | build = config.builds[i]; 66 | if (!option_product) options['cs-product'] = build['cs-products'][0]; 67 | if (!option_version) options['cs-version'] = build['cs-versions'][0]; 68 | return callback(); 69 | } 70 | } 71 | 72 | console.error(roto.colorize('ERROR: ', 'red') + 'No matching build configuration.'); 73 | return callback(false); 74 | }); 75 | 76 | // validate host information 77 | roto.addTask(function(callback) { 78 | try { 79 | host = hosts.getProduct(options['cs-product'], options['cs-version']); 80 | } catch (err) { 81 | console.error(roto.colorize('ERROR: ', 'red') + err.message); 82 | return callback(false); 83 | } 84 | if (!host) { 85 | console.error(roto.colorize('ERROR: ', 'red') + 'No matching host found.'); 86 | return callback(false); 87 | } 88 | callback(); 89 | }); 90 | 91 | // detect application version and location 92 | roto.addTask(function(callback) { 93 | ver_selected = String(parseFloat(options['cs-version'])); 94 | 95 | folder_apps = IS_WINDOWS ? 'C:/Program Files' : '/Applications'; 96 | folder_source = './build/bin-debug'; 97 | folder_application = folder_apps + '/Adobe ' + host.name + ' CS' + ver_selected; 98 | folder_home = process.env[IS_WINDOWS ? 'USERPROFILE' : 'HOME']; 99 | folder_servicemgr = IS_WINDOWS 100 | ? folder_home + '/AppData/Roaming/Adobe/CS' + ver_selected + 'ServiceManager/extensions' 101 | : folder_home + '/Library/Application Support/Adobe/CS' + ver_selected + 'ServiceManager/extensions'; 102 | folder_destination = folder_servicemgr + '/' + config.id; 103 | path_log = IS_WINDOWS 104 | ? folder_home + '/AppData/Roaming/Macromedia/Flash Player/Logs/flashlog.txt' 105 | : folder_home + '/Library/Preferences/Macromedia/Flash Player/Logs/flashlog.txt'; 106 | 107 | if (!fs.existsSync(folder_application)) { 108 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to find Adobe ' + host.name + ' CS' + ver_selected + '.'); 109 | console.error('"' + folder_application + '"'); 110 | return callback(false); 111 | } 112 | 113 | path_application = folder_application + '/Adobe ' + host.name + ' CS' + ver_selected + (IS_WINDOWS ? '.exe' : '.app'); 114 | if (!fs.existsSync(path_application)) { 115 | path_application = folder_application + '/Adobe ' + host.name + (IS_WINDOWS ? '.exe' : '.app') 116 | } 117 | 118 | callback(); 119 | }); 120 | 121 | // compile debug version 122 | if (options['compile'] !== false) { 123 | roto.addTask('target:compile', function() { 124 | var opts = _.extend({debug: true}, build, options); 125 | return opts; 126 | }); 127 | } 128 | 129 | // install extension 130 | roto.addTask('dir-copy', function() { 131 | return { 132 | from : folder_source, 133 | to : folder_destination 134 | } 135 | }); 136 | 137 | // enable debug mode + logging 138 | roto.addTask(function(callback) { 139 | var path_debug; 140 | var path_mmcfg; 141 | 142 | // enable application debug mode 143 | if (host.name === 'Photoshop' || host.name === 'Dreamweaver') { 144 | path_debug = IS_WINDOWS 145 | ? folder_application + '/debug' 146 | : path_application + '/Contents/debug'; 147 | 148 | console.log(roto.colorize('touch "' + path_debug, 'magenta') + '"'); 149 | fs.writeFileSync(path_debug, '', 'utf8'); 150 | } 151 | 152 | // enable flash player logging 153 | try { 154 | path_mmcfg = IS_WINDOWS ? folder_home + '/mm.cfg' : '/Library/Application Support/Macromedia/mm.cfg'; 155 | console.log('Creating "' + path_mmcfg + '"...'); 156 | fs.writeFileSync(path_mmcfg, [ 157 | 'ErrorReportingEnable=1', 158 | 'TraceOutputFileEnable=1' 159 | ].join('\n'), 'utf8'); 160 | } catch (e) { 161 | console.log(roto.colorize('WARNING: Unable to write "mm.cfg". If debugging doesn\'t work, run with sudo.', 'yellow')); 162 | } 163 | 164 | // create empty log 165 | console.log('Empty log file at "' + path_log + '"...'); 166 | roto.writeFile(path_log, '', 'utf8'); 167 | 168 | callback(); 169 | }); 170 | 171 | // set "PlayerDebugMode" flag in plist 172 | roto.addTask(function(callback) { 173 | var args, defaults; 174 | var PLISTS = { 175 | '5' : folder_home + '/Library/Preferences/com.adobe.CSXS2Preferences.plist', 176 | '5.5' : folder_home + '/Library/Preferences/com.adobe.CSXS.2.5.plist', 177 | '6' : folder_home + '/Library/Preferences/com.adobe.CSXS.3.plist' 178 | }; 179 | 180 | if (!IS_MAC) return callback(); 181 | if (!PLISTS.hasOwnProperty(ver_selected)) return callback(); 182 | 183 | args = ['write', PLISTS[ver_selected], 'PlayerDebugMode', '1']; 184 | console.log(roto.colorize('defaults ' + args.join(' '), 'magenta')); 185 | 186 | defaults = spawn('defaults', args); 187 | defaults.stdout.on('data', function (data) { process.stdout.write(data); }); 188 | defaults.stderr.on('data', function (data) { process.stderr.write(data); }); 189 | defaults.on('exit', function(code) { callback(); }); 190 | }); 191 | 192 | // launch application 193 | if (options.launch) { 194 | roto.addTask(function(callback) { 195 | if (IS_WINDOWS) return callback(); 196 | var cmd_kill = 'kill -9 `ps -ef | grep "Adobe ' + host.name + ' CS" | grep -v grep | awk \'{print $2}\'`'; 197 | console.log(roto.colorize(cmd_kill, 'magenta')); 198 | exec(cmd_kill, function(err, stdout, stderr) { 199 | callback(); 200 | }); 201 | }); 202 | roto.addTask(function(callback) { 203 | var application; 204 | var path_start = IS_WINDOWS ? 'start' : 'open'; 205 | 206 | 207 | console.log(roto.colorize(path_start + ' "' + path_application + '"', 'magenta')); 208 | 209 | application = IS_WINDOWS 210 | ? spawn(path_start, [path_application]) 211 | : spawn(path_start, ['-F', '-n', path_application]); 212 | application.stdout.on('data', function (data) { process.stdout.write(data); }); 213 | application.stderr.on('data', function (data) { process.stderr.write(data); }); 214 | application.on('exit', function(code) { 215 | callback(); 216 | }); 217 | }); 218 | } 219 | 220 | // start flash debugger 221 | if (options.fdb) { 222 | roto.addTask('csxs.fdb', function() { 223 | return {ver_flex: options['flex-version'] || config['flex-version']}; 224 | }); 225 | } else { 226 | roto.addTask(function(callback) { 227 | var tail, args; 228 | 229 | console.log(roto.colorize('tail -f "' + path_log + '"', 'magenta')); 230 | tail = spawn('tail', ['-f', path_log]); 231 | tail.stdout.on('data', function (data) { process.stdout.write(data); }); 232 | tail.stderr.on('data', function (data) { process.stderr.write(data); }); 233 | tail.on('exit', function(code) { callback(); }); 234 | }); 235 | } 236 | 237 | }); -------------------------------------------------------------------------------- /src/targets/package.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var fs = require('fs'); 18 | var path = require('path'); 19 | var spawn = require('child_process').spawn; 20 | var exec = require('child_process').exec; 21 | var uuid = require('../lib/uuid.js'); 22 | var hosts = require('../lib/hosts.js'); 23 | 24 | 25 | roto.addTarget('package', { 26 | description: 'Generates signed *.zxp installer ready for distribution.' 27 | }, function(options) { 28 | var folder_build = './build/bin-release'; 29 | var folder_package = './package'; 30 | var zxps = []; 31 | 32 | // load project configuration to `config` global 33 | roto.addTask('csxs.config_load'); 34 | 35 | // certificate settings 36 | roto.addTask(function(callback) { 37 | if (!config.certificate) { 38 | config.certificate = { 39 | location: '.certificate-self.p12', 40 | password: 'password' 41 | }; 42 | console.log(roto.colorize('WARNING: You should provide a certificate from a valid issuing', 'yellow')); 43 | console.log(roto.colorize('certificate authority (IA) to prevent warnings during installation.', 'yellow')); 44 | console.log(roto.colorize('http://cssdk.host.adobe.com/sdk/1.0/docs/WebHelp/programmers_guide/Deploy.htm', 'gray')); 45 | console.log(roto.colorize('https://github.com/creativemarket/csxs/blob/master/docs/configuration.md#certificate', 'gray')); 46 | 47 | if (!fs.existsSync(config.certificate.location)) { 48 | return roto.executeTask('target:certificate', { 49 | password : config.certificate.password, 50 | output : config.certificate.location 51 | }, callback); 52 | } 53 | } 54 | callback(); 55 | }); 56 | 57 | // create temporary "package" directory 58 | roto.addTask('dir-remove', {path: folder_package}); 59 | roto.addTask(function(callback) { 60 | fs.mkdir(folder_package, function() { callback(); }); 61 | }); 62 | 63 | // execute individual sub builds 64 | roto.addTask(function(callback) { 65 | var i, n, jobs = []; 66 | var build = function() { 67 | if (!jobs.length) return callback(); 68 | 69 | var job = jobs.shift(); 70 | var config_job = _.extend({}, config, job); 71 | var filename = uuid() + '.zxp'; 72 | 73 | config_job.debug = false; 74 | zxps.push(filename); 75 | 76 | roto.executeTask('target:compile', config_job, function(result) { 77 | if (result === false) { 78 | return callback(false); 79 | } 80 | 81 | roto.executeTask('csxs.ucf', { 82 | input : folder_build, 83 | output : folder_package + '/' + filename, 84 | keystore : config.certificate.location, 85 | password : config.certificate.password 86 | }, function(result) { 87 | if (result === false) { 88 | return callback(false); 89 | } 90 | build(); 91 | }); 92 | 93 | }); 94 | }; 95 | 96 | // queue builds & begin 97 | for (i = 0, n = config.builds.length; i < n; i++) { 98 | jobs.push(config.builds[i]); 99 | } 100 | build(); 101 | }); 102 | 103 | // populate project mxi 104 | roto.addTask(function(callback) { 105 | var i, j, n, host_key, settings, version_range, version_ranges, filename_zxp; 106 | var product_versions = {}; 107 | var list_files = []; 108 | var list_products = []; 109 | 110 | var add_version_range = function(host_key, range) { 111 | if (!product_versions.hasOwnProperty(host_key)) { 112 | product_versions[host_key] = {}; 113 | } 114 | if (!product_versions[host_key].min || parseFloat(range.min) < parseFloat(product_versions[host_key].min)) { 115 | product_versions[host_key].min = range.min; 116 | } 117 | if (!product_versions[host_key].max || parseFloat(range.max) > parseFloat(product_versions[host_key].max)) { 118 | product_versions[host_key].max = range.max; 119 | } 120 | }; 121 | 122 | var get_cs_version_range = function(host_key, cs_versions) { 123 | var range = hosts.getVersionRange(host_key, cs_versions); 124 | add_version_range(host_key, range); 125 | return range; 126 | }; 127 | 128 | var get_cc_product_list = function(product_name) { 129 | // http://helpx.adobe.com/extension-manager/kb/general-mxi-elements.html#id_64891 130 | var map = { 131 | 'Illustrator' : 'Illustrator,Illustrator32,Illustrator64', 132 | 'InCopy' : 'InCopy,InCopy32,InCopy64', 133 | 'InDesign' : 'InDesign,InDesign32,InDesign64', 134 | 'Photoshop' : 'Photoshop,Photoshop32,Photoshop64' 135 | }; 136 | 137 | return map[product_name] || product_name; 138 | }; 139 | 140 | // create list 141 | for (i = 0, n = config.builds.length; i < n; i++) { 142 | settings = config.builds[i]; 143 | filename_zxp = zxps[i]; 144 | 145 | // creative suite apps 146 | if (settings.hasOwnProperty('cs-products')) { 147 | for (j = 0; j < settings['cs-products'].length; j++) { 148 | host_key = settings['cs-products'][j]; 149 | version_range = get_cs_version_range(host_key, settings['cs-versions']); 150 | list_files.push(''); 151 | } 152 | } 153 | 154 | // creative cloud apps 155 | if (settings.hasOwnProperty('cc-products')) { 156 | for (host_key in settings['cc-products']) { 157 | if (!settings['cc-products'].hasOwnProperty(host_key)) { 158 | continue; 159 | } 160 | version_ranges = settings['cc-products'][host_key]; 161 | for (j = 0; j < version_ranges.length; j++) { 162 | add_version_range(host_key, version_ranges[j]); 163 | list_files.push(''); 164 | } 165 | } 166 | } 167 | 168 | } 169 | 170 | // create list 171 | for (host_key in product_versions) { 172 | if (product_versions.hasOwnProperty(host_key)) { 173 | list_products.push(''); 174 | } 175 | } 176 | 177 | roto.executeTask('template', { 178 | files : 'src/' + config.basename + '.mxi', 179 | output : './' + config.basename + '.mxi', 180 | data : _.extend({}, config, { 181 | 'list-files': list_files.join('\n\t\t'), 182 | 'list-products': list_products.join('\n\t\t') 183 | }) 184 | }, callback); 185 | }); 186 | 187 | // package hybrid extension 188 | roto.addTask('csxs.fs_copy', {from: 'assets/icon-mxi.png', to: folder_package + '/icon.png'}); 189 | roto.addTask('csxs.fs_copy', function() { 190 | return { 191 | from : config.basename + '.mxi', 192 | to : folder_package + '/' + config.basename + '.mxi' 193 | }; 194 | }); 195 | roto.addTask('csxs.ucf', function() { 196 | return { 197 | input : folder_package, 198 | output : config.filename + '.' + config.version + '.zxp', 199 | keystore : config.certificate.location, 200 | password : config.certificate.password 201 | }; 202 | }); 203 | roto.addTask('csxs.fs_copy', function() { 204 | return { 205 | from : config.filename + '.' + config.version + '.zxp', 206 | to : config.basename + '.zxp' 207 | }; 208 | }); 209 | 210 | }); -------------------------------------------------------------------------------- /src/targets/publish.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var fs = require('fs'); 17 | var path = require('path'); 18 | var spawn = require('child_process').spawn; 19 | var exec = require('child_process').exec; 20 | var http = require('http'); 21 | var git = require('../lib/git.js'); 22 | var project = require('../lib/project.js'); 23 | 24 | 25 | roto.addTarget('publish', { 26 | description: 'Builds, signs, and uploads a *.zxp installer + update info to S3.' 27 | }, function(options) { 28 | 29 | var changes; 30 | var changes_html; 31 | var file_zxp_versioned; 32 | var file_zxp; 33 | var url_zxp; 34 | var path_s3; 35 | var path_changelog; 36 | 37 | // load project configuration to `config` global 38 | roto.addTask('csxs.config_load'); 39 | 40 | // validate settings 41 | roto.addTask(function(callback) { 42 | var err; 43 | if (!config.s3) err = 'Amazon S3 not configured.'; 44 | else if (!config.s3.bucket) err = 'Amazon S3 bucket not provided.'; 45 | else if (!config.s3.key) err = 'Amazon S3 access key not provided.'; 46 | else if (!config.s3.secret) err = 'Amazon S3 access secret not provided.'; 47 | 48 | if (err) { 49 | console.error(roto.colorize('ERROR: ', 'red') + err); 50 | console.error(' ' + roto.colorize('https://github.com/creativemarket/csxs/blob/master/docs/configuration.md#s3', 'underline')); 51 | return callback(false); 52 | } 53 | 54 | callback(); 55 | }); 56 | 57 | // deploy settings 58 | roto.addTask(function(callback) { 59 | file_zxp_versioned = config.filename + '.' + config.version + '.zxp'; 60 | file_zxp = config.filename + '.zxp'; 61 | path_changelog = 'changes/' + config.version + '.txt'; 62 | path_s3 = config.s3.path || '/'; 63 | changes = ''; 64 | 65 | if (path_s3.charAt(path_s3.length - 1) !== '/') path_s3 += '/'; 66 | path_s3 = path_s3.replace(/^\/+/, ''); 67 | 68 | url_zxp = 'http://' + config.s3.bucket + '/' + path_s3 + file_zxp_versioned; 69 | callback(); 70 | }); 71 | 72 | // read changes 73 | roto.addTask(function(callback) { 74 | try { 75 | changes = fs.readFileSync(path_changelog, 'utf8'); 76 | } catch (e) { 77 | console.error(roto.colorize('ERROR: ', 'red') + '"' + path_changelog + '" must exist.'); 78 | return callback(false); 79 | } 80 | callback(); 81 | }); 82 | 83 | // build "update.xml" description (html) 84 | roto.addTask(function(callback) { 85 | var version; 86 | var changelogs = project.getChangelogs(); 87 | changes_html = '
'; 88 | 89 | for (var i = changelogs.length - 1, i0 = Math.max(0, i - 2); i >= i0; i--) { 90 | version = 'v' + path.basename(changelogs[i], '.txt'); 91 | changes_html += '
' + version + '
'; 92 | changes_html += '
' + fs.readFileSync(changelogs[i], 'utf8').replace(/\r?\n/g, '
') + '
'; 93 | } 94 | changes_html += '
'; 95 | callback(); 96 | }); 97 | 98 | // generate new master changelog files 99 | roto.addTask('target:changelogs'); 100 | 101 | // check to see if this version has already been released 102 | roto.addTask(function(callback) { 103 | http.request({ 104 | hostname : config.s3.bucket, 105 | port : 80, 106 | path : '/releases/' + file_zxp_versioned, 107 | method : 'HEAD' 108 | }, function(res) { 109 | if (res.statusCode === 200) { 110 | if (options.force) { 111 | console.error(roto.colorize('WARNING:', 'yellow') + ' v' + config.version + ' has already been released.'); 112 | callback(); 113 | } else { 114 | console.error(roto.colorize('ERROR:', 'red') + ' v' + config.version + ' has already been released. Run with --force to ignore.'); 115 | callback(false); 116 | } 117 | } else { 118 | callback(); 119 | } 120 | }).end(); 121 | }); 122 | 123 | // check for clean working directory 124 | roto.addTask('csxs.git_is_clean'); 125 | 126 | // build fresh copy 127 | roto.addTask('target:package'); 128 | 129 | // create staged files 130 | roto.addTask('dir-remove', {path: 'temp'}); 131 | roto.addTask('dir-copy', {from: 'changes', to: 'temp/changes'}); 132 | roto.addTask('csxs.fs_copy', function() { 133 | return {from: file_zxp_versioned, to: 'temp/' + file_zxp}; 134 | }); 135 | roto.addTask('csxs.fs_copy', function() { 136 | return {from: file_zxp_versioned, to: 'temp/' + file_zxp_versioned}; 137 | }); 138 | 139 | // update.json 140 | roto.addTask(function(callback) { 141 | var info = { 142 | 'version': config.version, 143 | 'description': changes, 144 | 'url': url_zxp 145 | }; 146 | 147 | roto.writeFile('temp/update.json', JSON.stringify(info), 'utf8'); 148 | callback(); 149 | }); 150 | 151 | // update.xml 152 | roto.addTask('template', function() { 153 | return { 154 | files : 'src/update.xml', 155 | output : 'temp/update.xml', 156 | data : { 157 | version: config.version, 158 | description: changes_html, 159 | url: url_zxp 160 | } 161 | }; 162 | }); 163 | 164 | // sync to s3 165 | roto.addTask('s3', function() { 166 | return { 167 | key : config.s3.key, 168 | secret : config.s3.secret, 169 | bucket : config.s3.bucket, 170 | folder : 'temp', 171 | destination : path_s3, 172 | ttl : 0 173 | }; 174 | }); 175 | 176 | // create git tag 177 | roto.addTask('csxs.git_tag', function() { return {name: 'v' + config.version}; }); 178 | roto.addTask('csxs.git_push_tags'); 179 | 180 | // completion 181 | roto.addTask('dir-remove', {path: 'temp'}); 182 | roto.addTask(function(callback) { 183 | console.log(roto.colorize('v' + config.version + ' successfully released.', 'green')); 184 | callback(); 185 | }); 186 | 187 | }); -------------------------------------------------------------------------------- /src/tasks/amxmlc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var _ = require('lodash'); 17 | var fs = require('fs'); 18 | var path = require('path'); 19 | var spawn = require('child_process').spawn; 20 | var project = require('../lib/project.js'); 21 | var hosts = require('../lib/hosts.js'); 22 | 23 | /** 24 | * Options: 25 | * - input 26 | * - output 27 | * - cs-products 28 | * - cs-versions 29 | */ 30 | 31 | roto.defineTask('csxs.amxmlc_manifest', function(callback, options) { 32 | var i, j, k, n, range, ranges, host, host_id; 33 | var list_hosts = []; 34 | 35 | // creative suite apps 36 | var config_cs_products = options['cs-products']; 37 | var config_cs_versions = options['cs-versions']; 38 | if (config_cs_products) { 39 | for (i = 0, n = config_cs_products.length; i < n; i++) { 40 | host = hosts.getProduct(config_cs_products[i]); 41 | range = hosts.getVersionRange(config_cs_products[i], config_cs_versions); 42 | for (j = 0; j < host.ids.length; j++) { 43 | list_hosts.push(''); 44 | } 45 | } 46 | } 47 | 48 | // creative cloud apps 49 | var config_cc_products = options['cc-products']; 50 | if (config_cc_products) { 51 | for (host_id in config_cc_products) { 52 | if (!config_cc_products.hasOwnProperty(host_id)) { 53 | continue; 54 | } 55 | host = hosts.getProduct(host_id); 56 | ranges = config_cc_products[host_id]; 57 | for (j = 0; j < host.ids.length; j++) { 58 | for (k = 0; k < ranges.length; k++) { 59 | list_hosts.push(''); 60 | } 61 | } 62 | } 63 | } 64 | 65 | roto.executeTask('template', { 66 | files : path.relative(process.cwd(), options.input), 67 | output : options.output, 68 | data : _.extend({}, config, { 69 | 'list-hosts': list_hosts.join('\n\t\t\t') 70 | }) 71 | }, callback); 72 | }); 73 | 74 | /** 75 | * Options: 76 | * - profile 77 | * - ver_flex 78 | * - path_output 79 | * - path_src 80 | * - path_mxml 81 | * - path_amxmlc 82 | */ 83 | 84 | roto.defineTask('csxs.amxmlc', function(callback, options) { 85 | var args, args_extra, amxmlc, beautify, i, n; 86 | 87 | beautify = function(str) { 88 | return String(str) 89 | .replace(/(.+?) line: (\d+)(?: col:? \d+)?Warning: ([^\n]+)/g, roto.colorize('$1', 'white') + ' line $2\n' + roto.colorize('WARNING: $3', 'yellow')) // warnings 90 | .replace(/(.+?)\((\d+)\): (?:col:? \d+ )?Warning: ([^\n]+)/g, roto.colorize('$1', 'white') + ' line $2\n' + roto.colorize('WARNING: $3', 'yellow')) // warnings 91 | .replace(/([^\r\n]*?)\((\d+)\): col: (\d+):?/, roto.colorize('$1', 'white') + ' line $2 col $3') // errors 92 | .replace(/Error: ([^\r\n]+)/g, '\n' + roto.colorize('ERROR: $1', 'red')) // errors 93 | .replace(/(^|\n)[\t ]*\^[\t ]*(\n|$)/g, '$2') // pointers 94 | .replace(/\s{2,}/g, '\n') // consecutive whitespace 95 | .replace(/^\s+/, '') // leading line breaks 96 | .replace(/\s+$/, ''); // trailing line breaks 97 | }; 98 | 99 | // base compiler args 100 | args = [ 101 | '-verify-digests', 102 | '-warnings=true', 103 | '-use-network=true', 104 | '-compiler.strict=true', 105 | '-compiler.show-binding-warnings=true', 106 | '-compiler.show-deprecation-warnings=true', 107 | '-compiler.debug=' + String(options.profile === 'debug'), 108 | '-locale=en_US', 109 | '-output=' + options.path_output, 110 | '-library-path+=' + config.flex[options.ver_flex].join(',') 111 | ]; 112 | 113 | // extended arguments 114 | args_extra = project.getCompilerArguments(config, options, options.properties); 115 | for (i = 0, n = args_extra.length; i < n; i++) { 116 | args.push(args_extra[i]); 117 | } 118 | 119 | args.push('--source-path'); 120 | args.push(options.path_src); 121 | args.push('--'); 122 | args.push(options.path_mxml); 123 | 124 | // execute compiler 125 | console.log(roto.colorize('amxmlc ' + args.join(' '), 'magenta')); 126 | amxmlc = spawn(options.path_amxmlc, args); 127 | amxmlc.stdout.on('data', function (data) { console.log(beautify(data)); }); 128 | amxmlc.stderr.on('data', function (data) { console.error(beautify(data)); }); 129 | amxmlc.on('exit', function(code) { 130 | if (code !== 0) { 131 | console.error(roto.colorize('"' + options.path_output + '"', '') + ' [' + roto.colorize('fail', 'red') + ']'); 132 | return callback(false); 133 | } 134 | console.log(roto.colorize('"' + options.path_output + '"', '') + ' [' + roto.colorize('success', 'green') + ']'); 135 | return callback(); 136 | }); 137 | }); -------------------------------------------------------------------------------- /src/tasks/config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var fs = require('fs'); 17 | var path = require('path'); 18 | var jsmin = require('jsmin').jsmin; 19 | var jsonschema = require('jsonschema'); 20 | var schema = require('../../schema.json'); 21 | var validator = new jsonschema.Validator(); 22 | 23 | if (schema.definitions) { 24 | for (var key in schema.definitions) { 25 | if (schema.definitions.hasOwnProperty(key)) { 26 | validator.addSchema(schema.definitions[key], '/definitions/' + key); 27 | } 28 | } 29 | } 30 | 31 | delete schema.definitions; 32 | 33 | roto.defineTask('csxs.config_load', function(callback, options, target, globalOptions){ 34 | var path_config = globalOptions.config || 'csxs.json'; 35 | 36 | /** 37 | * Reads and parses "csxs.json". 38 | * 39 | * @param {function} callback 40 | */ 41 | var read = function(callback) { 42 | var data; 43 | var path_config_resolved = path.resolve(process.cwd(), path_config); 44 | if (!fs.existsSync(path_config_resolved)) return callback('File not found.'); 45 | try { data = JSON.parse(jsmin(fs.readFileSync(path_config_resolved, 'utf8'))); } 46 | catch (e) { console.dir(e.toString()); return callback('Unable to parse JSON.'); } 47 | 48 | data.basename = data.basename || data.id; 49 | data.filename = data.filename || data.basename; 50 | callback(null, data); 51 | }; 52 | 53 | /** 54 | * Validates configuration. 55 | * 56 | * @param {object} data 57 | * @returns {object} 58 | */ 59 | var validate = function(data, callback) { 60 | if (!data) return 'Configuration empty (' + path_config + ').'; 61 | process.stdout.write('Validating ' + path_config + '...'); 62 | 63 | var message, i, n; 64 | var result = validator.validate(data, schema); 65 | var err = result.errors; 66 | 67 | if (err.length) process.stdout.write('\n'); 68 | for (i = 0, n = err.length; i < n; i++) { 69 | if (err[i].validator === 'definitions') continue; 70 | 71 | if (err[i].schema.description) { 72 | message = '"' + err[i].property + '" ' + err[i].schema.description; 73 | } else { 74 | message = err[i].stack; 75 | } 76 | 77 | message = message.replace('instance.', ''); 78 | console.error(roto.colorize('ERROR: ', 'red') + message); 79 | } 80 | 81 | if (!err.length) { 82 | console.log(' [' + roto.colorize('success', 'green') + ']'); 83 | } 84 | return !err.length; 85 | }; 86 | 87 | if (config) return callback(); 88 | console.log('Reading project configuration...'); 89 | read(function(err, data) { 90 | if (err) { 91 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to read "' + path_config + '" (' + err + ').'); 92 | return callback(false); 93 | } 94 | if (!validate(data)) { 95 | return callback(false); 96 | } else { 97 | config = data; 98 | callback(); 99 | } 100 | }); 101 | }); -------------------------------------------------------------------------------- /src/tasks/fdb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var fs = require('fs'); 17 | var path = require('path'); 18 | var spawn = require('child_process').spawn; 19 | 20 | /** 21 | * Options: 22 | * - ver_flex 23 | */ 24 | 25 | roto.defineTask('csxs.fdb', function(callback, options) { 26 | var fdb, paused, running, args; 27 | var ver_flex = options.ver_flex; 28 | var folder_flex = process.env.CSSDK + '/CS Flex SDK ' + ver_flex; 29 | var path_fdb = path.normalize(folder_flex + '/lib/fdb.jar'); 30 | 31 | if (!fs.existsSync(path_fdb)) { 32 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to find "' + path_fdb + '".'); 33 | return callback(false); 34 | } 35 | 36 | paused = false; 37 | running = false; 38 | args = ['-jar', '-Dtrace.error=true', path_fdb]; 39 | console.log(roto.colorize('java ' + args.join(' '), 'magenta')); 40 | 41 | fdb = spawn('java', args); 42 | fdb.stdout.on('data', function (data) { 43 | if (/type 'continue'/.test(data)) { 44 | paused = true; 45 | } 46 | if (/\(fdb\)/.test(data)) { 47 | if (running && paused) { 48 | console.log(roto.colorize('(fdb) continue', 'gray')); 49 | fdb.stdin.write('continue\n'); 50 | paused = false; 51 | } else if (!running) { 52 | console.log(roto.colorize('(fdb) run', 'gray')); 53 | fdb.stdin.write('run\n'); 54 | running = true; 55 | } 56 | } else { 57 | console.log(data); 58 | } 59 | }); 60 | 61 | fdb.stderr.on('data', function (data) { 62 | console.error(data); 63 | }); 64 | 65 | fdb.on('exit', function(code) { 66 | callback(); 67 | }); 68 | }); -------------------------------------------------------------------------------- /src/tasks/fs.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var fs = require('fs'); 17 | var spawn = require('child_process').spawn; 18 | 19 | var task_symlink = function(callback, options) { 20 | var args = ['-s', options.from, options.to]; 21 | console.log(roto.colorize('ln ' + args.join(' '), 'magenta')); 22 | var ln = spawn('ln', args); 23 | ln.on('exit', function() { callback(); }); 24 | }; 25 | 26 | var task_copy = function(callback, options) { 27 | if (!fs.existsSync(options.from)) { 28 | console.error(roto.colorize('ERROR: ', 'red') + 'File not found "' + options.from + '".'); 29 | return callback(false); 30 | } 31 | var content = fs.readFileSync(options.from, 'binary'); 32 | fs.writeFileSync(options.to, content, 'binary'); 33 | callback(); 34 | }; 35 | 36 | roto.defineTask('csxs.fs_copy', task_copy); 37 | roto.defineTask('csxs.fs_symlink', IS_WINDOWS ? task_copy : task_symlink); -------------------------------------------------------------------------------- /src/tasks/git.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var spawn = require('child_process').spawn; 17 | var git = require('../lib/git.js'); 18 | 19 | 20 | roto.defineTask('csxs.git_tag', function(callback, options) { 21 | git.status(function(status) { 22 | if (!status) return callback(); 23 | 24 | var args = ['tag', '--force', options.name]; 25 | console.log(roto.colorize('git ' + args.join(' '), 'magenta')); 26 | var git = spawn('git', args); 27 | git.on('exit', function(code) { callback(); }); 28 | }); 29 | }); 30 | 31 | 32 | roto.defineTask('csxs.git_push_tags', function(callback) { 33 | git.status(function(status) { 34 | if (!status) return callback(); 35 | 36 | var args = ['push', 'origin', '--tags']; 37 | console.log(roto.colorize('git ' + args.join(' '), 'magenta')); 38 | var git = spawn('git', args); 39 | git.on('exit', function(code) { callback(); }); 40 | }); 41 | }); 42 | 43 | 44 | roto.defineTask('csxs.git_is_clean', function(callback) { 45 | git.status(function(status) { 46 | if (!status || status.clean) { 47 | callback(); 48 | } else { 49 | roto.error(roto.colorize('ERROR:', 'red') + ' You must commit modified files before issuing a public release.\n'); 50 | callback(false); 51 | } 52 | }); 53 | }); -------------------------------------------------------------------------------- /src/tasks/ucf.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013 Creative Market 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this 5 | * file except in compliance with the License. You may obtain a copy of the License at: 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under 9 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF 10 | * ANY KIND, either express or implied. See the License for the specific language 11 | * governing permissions and limitations under the License. 12 | * 13 | * @author Brian Reavis 14 | */ 15 | 16 | var fs = require('fs'); 17 | var os = require('os'); 18 | var spawn = require('child_process').spawn; 19 | var path = require('path'); 20 | 21 | 22 | roto.defineTask('csxs.ucf', function(callback, options) { 23 | var ucf, args, err; 24 | var path_tmp = (os.tmpdir || os.tmpDir)(); 25 | var path_project = process.cwd(); 26 | var path_output = path.normalize(path_tmp + '/' + path.basename(options.output)); 27 | var path_input = options.input; 28 | 29 | args = [ 30 | '-jar', 31 | path.resolve(__dirname, '../../bin/ucf.jar'), 32 | '-package', 33 | '-storetype', 'PKCS12', 34 | '-keystore', options.keystore, 35 | '-storepass', options.password, 36 | '-tsa', 'https://timestamp.geotrust.com/tsa', 37 | path_output, 38 | '-C', path_input, '.' 39 | ]; 40 | 41 | console.log(roto.colorize(options.output, 'white')); 42 | console.log(roto.colorize('java ' + args.join(' '), 'magenta')); 43 | 44 | ucf = spawn('java', args); 45 | ucf.stdout.on('data', function (data) { process.stdout.write(data); }); 46 | ucf.stderr.on('data', function (data) { process.stderr.write(data); err = true; }); 47 | ucf.on('exit', function(code) { 48 | if (err) { 49 | console.error(roto.colorize('ERROR: ', 'red') + 'Unable to create ZXP package.'); 50 | callback(false); 51 | } else { 52 | fs.renameSync(path_output, path.normalize(path_project + '/' + options.output)); 53 | callback(); 54 | } 55 | }); 56 | }); --------------------------------------------------------------------------------