├── app
├── templates
│ ├── app
│ │ ├── _index.js
│ │ ├── _main.css
│ │ ├── _index.html
│ │ └── _package.json
│ ├── gitignore
│ ├── linux
│ │ ├── description-pak
│ │ ├── run.sh
│ │ ├── amd64
│ │ │ └── libudev.so.0.6.1
│ │ ├── i386
│ │ │ └── libudev.so.0.6.1
│ │ ├── application.desktop
│ │ ├── install.sh
│ │ ├── debPackage.sh
│ │ └── rpmPackage.sh
│ ├── travis.yml
│ ├── _bower.json
│ ├── mac
│ │ ├── icon.icns
│ │ ├── background.png
│ │ ├── package.sh
│ │ ├── dmgStyler.applescript
│ │ └── _Info.plist.tmp
│ ├── editorconfig
│ ├── jshintrc
│ ├── _package.json
│ └── _Gruntfile.js
├── examples.js
└── index.js
├── .gitattributes
├── .travis.yml
├── .coveralls.yml
├── .gitignore
├── download
├── templates
│ └── _.yo-rc.json
└── index.js
├── .editorconfig
├── test
├── test-load.js
├── prompt.js
├── test-creation.js
└── prompt-github.js
├── .jshintrc
├── LICENSE
├── package.json
└── README.md
/app/templates/app/_index.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/templates/app/_main.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.10'
4 |
--------------------------------------------------------------------------------
/app/templates/gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | tmp/
3 | .DS_Store
--------------------------------------------------------------------------------
/.coveralls.yml:
--------------------------------------------------------------------------------
1 | repo_token: wgdUspAL7gRfktqDqUl1g4bEHXh3X7jsT
2 |
--------------------------------------------------------------------------------
/app/templates/linux/description-pak:
--------------------------------------------------------------------------------
1 | Communication and Collaboration tool
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules/
3 | temp/
4 | .DS_Store
5 | dist/
6 | test/tmp
7 |
--------------------------------------------------------------------------------
/app/templates/travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.8'
4 | - '0.10'
5 |
--------------------------------------------------------------------------------
/download/templates/_.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "nodeWebkitVersion": "<%= nodeWebkitVersion %>"
3 | }
4 |
--------------------------------------------------------------------------------
/app/templates/linux/run.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | /usr/lib/quickquestion/node-webkit /usr/lib/quickquestion/app.nw
--------------------------------------------------------------------------------
/app/templates/_bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "package",
3 | "version": "0.0.0",
4 | "dependencies": {}
5 | }
6 |
7 |
--------------------------------------------------------------------------------
/app/templates/mac/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dica-Developer/generator-node-webkit/HEAD/app/templates/mac/icon.icns
--------------------------------------------------------------------------------
/app/templates/mac/background.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dica-Developer/generator-node-webkit/HEAD/app/templates/mac/background.png
--------------------------------------------------------------------------------
/app/templates/linux/amd64/libudev.so.0.6.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dica-Developer/generator-node-webkit/HEAD/app/templates/linux/amd64/libudev.so.0.6.1
--------------------------------------------------------------------------------
/app/templates/linux/i386/libudev.so.0.6.1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Dica-Developer/generator-node-webkit/HEAD/app/templates/linux/i386/libudev.so.0.6.1
--------------------------------------------------------------------------------
/app/templates/app/_index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | <%= appName %>
5 |
6 |
7 | <%= appName %>
8 | <%= appDescription %>
9 |
10 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 4
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/app/templates/editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 4
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/test/test-load.js:
--------------------------------------------------------------------------------
1 | /*global describe, beforeEach, it*/
2 | 'use strict';
3 |
4 | var assert = require('assert');
5 |
6 | describe('node-webkit generator', function () {
7 | it('can be imported without blowing up', function () {
8 | var app = require('../app');
9 | assert(app !== undefined);
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/app/templates/linux/application.desktop:
--------------------------------------------------------------------------------
1 | [Desktop Entry]
2 | Name=Quick Question
3 | GenericName=Communication and Collaboration tool
4 | Comment=Communication and Collaboration tool
5 | Exec=qq
6 | Icon=quickquestion
7 | Terminal=false
8 | Type=Application
9 | StartupNotify=true
10 | Categories=Tool;
11 | X-Ubuntu-Gettext-Domain=tuxtype
12 |
--------------------------------------------------------------------------------
/app/templates/linux/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | mkdir /usr/lib/quickquestion
4 | cp -r dist/app.nw /usr/lib/quickquestion/
5 | cp dist/nw.pak /usr/lib/quickquestion/
6 | cp dist/node-webkit /usr/lib/quickquestion/
7 | cp dist/qq /usr/bin/
8 |
9 | cp resources/linux/quick-question.desktop /usr/share/applications/
10 | cp resources/icons/QQ_Colored.svg /usr/share/pixmaps/
11 |
12 |
--------------------------------------------------------------------------------
/app/templates/app/_package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "<%= appName %>",
3 | "main": "views/index.html",
4 | "version": "0.0.1",
5 | "single-instance": true,
6 | "window": {
7 | "title": "<%= appName %>",
8 | "width": 650,
9 | "height": 650,
10 | "min_width": 650,
11 | "min_height": 650,
12 | "toolbar": false
13 | },
14 | "chromium-args": "--child-clean-exit"
15 | }
16 |
--------------------------------------------------------------------------------
/app/templates/linux/debPackage.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cp -f resources/linux/description-pak ./
4 | checkinstall -y --install=no --fstrans=yes -D --pkgname QuickQuestion --pkgrelease 1 --reset-uids --deldoc --delspec \
5 | --deldesc --maintainer dica-developer@mascha.me --pkgversion $1 --pkgarch amd64 --showinstall=no \
6 | --pkgsource http://dica-developer.github.io/quickQuestion/ --pkglicense GPLv3 --pkggroup Tool resources/linux/install.sh
7 | rm description-pak
8 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "curly": true,
7 | "eqeqeq": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "regexp": true,
15 | "undef": true,
16 | "unused": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "white": true
21 | }
22 |
--------------------------------------------------------------------------------
/app/templates/jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "curly": true,
7 | "eqeqeq": true,
8 | "immed": true,
9 | "indent": 4,
10 | "latedef": true,
11 | "newcap": true,
12 | "noarg": true,
13 | "quotmark": "single",
14 | "regexp": true,
15 | "undef": true,
16 | "unused": true,
17 | "strict": true,
18 | "trailing": true,
19 | "smarttabs": true,
20 | "white": true
21 | }
22 |
--------------------------------------------------------------------------------
/app/templates/linux/rpmPackage.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cp -f resources/linux/description-pak ./
4 | mkdir -p ./SOURCES
5 | tar -cz app/ > ./SOURCES/QuickQuestion-$1.tgz
6 | checkinstall -y --install=no --fstrans=yes -R --pkgname QuickQuestion --pkgrelease 1 --reset-uids --deldoc --delspec \
7 | --deldesc --maintainer dica-developer@mascha.me --pkgversion $1 --pkgarch amd64 --showinstall=no \
8 | --pkgsource http://dica-developer.github.io/quickQuestion/ --pkglicense GPLv3 --pkggroup Tool resources/linux/install.sh
9 | mv ~/rpmbuild/RPMS/amd64/QuickQuestion-$1-1.amd64.rpm ./
10 | rm -r ./SOURCES
11 | rm description-pak
12 |
--------------------------------------------------------------------------------
/app/templates/mac/package.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | hdiutil create -srcfolder "dist/macOS/$1.app" -volname "$1" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW dist/macOS/$1.tmp.dmg
4 | hdiutil attach -readwrite -noverify -noautoopen "dist/macOS/$1.tmp.dmg"
5 | mkdir /Volumes/$1/.background
6 | cp resources/mac/background.png /Volumes/$1/.background
7 | chmod -Rf go-w /Volumes/$1
8 | ln -sfn /Applications/ /Volumes/$1/Applications
9 | export APP_NAME=$1
10 | osascript resources/mac/dmgStyler.applescript
11 | hdiutil detach /Volumes/$1
12 | hdiutil convert "dist/macOS/$1.tmp.dmg" -format UDZO -imagekey zlib-level=9 -o "dist/macOS/$1.dmg" -puppetstrings
13 | rm dist/macOS/$1.tmp.dmg
--------------------------------------------------------------------------------
/app/templates/_package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "<%= appName %>",
3 | "version": "0.0.0",
4 | "description": "<%= description %>",
5 | "keywords": [],
6 | <% if(github) {%>
7 | "homepage": "<%= githubUrl %>/<%= appName %>",
8 | "bugs": "<%= githubUrl %>/<%= appName %>/issues",
9 | "author": {
10 | "name": "<%= realname %>",
11 | "email": "",
12 | "url": "<%= githubUrl %>"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "git://github.com/<%= githubUser %>/<%= appName %>.git"
17 | },
18 | <% } %>
19 | "dependencies": {},
20 | "devDependencies": {
21 | "grunt": "~0.4.5",
22 | "grunt-contrib-concat": "~0.5.0",
23 | "grunt-contrib-jshint": "~0.10.0",
24 | "grunt-contrib-rename": "0.0.3",
25 | "grunt-contrib-compress": "^0.10.0",
26 | "grunt-contrib-clean": "~0.6.0",
27 | "grunt-contrib-copy": "~0.5.0",
28 | "load-grunt-tasks": "^0.6.0",
29 | "time-grunt": "^0.4.0",
30 | "concat-files": "~0.1.0"
31 | },
32 | "engines": {
33 | "node": ">=0.8.0"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2013
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/app/templates/mac/dmgStyler.applescript:
--------------------------------------------------------------------------------
1 | set appName to (system attribute "APP_NAME")
2 | tell application "Finder"
3 | tell disk appName
4 | open
5 | set current view of container window to icon view
6 | set toolbar visible of container window to false
7 | set statusbar visible of container window to false
8 | set the bounds of container window to {100, 100, 640, 250}
9 | set theViewOptions to the icon view options of container window
10 | set arrangement of theViewOptions to not arranged
11 | set icon size of theViewOptions to 64
12 | set background picture of theViewOptions to POSIX file ("/Volumes/" & appName & "/.background/background.png")
13 | set position of item (appName & ".app") of container window to {225, 40}
14 | set position of item "Applications" of container window to {375, 40}
15 | set position of item ".DS_Store" of container window to {400, 400}
16 | set position of item ".Trashes" of container window to {400, 400}
17 | set position of item ".fseventsd" of container window to {400, 400}
18 | set position of item ".background" of container window to {400, 400}
19 | update without registering applications
20 | close
21 | end tell
22 | end tell
23 |
--------------------------------------------------------------------------------
/app/templates/mac/_Info.plist.tmp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | <%= appName %>
9 | CFBundleExecutable
10 | <%%= nwExecutableName %>
11 | <% if(github) {%>
12 | CFBundleGetInfoString
13 | © <%= realname %>, 2013
14 | <% } %>
15 | CFBundleIconFile
16 | nw.icns
17 | CFBundleInfoDictionaryVersion
18 | 6.0
19 | CFBundleName
20 | <%= appName %>
21 | LSApplicationCategoryType
22 | public.app-category.productivity
23 | CFBundlePackageType
24 | APPL
25 | CFBundleShortVersionString
26 | <%%= version %>
27 | CFBundleVersion
28 | <%%= version %>
29 | LSFileQuarantineEnabled
30 |
31 | LSMinimumSystemVersion
32 | 10.6.0
33 | NSPrincipalClass
34 | NSApplication
35 | NSSupportsAutomaticGraphicsSwitching
36 |
37 | SCMRevision
38 | 175484
39 |
40 |
41 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "generator-node-webkit",
3 | "version": "1.0.4",
4 | "description": "A generator for node-webkit",
5 | "keywords": [
6 | "yeoman-generator",
7 | "node-webkit"
8 | ],
9 | "homepage": "https://github.com/Dica-Developer/generator-node-webkit",
10 | "bugs": "https://github.com/Dica-Developer/generator-node-webkit/issues",
11 | "author": {
12 | "name": "Dica-Developer",
13 | "email": "",
14 | "url": "https://github.com/Dica-Developer"
15 | },
16 | "main": "app/index.js",
17 | "repository": {
18 | "type": "git",
19 | "url": "git://github.com/Dica-Developer/generator-node-webkit.git"
20 | },
21 | "scripts": {
22 | "test": "mocha test -R mocha-lcov-reporter | coveralls"
23 | },
24 | "dependencies": {
25 | "decompress-zip": "^0.1.0",
26 | "follow-redirects": "^0.0.3",
27 | "fs-extra": "^0.16.3",
28 | "github": "^0.2.3",
29 | "html-wiring": "^1.1.0",
30 | "lodash": "^3.8.0",
31 | "request": "^2.53.0",
32 | "tar-fs": "^1.4.2",
33 | "temp": ">=0.8.1",
34 | "when": "^3.7.2",
35 | "yeoman-generator": "~0.19.0",
36 | "yeoman-welcome": "~1.0.1"
37 | },
38 | "devDependencies": {
39 | "chai": "^1.10.0",
40 | "coveralls": ">=2.11.2",
41 | "mocha": "^2.1.0",
42 | "mocha-lcov-reporter": ">=0.0.1",
43 | "temp": ">=0.8.1"
44 | },
45 | "peerDependencies": {
46 | "yo": ">=1.0.0"
47 | },
48 | "engines": {
49 | "node": ">=0.10.0",
50 | "npm": ">=1.2.10"
51 | },
52 | "license": "MIT"
53 | }
54 |
--------------------------------------------------------------------------------
/test/prompt.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var helpers = require('yeoman-generator').test;
3 | var expect = require('chai').expect;
4 |
5 | describe('Test prompt validations', function () {
6 |
7 | var app,
8 | deps = [
9 | [helpers.createDummyGenerator(), 'node-webkit:download']
10 | ];
11 |
12 | beforeEach(function () {
13 | app = helpers.run(path.join(__dirname, '../app'))
14 | .inDir(path.join(__dirname, './tmp'))
15 | .withOptions({ 'skip-install': true, 'skip-welcome-message': true })
16 | .withGenerators(deps);
17 | });
18 |
19 | it('App name has invalid character and should fail', function (done) {
20 |
21 | app
22 | .withPrompts({
23 | 'appName': 'Test App',
24 | 'appDescription': 'Test App Description',
25 | 'githubUser': 'someuser'
26 | })
27 | .on('end', function () {
28 | expect(app.generator.prompt.errors).not.to.be.an('undefined');
29 | expect(app.generator.prompt.errors).to.have.length(1);
30 | expect(app.generator.prompt.errors).to.have.deep.property('[0].name', 'appName');
31 | expect(app.generator.prompt.errors).to.have.deep.property('[0].message', 'The application name should only consist of the following characters a-z, A-Z and 0-9.');
32 | done();
33 | });
34 | });
35 |
36 | it('App name has valid character and should not fail', function (done) {
37 |
38 | app
39 | .withPrompts({
40 | 'appName': 'TestApp',
41 | 'appDescription': 'Test App Description',
42 | 'githubUser': 'someuser'
43 | })
44 | .on('end', function () {
45 | expect(app.generator.prompt.errors).to.be.an('undefined');
46 | done();
47 | });
48 | });
49 | });
--------------------------------------------------------------------------------
/test/test-creation.js:
--------------------------------------------------------------------------------
1 | /*global describe, beforeEach, it, after*/
2 | 'use strict';
3 |
4 | var path = require('path');
5 | var helpers = require('yeoman-generator').test;
6 | var expect = require('chai').expect;
7 |
8 | describe('Test file creation', function () {
9 | var app,
10 | deps = [
11 | [helpers.createDummyGenerator(), 'node-webkit:download']
12 | ];
13 |
14 | beforeEach(function () {
15 | app = helpers.run(path.join(__dirname, '../app'))
16 | .inDir(path.join(__dirname, './tmp'))
17 | .withOptions({ 'skip-install': true, 'skip-welcome-message': true })
18 | .withGenerators(deps)
19 | .withPrompts({
20 | 'appName': 'TestApp',
21 | 'appDescription': 'Test App Description',
22 | 'githubUser': 'someuser'
23 | });
24 | });
25 |
26 | it('Creates dot files', function (done) {
27 | var expected = [
28 | '.jshintrc',
29 | '.editorconfig',
30 | '.gitignore'
31 | ];
32 |
33 | app.on('end', function () {
34 | expect(app.generator.prompt.errors).to.be.an('undefined');
35 | helpers.assertFile(expected);
36 | done();
37 | });
38 | });
39 |
40 | it('Creates main package files', function (done) {
41 | var expected = [
42 | // add files you expect to exist here.
43 | 'Gruntfile.js',
44 | 'package.json',
45 | 'bower.json'
46 | ];
47 |
48 | app.on('end', function () {
49 | expect(app.generator.prompt.errors).to.be.an('undefined');
50 | helpers.assertFile(expected);
51 | done();
52 | });
53 | });
54 |
55 | it('Creates app files', function (done) {
56 | var expected = [
57 | 'app/css/main.css',
58 | 'app/js/index.js',
59 | 'app/package.json',
60 | 'app/views/index.html'
61 | ];
62 |
63 | app.on('end', function () {
64 | expect(app.generator.prompt.errors).to.be.an('undefined');
65 | helpers.assertFile(expected);
66 | done();
67 | });
68 | });
69 |
70 | it('Creates resource files', function (done) {
71 | var expected = [
72 | 'resources/mac/dmgStyler.applescript',
73 | 'resources/mac/package.sh',
74 | 'resources/mac/background.png',
75 | 'resources/mac/Info.plist.tmp',
76 | 'resources/mac/Info.plist'
77 | ];
78 |
79 | app.on('end', function () {
80 | expect(app.generator.prompt.errors).to.be.an('undefined');
81 | helpers.assertFile(expected);
82 | done();
83 | });
84 | });
85 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # generator-node-webkit
2 |
3 | [](https://gitter.im/Dica-Developer/generator-node-webkit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4 | [](https://travis-ci.org/Dica-Developer/generator-node-webkit)
5 | [](https://david-dm.org/Dica-Developer/generator-node-webkit)
6 | [](https://david-dm.org/Dica-Developer/generator-node-webkit#info=devDependencies)
7 | [](http://badge.fury.io/js/generator-node-webkit)
8 | [](https://coveralls.io/r/Dica-Developer/generator-node-webkit)
9 | [](https://www.npmjs.org/package/generator-node-webkit)
10 | [](https://www.npmjs.org/package/generator-node-webkit)
11 | [](http://en.wikipedia.org/wiki/MIT_License)
12 | [](https://github.com/Dica-Developer/generator-node-webkit/issues)
13 | [](https://waffle.io/dica-developer/generator-node-webkit)
14 |
15 | Required software:
16 |
17 | [Node.js](http://nodejs.org/ "nodejs")
18 |
19 | [Yeoman](http://yeoman.io/ "Yeoman")
20 |
21 |
22 | To install generator-node-webkit from npm, run:
23 |
24 | ```
25 | $ npm install -g generator-node-webkit
26 | ```
27 |
28 | Finally, initiate the generator:
29 |
30 | ```
31 | $ yo node-webkit
32 | ```
33 |
34 |
35 | For further informations, please visit our [Wiki](https://github.com/Dica-Developer/generator-node-webkit/wiki "Wiki")
36 |
37 | ## We would like to thank
38 |
39 | [Jim Buck](https://github.com/JimmyBoh "JimmyBoh")
40 |
41 | [Andy Matthews](https://github.com/commadelimited "commadelimited")
42 |
43 | [Zack Lalanne](https://github.com/zlalanne "zlalanne")
44 |
45 | for helping to make it easy to develop cross platform apps.
46 |
47 |
48 | ## License
49 |
50 | [MIT License](http://en.wikipedia.org/wiki/MIT_License)
51 |
--------------------------------------------------------------------------------
/app/examples.js:
--------------------------------------------------------------------------------
1 | var when = require('when');
2 | var GitHubApi = require('github');
3 | var request = require('request');
4 | var fs = require('fs-extra');
5 | var DecompressZip = require('decompress-zip');
6 | var url = require('url');
7 |
8 | var proxy = process.env.http_proxy || process.env.HTTP_PROXY || process.env.https_proxy || process.env.HTTPS_PROXY || null;
9 | var githubOptions = {
10 | version: '3.0.0'
11 | };
12 |
13 | if (proxy) {
14 | githubOptions.proxy = {};
15 | githubOptions.proxy.host = url.parse(proxy).hostname;
16 | githubOptions.proxy.port = url.parse(proxy).port;
17 | }
18 |
19 | var github = new GitHubApi(githubOptions);
20 |
21 | function Examples(yeoman) {
22 | this.yeoman = yeoman;
23 | this.entries = [];
24 | }
25 |
26 | Examples.prototype.getExamplesOverview = function () {
27 | var defer = when.defer();
28 | github.gitdata.getTree({
29 | 'user': 'zcbenz',
30 | 'repo': 'nw-sample-apps',
31 | 'sha': 'master'
32 | },
33 | function (err, resp) {
34 | defer.resolve(resp);
35 | }
36 | );
37 | return defer.promise;
38 | };
39 |
40 | Examples.prototype.getExampleList = function () {
41 | var _this = this;
42 | var defer = when.defer();
43 | this.getExamplesOverview()
44 | .then(function (resp) {
45 | var list = [];
46 | resp.tree.forEach(function (treeEntry) {
47 | if ('tree' === treeEntry.type) {
48 | list.push(treeEntry.path);
49 | _this.entries.push(treeEntry);
50 | }
51 | });
52 | defer.resolve(list);
53 | });
54 | return defer.promise;
55 | };
56 |
57 | Examples.prototype.downloadAndInstallExamples = function downloadAndInstallExamples(example) {
58 | this.example = example;
59 | var defer = when.defer();
60 |
61 | this.downloadExamples()
62 | .then(this.unzipExamples.bind(this))
63 | .then(this.installExamples.bind(this))
64 | .then(function () {
65 | defer.resolve();
66 | });
67 |
68 | return defer.promise;
69 | };
70 |
71 | Examples.prototype.downloadExamples = function downloadExamples() {
72 | var defer = when.defer();
73 | var _this = this;
74 | if (!fs.existsSync('tmp/node-webkit-examples.zip')) {
75 | this.yeoman.log.info('Downloading node-webkit examples');
76 |
77 | var writeStream = fs.createWriteStream('tmp/node-webkit-examples.zip');
78 | var req = request('https://github.com/zcbenz/nw-sample-apps/archive/master.zip')
79 | .pipe(writeStream);
80 | req.on('error', function (err) {
81 | _this.yeoman.log.conflict(err);
82 | });
83 | writeStream.on('finish', function () {
84 | defer.resolve();
85 | });
86 |
87 | } else {
88 | this.yeoman.log.ok('Node-webkit examples already downloaded');
89 | defer.resolve();
90 | }
91 | return defer.promise;
92 | };
93 |
94 | Examples.prototype.unzipExamples = function unzipExamples() {
95 | var defer = when.defer();
96 | var _this = this;
97 | if (fs.existsSync('tmp/node-webkit-examples.zip')) {
98 | this.yeoman.log.info('Unzip examples.');
99 | var unzipper = new DecompressZip('tmp/node-webkit-examples.zip');
100 |
101 | unzipper.on('error', function (error) {
102 | _this.yeoman.log.conflict('Error while unzipping "tmp/node-webkit-examples.zip"', error);
103 | defer.reject(error);
104 | });
105 |
106 | unzipper.on('extract', function () {
107 | _this.yeoman.log.ok('Examples successfully unzipped');
108 | defer.resolve();
109 | });
110 |
111 | unzipper.extract({
112 | path: 'tmp'
113 | });
114 | } else {
115 | defer.resolve();
116 | }
117 | return defer.promise;
118 | };
119 |
120 | Examples.prototype.installExamples = function installExamples() {
121 | var _this = this;
122 | var defer = when.defer();
123 | fs.copy('tmp/nw-sample-apps-master/' + this.example, 'app', function (err) {
124 | if (err) {
125 | _this.yeoman.log.conflict('Error while copying example', err);
126 | defer.reject(err);
127 | }
128 | defer.resolve();
129 | });
130 | return defer.promise;
131 | };
132 |
133 | module.exports = Examples;
134 |
--------------------------------------------------------------------------------
/test/prompt-github.js:
--------------------------------------------------------------------------------
1 | /*global describe, beforeEach, it, after*/
2 | 'use strict';
3 |
4 | var path = require('path');
5 | var helpers = require('yeoman-generator').test;
6 | var assert = require('yeoman-generator').assert;
7 | var fs = require('fs-extra');
8 |
9 | describe('Test github prompt', function () {
10 | var app,
11 | deps = [
12 | [helpers.createDummyGenerator(), 'node-webkit:download']
13 | ];
14 |
15 | beforeEach(function () {
16 | app = helpers.run(path.join(__dirname, '../app'))
17 | .inDir(path.join(__dirname, './tmp'))
18 | .withOptions({ 'skip-install': true, 'skip-welcome-message': true })
19 | .withGenerators(deps);
20 | });
21 |
22 | it('Should retrieve github information for given name if user exists', function (done) {
23 | app
24 | .withPrompts({
25 | 'appName': 'TestApp',
26 | 'appDescription': 'Test App Description',
27 | 'githubUser': 'JayGray'
28 | })
29 | .on('end', function () {
30 | assert.ok(typeof app.generator.prompt.errors === 'undefined', 'This should fail if the app name contains a space.');
31 | assert.ok(app.generator.github, 'This should fail if app.github is set to false.');
32 | assert.ok(app.generator.githubUser === 'JayGray', 'This should fail if app.githubUser is not "JayGray".');
33 | assert.ok(app.generator.realname === 'Jörg Weber', 'This should fail if the app.realname is not "Jörg Weber".');
34 | assert.ok(app.generator.githubUrl === 'https://github.com/JayGray', 'This should fail if the app.githubUrl is not "https://github.com/JayGray".');
35 | done();
36 | });
37 |
38 | });
39 |
40 | it('Should skip retrieving github information if given name is default', function (done) {
41 | app
42 | .withPrompts({
43 | 'appName': 'TestApp',
44 | 'appDescription': 'Test App Description',
45 | 'githubUser': 'someuser'
46 | })
47 | .on('end', function () {
48 | assert.ok(typeof app.generator.prompt.errors === 'undefined', 'This should fail if the app name contains a space.');
49 | assert.strictEqual(app.generator.github, false, 'This should fail if app.github is set to false.');
50 | assert.strictEqual(app.generator.github, false, 'This should fail if app.github is set to false.');
51 | assert.strictEqual(app.generator.githubUser, 'someuser', 'This should fail if app.githubUser is not "someuser".');
52 | assert.strictEqual(app.generator.realname, void 0, 'This should fail if the app.realname is not "undefined".');
53 | assert.strictEqual(app.generator.githubUrl, void 0, 'This should fail if the app.githubUrl is not "undefined".');
54 | done();
55 | });
56 | });
57 |
58 | it('Should set app.github to false if given name is not known by github', function (done) {
59 | app
60 | .withPrompts({
61 | 'appName': 'TestApp',
62 | 'appDescription': 'Test App Description',
63 | 'githubUser': 'HopefullyNotExistingUser',
64 | downloadNodeWebkit: false,
65 | 'platforms': ['Linux64']
66 | })
67 | .on('end', function () {
68 | assert.ok(typeof app.generator.prompt.errors === 'undefined', 'This should fail if the app name contains a space.');
69 | assert.strictEqual(app.generator.github, false, 'This should fail if app.github is set to true.');
70 | assert.strictEqual(app.generator.githubUser, 'HopefullyNotExistingUser', 'This should fail if app.githubUser is not "HopefullyNotExistingUser".');
71 | assert.strictEqual(app.generator.realname, void 0, 'This should fail if the app.realname is not "undefined".');
72 | assert.strictEqual(app.generator.githubUrl, void 0, 'This should fail if the app.githubUrl is not "undefined".');
73 | done();
74 | });
75 | });
76 |
77 | it('Should write retrieved github informations correct in package.json', function (done) {
78 | app
79 | .withPrompts({
80 | 'appName': 'TestApp',
81 | 'appDescription': 'Test App Description',
82 | 'githubUser': 'JayGray'
83 | })
84 | .on('end', function () {
85 | var packageJson = fs.readJsonFileSync('package.json');
86 | assert.equal(packageJson.author.name, 'Jörg Weber', 'Should fail if author name is not "Jörg Weber"');
87 | assert.equal(packageJson.author.url, 'https://github.com/JayGray', 'Should fail if author url is not "https://github.com/JayGray"');
88 | assert.equal(packageJson.homepage, 'https://github.com/JayGray/testapp', 'Should fail if homepage is not "https://github.com/JayGray/testapp"');
89 | assert.equal(packageJson.bugs, 'https://github.com/JayGray/testapp/issues', 'Should fail if bugs url is not "https://github.com/JayGray/testapp"');
90 | done();
91 | });
92 | });
93 |
94 | it('Should no entry in package.json if no github information are available', function (done) {
95 | app
96 | .withPrompts({
97 | 'appName': 'TestApp',
98 | 'appDescription': 'Test App Description',
99 | 'githubUser': 'someuser'
100 | })
101 | .on('end', function () {
102 | var packageJson = fs.readJsonFileSync('package.json');
103 | assert.equal(packageJson.author, void 0, 'Should fail if author name is not "undefined"');
104 | assert.equal(packageJson.homepage, void 0, 'Should fail if homepage is not "undefined"');
105 | assert.equal(packageJson.bugs, void 0, 'Should fail if bugs url is not "undefined"');
106 | done();
107 | });
108 | });
109 | });
--------------------------------------------------------------------------------
/app/index.js:
--------------------------------------------------------------------------------
1 | /*global require*/
2 | 'use strict';
3 |
4 | var util = require('util');
5 | var path = require('path');
6 | var yeoman = require('yeoman-generator');
7 | var url = require('url');
8 | var GitHubApi = require('github');
9 | var _ = require('lodash');
10 | var readFileAsString = require("html-wiring").readFileAsString;
11 | var welcomeMessage = require('yeoman-welcome');
12 |
13 | var Examples = require('./examples.js');
14 |
15 | var NodeWebkitGenerator = module.exports = function NodeWebkitGenerator(args, options) {
16 | yeoman.generators.Base.apply(this, arguments);
17 |
18 | this.on('end', function () {
19 | this.installDependencies({
20 | skipInstall: options['skip-install']
21 | });
22 | });
23 |
24 | this.pkg = JSON.parse(readFileAsString(path.join(__dirname, '../package.json')));
25 | this.github = false;
26 | };
27 |
28 | util.inherits(NodeWebkitGenerator, yeoman.generators.Base);
29 |
30 | NodeWebkitGenerator.prototype.welcome = function welcome() {
31 | if (!this.options['skip-welcome-message']) {
32 | this.log(welcomeMessage);
33 | }
34 | };
35 |
36 | NodeWebkitGenerator.prototype.askForAppName = function askForAppName() {
37 | var done = this.async();
38 | var basePath = path.basename(process.env.PWD);
39 | var appName = _.camelCase(basePath);
40 |
41 | var prompts = [{
42 | name: 'appName',
43 | message: 'What do you want to call your app? Allowed characters ^[a-zA-Z0-9]+$',
44 | default: appName,
45 | validate: function (answer) {
46 | if (!/^[a-zA-Z0-9]+$/.test(answer)) {
47 | return 'The application name should only consist of the following characters a-z, A-Z and 0-9.';
48 | }
49 | return true;
50 | }
51 | }];
52 |
53 | this.prompt(prompts, function (props) {
54 | this.appName = props.appName;
55 | done();
56 | }.bind(this));
57 |
58 | };
59 |
60 | NodeWebkitGenerator.prototype.askForDescription = function askForDescription() {
61 | var done = this.async();
62 | var prompts = [{
63 | name: 'appDescription',
64 | message: 'A little description for your app?'
65 | }];
66 |
67 | this.prompt(prompts, function (props) {
68 | this.appDescription = props.appDescription;
69 | done();
70 | }.bind(this));
71 |
72 | };
73 |
74 | NodeWebkitGenerator.prototype.askForGithubName = function askForGithubName() {
75 | var done = this.async();
76 | var prompts = [{
77 | name: 'githubUser',
78 | message: 'Would you mind telling me your username on GitHub?',
79 | default: 'someuser'
80 | }];
81 |
82 | this.prompt(prompts, function (props) {
83 | this.githubUser = props.githubUser;
84 | done();
85 | }.bind(this));
86 | };
87 |
88 | NodeWebkitGenerator.prototype.askForInstallExamples = function askForInstallExamples() {
89 | var done = this.async();
90 | var prompts = [{
91 | type: 'confirm',
92 | name: 'installExamples',
93 | message: 'Do you want to install one of the node-webkit examples?',
94 | default: false
95 | }];
96 | this.prompt(prompts, function (props) {
97 | this.installExamples = props.installExamples;
98 | done();
99 | }.bind(this));
100 |
101 | };
102 |
103 | NodeWebkitGenerator.prototype.getGithubUserInfo = function getGithubUserInfo() {
104 | var done = this.async();
105 | var _this = this;
106 | var responseClbk = function (err, responseText) {
107 | if (err) {
108 | _this.log.info('Error while fetching github user information.', err);
109 | _this.log.skip('Skip fetching github user information.');
110 | done();
111 | } else {
112 | var responseObject = JSON.parse(JSON.stringify(responseText));
113 | _this.log.ok('Github informations successfully retrieved.');
114 | _this.github = true;
115 | _this.realname = responseObject.name;
116 | _this.githubUrl = responseObject.html_url;
117 | done();
118 | }
119 | };
120 |
121 | if (this.githubUser !== 'someuser') {
122 | var proxy = process.env.http_proxy || process.env.HTTP_PROXY || process.env.https_proxy || process.env.HTTPS_PROXY || null;
123 | var githubOptions = {
124 | version: '3.0.0'
125 | };
126 |
127 | if (proxy) {
128 | githubOptions.proxy = {};
129 | githubOptions.proxy.host = url.parse(proxy).hostname;
130 | githubOptions.proxy.port = url.parse(proxy).port;
131 | }
132 |
133 | var github = new GitHubApi(githubOptions);
134 | this.log.info('Get GitHub informations');
135 | github.user.getFrom({
136 | user: this.githubUser
137 | }, responseClbk);
138 | } else {
139 | done();
140 | }
141 | };
142 |
143 | NodeWebkitGenerator.prototype.getExampleList = function getExampleList() {
144 | var done = this.async();
145 | if (this.installExamples) {
146 | var prompts = [{
147 | type: 'list',
148 | name: 'example',
149 | message: 'Which example do you want to install?',
150 | choices: []
151 | }];
152 |
153 | this.examplesAPI = new Examples(this);
154 | this.log.info('Getting list of available examples.');
155 | this.examplesAPI.getExampleList()
156 | .then(function (list) {
157 | prompts[0].choices = list;
158 |
159 | this.prompt(prompts, function (props) {
160 | this.example = props.example;
161 | done();
162 | }.bind(this));
163 | }.bind(this));
164 | } else {
165 | done();
166 | }
167 | };
168 |
169 | NodeWebkitGenerator.prototype.nodeWebkitSubgenerator = function createFolder() {
170 | var done = this.async();
171 | this.invoke("node-webkit:download", {}, function () {
172 | done();
173 | });
174 | };
175 |
176 | NodeWebkitGenerator.prototype.processProjectfiles = function processProjectfiles() {
177 | this.copy('editorconfig', '.editorconfig');
178 | this.copy('jshintrc', '.jshintrc');
179 | this.copy('gitignore', '.gitignore');
180 | this.copy('_bower.json', 'bower.json');
181 | this.copy('mac/dmgStyler.applescript', 'resources/mac/dmgStyler.applescript');
182 | this.copy('mac/package.sh', 'resources/mac/package.sh');
183 | this.copy('mac/background.png', 'resources/mac/background.png');
184 | this.template('_package.json', 'package.json');
185 | this.template('_Gruntfile.js', 'Gruntfile.js');
186 | this.template('mac/_Info.plist.tmp', 'resources/mac/Info.plist.tmp');
187 | };
188 |
189 | NodeWebkitGenerator.prototype.processAppFiles = function processAppFiles() {
190 | var done = this.async();
191 | if (this.installExamples) {
192 | this.examplesAPI.downloadAndInstallExamples(this.example)
193 | .then(function() {
194 | done();
195 | });
196 | } else {
197 | this.copy('app/_main.css', 'app/css/main.css');
198 | this.copy('app/_index.js', 'app/js/index.js');
199 | this.template('app/_package.json', 'app/package.json');
200 | this.template('app/_index.html', 'app/views/index.html');
201 | done();
202 | }
203 | };
204 |
--------------------------------------------------------------------------------
/download/index.js:
--------------------------------------------------------------------------------
1 | /*global require*/
2 | 'use strict';
3 |
4 | var yeoman = require('yeoman-generator');
5 | var when = require('when');
6 | var http = require('follow-redirects').http;
7 | var request = require('request');
8 | var fs = require('fs-extra');
9 | var DecompressZip = require('decompress-zip');
10 | var tar = require('tar-fs');
11 | var zlib = require('zlib');
12 |
13 | module.exports = yeoman.generators.Base.extend({
14 | constructor: function () {
15 | yeoman.generators.Base.apply(this, arguments);
16 | this.defaultNodeWebkitVersion = 'v0.12.0';
17 | this.nodeWebkitVersion = 'v0.12.0';
18 | this.downloadNodeWebkit = true;
19 | },
20 | _getDownloadUrl: function() {
21 | var namePart = '/nwjs-';
22 | if (this.nodeWebkitVersion.indexOf('v0.9.') !== -1 || this.nodeWebkitVersion.indexOf('v0.8.') !== -1 || this.nodeWebkitVersion.indexOf('v0.10.') !== -1 || this.nodeWebkitVersion.indexOf('v0.11.') !== -1) {
23 | namePart = '/node-webkit-';
24 | }
25 | return 'http://dl.nwjs.io/' + this.nodeWebkitVersion + namePart + this.nodeWebkitVersion + '-';
26 | },
27 | _getDownloadTmpUrl: function(version) {
28 | var namePart = '/nwjs-';
29 | if (version.indexOf('v0.9.') !== -1 || version.indexOf('v0.8.') !== -1 || version.indexOf('v0.10.') !== -1 || version.indexOf('v0.11.') !== -1) {
30 | namePart = '/node-webkit-';
31 | }
32 | return 'http://dl.nwjs.io/' + version + namePart + version + '-linux-x64.tar.gz';
33 | },
34 | askForInstallNodeWebkit: function askForInstallNodeWebkit() {
35 | var done = this.async();
36 | var prompts = [{
37 | type: 'confirm',
38 | name: 'downloadNodeWebkit',
39 | message: 'Do you want to download node-webkit?',
40 | default: true
41 | }];
42 | this.prompt(prompts, function (props) {
43 | this.downloadNodeWebkit = props.downloadNodeWebkit;
44 | done();
45 | }.bind(this));
46 |
47 | },
48 | askForVersion: function askForInstallLatesVersion() {
49 | var done = this.async(),
50 | _this = this;
51 | var prompts = [{
52 | type: 'input',
53 | name: 'nodeWebkitVersion',
54 | message: 'Please specify which version of node-webkit you want download',
55 | default: _this.defaultNodeWebkitVersion,
56 | when: function () {
57 | return _this.downloadNodeWebkit;
58 | },
59 | validate: function (answer) {
60 | var validateDone = this.async(),
61 | url = _this._getDownloadTmpUrl(answer);
62 |
63 | _this.log.info('Check if version "' + answer + '" is available for download.');
64 | request.head(url, function (error, response) {
65 | if (error) {
66 | _this.log.conflict(error);
67 | } else {
68 | if (response.statusCode === 200) {
69 | _this.log.ok('Use version "' + answer + '".');
70 | validateDone(true);
71 | } else {
72 | validateDone('No download url found for version "' + answer + '" (' + url + ')!');
73 | }
74 | }
75 | });
76 | }
77 | }];
78 |
79 | this.prompt(prompts, function (props) {
80 | this.nodeWebkitVersion = props.nodeWebkitVersion;
81 | this.template('_.yo-rc.json', '.yo-rc.json');
82 | done();
83 | }.bind(this));
84 | },
85 | askForPlatform: function askForPlatform() {
86 | var done = this.async(),
87 | _this = this,
88 | prompts = [{
89 | type: 'checkbox',
90 | name: 'platforms',
91 | message: 'Which platform do you wanna support?',
92 | choices: [{
93 | name: 'MacOS 32',
94 | checked: 'darwin' === process.platform
95 | }, {
96 | name: 'MacOS 64',
97 | checked: false
98 | }, {
99 | name: 'Linux 64',
100 | checked: 'linux' === process.platform
101 | }, {
102 | name: 'Linux 32',
103 | checked: false
104 | }, {
105 | name: 'Windows',
106 | checked: 'win32' === process.platform
107 | }],
108 | when: function () {
109 | return _this.downloadNodeWebkit;
110 | },
111 | validate: function (answer) {
112 | if (answer.length < 1) {
113 | return 'You must choose at least one platform.';
114 | }
115 | return true;
116 | }
117 | }];
118 |
119 | this.prompt(prompts, function (props) {
120 | _this.platforms = props.platforms;
121 | _this.MacOS32 = false;
122 | _this.MacOS64 = false;
123 | _this.Linux64 = false;
124 | _this.Windows = false;
125 | if (_this.downloadNodeWebkit) {
126 | _this.platforms.forEach(function (platform) {
127 | switch (platform) {
128 | case 'MacOS 32':
129 | _this.MacOS32 = true;
130 | break;
131 | case 'MacOS 64':
132 | _this.MacOS64 = true;
133 | break;
134 | case 'Linux 64':
135 | _this.Linux64 = true;
136 | break;
137 | case 'Linux 32':
138 | _this.Linux32 = true;
139 | break;
140 | case 'Windows':
141 | _this.Windows = true;
142 | break;
143 | }
144 | });
145 | }
146 | done();
147 | });
148 | },
149 | createFolder: function createFolder() {
150 | this.log.info('Creating folder structure for node-webkit source.');
151 | this.mkdir('resources/node-webkit');
152 | this.log.ok('Created: "resources/node-webkit"');
153 | if (this.MacOS32) {
154 | this.mkdir('resources/node-webkit/MacOS32');
155 | this.log.ok('Created: "resources/node-webkit/MacOS32"');
156 | }
157 | if (this.MacOS64) {
158 | this.mkdir('resources/node-webkit/MacOS64');
159 | this.log.ok('Created: "resources/node-webkit/MacOS64"');
160 | }
161 | if (this.Linux64) {
162 | this.mkdir('resources/node-webkit/Linux64');
163 | this.log.ok('Created: "resources/node-webkit/Linux64"');
164 | }
165 | if (this.Linux32) {
166 | this.mkdir('resources/node-webkit/Linux32');
167 | this.log.ok('Created: "resources/node-webkit/Linux32"');
168 | }
169 | if (this.Windows) {
170 | this.mkdir('resources/node-webkit/Windows');
171 | this.log.ok('Created: "resources/node-webkit/Windows"');
172 | }
173 | this.mkdir('tmp');
174 | this.log.ok('Created: "tmp"');
175 | },
176 | getNodeWebkit: function getNodeWebkit() {
177 | var done = this.async();
178 |
179 | var successClbk = function () {
180 | done();
181 | };
182 | var failureClbk = function (error) {
183 | throw error;
184 | };
185 | if (this.downloadNodeWebkit) {
186 | when.all(this._getNodeWebkit()).then(successClbk, failureClbk);
187 | } else {
188 | successClbk();
189 | }
190 | },
191 | _getNodeWebkit: function _getNodeWebkit() {
192 | var promises = [];
193 | if (this.MacOS32) {
194 | promises.push(this._requestNodeWebkit('osx-ia32', '.zip', 'MacOS32'));
195 | }
196 | if (this.MacOS64) {
197 | promises.push(this._requestNodeWebkit('osx-x64', '.zip', 'MacOS64'));
198 | }
199 | if (this.Linux64) {
200 | promises.push(this._requestNodeWebkit('linux-x64', '.tar.gz', 'Linux64'));
201 | }
202 | if (this.Linux32) {
203 | promises.push(this._requestNodeWebkit('linux-ia32', '.tar.gz', 'Linux32'));
204 | }
205 | if (this.Windows) {
206 | promises.push(this._requestNodeWebkit('win-ia32', '.zip', 'Windows'));
207 | }
208 | return promises;
209 | },
210 | _requestNodeWebkit: function _requestNodeWebkit(versionString, extension, platform) {
211 | var defer = when.defer(),
212 | _this = this;
213 |
214 | if (!fs.existsSync('tmp/' + platform + extension)) {
215 | if (fs.existsSync('tmp/' + platform + extension + '.part')) {
216 | fs.unlinkSync('tmp/' + platform + extension + '.part');
217 | }
218 | this.log.info('Downloading node-webkit for ' + platform);
219 | http.get(this._getDownloadUrl() + versionString + extension, function (res) {
220 | if (200 === res.statusCode) {
221 | res.on('data', function (chunk) {
222 | fs.appendFileSync('tmp/' + platform + extension + '.part', chunk);
223 | }).on('end', function () {
224 | fs.renameSync('tmp/' + platform + extension + '.part', 'tmp/' + platform + extension);
225 | _this.log.ok('Node-webkit for ' + platform + ' downloaded');
226 | defer.resolve();
227 | }).on('error', function (error) {
228 | _this.log.conflict('Error while downloading node-webkit for ' + platform, error);
229 | defer.reject(error);
230 | });
231 | } else {
232 | _this.log.conflict('Wrong content type for %s', platform);
233 | defer.reject('Wrong content type for ' + platform);
234 | }
235 | }).on('error', function (error) {
236 | _this.log.conflict('Error while downloading node-webkit for ' + platform, error);
237 | defer.reject(error);
238 | });
239 | } else {
240 | this.log.ok('Node-webkit for ' + platform + ' already downloaded');
241 | defer.resolve();
242 | }
243 | return defer.promise;
244 | },
245 | unzipNodeWebkit: function unzipNodeWebkit() {
246 | var done = this.async();
247 | var successClbk = function () {
248 | done();
249 | };
250 | var failureClbk = function (error) {
251 | throw error;
252 | };
253 | if (this.downloadNodeWebkit) {
254 | when.all(this._unzipNodeWebkit()).then(successClbk, failureClbk);
255 | } else {
256 | done();
257 | }
258 | },
259 | _unzipNodeWebkit: function _unzipNodeWebkit() {
260 | var promises = [];
261 |
262 | if (this.MacOS32) {
263 | promises.push(this._extract('MacOS32', '.zip'));
264 | }
265 | if (this.MacOS64) {
266 | promises.push(this._extract('MacOS64', '.zip'));
267 | }
268 | if (this.Linux64) {
269 | promises.push(this._extract('Linux64', '.tar.gz'));
270 | }
271 | if (this.Linux32) {
272 | promises.push(this._extract('Linux32', '.tar.gz'));
273 | }
274 | if (this.Windows) {
275 | promises.push(this._extract('Windows', '.zip'));
276 | }
277 | return promises;
278 | },
279 | _extract: function _extract(platform, extension) {
280 | var _this = this;
281 | var defer = when.defer();
282 | if ('.zip' === extension) {
283 | if (fs.existsSync('tmp/' + platform + extension)) {
284 | this.log.info('Unzip %s files.', platform);
285 | var unzipper = new DecompressZip('tmp/' + platform + extension);
286 |
287 | unzipper.on('error', function (error) {
288 | _this.log.conflict('Error while unzipping "tmp/' + platform + extension + '"', error);
289 | defer.reject(error);
290 | });
291 |
292 | unzipper.on('extract', function () {
293 | _this.log.ok('"tmp/%s.zip" successfully unzipped', platform);
294 | if (fs.existsSync('resources/node-webkit/' + platform + '/nwjs.app')) {
295 | if (fs.existsSync('resources/node-webkit/' + platform + '/node-webkit.app')) {
296 | fs.removeSync('resources/node-webkit/' + platform + '/node-webkit.app');
297 | }
298 | fs.renameSync('resources/node-webkit/' + platform + '/nwjs.app', 'resources/node-webkit/' + platform + '/node-webkit.app');
299 | }
300 | defer.resolve();
301 | });
302 |
303 | var stripLevel = 0;
304 | if ('MacOS64' === platform || this.nodeWebkitVersion.indexOf('v0.9.') === -1 && this.nodeWebkitVersion.indexOf('v0.8.') === -1) {
305 | stripLevel = 1;
306 | }
307 | unzipper.extract({
308 | path: 'resources/node-webkit/' + platform,
309 | strip: stripLevel
310 | });
311 | } else {
312 | defer.resolve();
313 | }
314 | } else if ('.tar.gz' === extension) {
315 | this.log.info('Un.tar.gz %s files.', platform);
316 | var src = 'tmp/' + platform + extension;
317 | var dst = 'resources/node-webkit/' + platform;
318 | fs.createReadStream(src).pipe(zlib.createGunzip()).pipe(tar.extract(dst)).on('finish', function (error) {
319 | if (!error) {
320 | var platformSuffix = platform === 'Linux64' ? '-linux-x64' : '-linux-ia32';
321 | var namePart = '/nwjs-';
322 | if (_this.nodeWebkitVersion.indexOf('v0.9.') !== -1 || _this.nodeWebkitVersion.indexOf('v0.8.') !== -1 || _this.nodeWebkitVersion.indexOf('v0.10.') !== -1 || _this.nodeWebkitVersion.indexOf('v0.11.') !== -1) {
323 | namePart = '/node-webkit-';
324 | }
325 | var copyPath = 'resources/node-webkit/' + platform + namePart + _this.nodeWebkitVersion + platformSuffix;
326 | fs.copy(copyPath, 'resources/node-webkit/' + platform, function(error) {
327 | if (error) {
328 | defer.reject(error);
329 | } else {
330 | fs.remove(copyPath);
331 | _this.log.ok('%s directory successfully copied.', platform);
332 | defer.resolve();
333 | }
334 | });
335 | } else {
336 | defer.reject(error);
337 | }
338 | });
339 | }
340 | return defer.promise;
341 | }
342 | });
343 |
--------------------------------------------------------------------------------
/app/templates/_Gruntfile.js:
--------------------------------------------------------------------------------
1 | /*jshint camelcase: false*/
2 |
3 | module.exports = function (grunt) {
4 | 'use strict';
5 |
6 | // load all grunt tasks
7 | require('time-grunt')(grunt);
8 | require('load-grunt-tasks')(grunt);
9 |
10 | // configurable paths
11 | var config = {
12 | app: 'app',
13 | dist: 'dist',
14 | distMac32: 'dist/macOS',
15 | distMac64: 'dist/macOS',
16 | distLinux32: 'dist/Linux32',
17 | distLinux64: 'dist/Linux64',
18 | distWin: 'dist/Win',
19 | tmp: 'buildTmp',
20 | resources: 'resources'
21 | };
22 |
23 | grunt.initConfig({
24 | config: config,
25 | clean: {
26 | dist: {
27 | files: [{
28 | dot: true,
29 | src: [
30 | '<%%= config.dist %>/*',
31 | '<%%= config.tmp %>/*'
32 | ]
33 | }]
34 | },
35 | distMac32: {
36 | files: [{
37 | dot: true,
38 | src: [
39 | '<%%= config.distMac32 %>/*',
40 | '<%%= config.tmp %>/*'
41 | ]
42 | }]
43 | },
44 | distMac64: {
45 | files: [{
46 | dot: true,
47 | src: [
48 | '<%%= config.distMac64 %>/*',
49 | '<%%= config.tmp %>/*'
50 | ]
51 | }]
52 | },
53 | distLinux64: {
54 | files: [{
55 | dot: true,
56 | src: [
57 | '<%%= config.distLinux64 %>/*',
58 | '<%%= config.tmp %>/*'
59 | ]
60 | }]
61 | },
62 | distLinux32: {
63 | files: [{
64 | dot: true,
65 | src: [
66 | '<%%= config.distLinux32 %>/*',
67 | '<%%= config.tmp %>/*'
68 | ]
69 | }]
70 | },
71 | distWin: {
72 | files: [{
73 | dot: true,
74 | src: [
75 | '<%%= config.distWin %>/*',
76 | '<%%= config.tmp %>/*'
77 | ]
78 | }]
79 | }
80 | },
81 | jshint: {
82 | options: {
83 | jshintrc: '.jshintrc'
84 | },
85 | files: '<%%= config.app %>/js/*.js'
86 | },
87 | copy: {
88 | appLinux: {
89 | files: [{
90 | expand: true,
91 | cwd: '<%%= config.app %>',
92 | dest: '<%%= config.distLinux64 %>/app.nw',
93 | src: '**'
94 | }]
95 | },
96 | appLinux32: {
97 | files: [{
98 | expand: true,
99 | cwd: '<%%= config.app %>',
100 | dest: '<%%= config.distLinux32 %>/app.nw',
101 | src: '**'
102 | }]
103 | },
104 | appMacos32: {
105 | files: [{
106 | expand: true,
107 | cwd: '<%%= config.app %>',
108 | dest: '<%%= config.distMac32 %>/node-webkit.app/Contents/Resources/app.nw',
109 | src: '**'
110 | }, {
111 | expand: true,
112 | cwd: '<%%= config.resources %>/mac/',
113 | dest: '<%%= config.distMac32 %>/node-webkit.app/Contents/',
114 | filter: 'isFile',
115 | src: '*.plist'
116 | }, {
117 | expand: true,
118 | cwd: '<%%= config.resources %>/mac/',
119 | dest: '<%%= config.distMac32 %>/node-webkit.app/Contents/Resources/',
120 | filter: 'isFile',
121 | src: '*.icns'
122 | }, {
123 | expand: true,
124 | cwd: '<%%= config.app %>/../node_modules/',
125 | dest: '<%%= config.distMac32 %>/node-webkit.app/Contents/Resources/app.nw/node_modules/',
126 | src: '**'
127 | }]
128 | },
129 | appMacos64: {
130 | files: [{
131 | expand: true,
132 | cwd: '<%%= config.app %>',
133 | dest: '<%%= config.distMac64 %>/node-webkit.app/Contents/Resources/app.nw',
134 | src: '**'
135 | }, {
136 | expand: true,
137 | cwd: '<%%= config.resources %>/mac/',
138 | dest: '<%%= config.distMac64 %>/node-webkit.app/Contents/',
139 | filter: 'isFile',
140 | src: '*.plist'
141 | }, {
142 | expand: true,
143 | cwd: '<%%= config.resources %>/mac/',
144 | dest: '<%%= config.distMac64 %>/node-webkit.app/Contents/Resources/',
145 | filter: 'isFile',
146 | src: '*.icns'
147 | }, {
148 | expand: true,
149 | cwd: '<%%= config.app %>/../node_modules/',
150 | dest: '<%%= config.distMac64 %>/node-webkit.app/Contents/Resources/app.nw/node_modules/',
151 | src: '**'
152 | }]
153 | },
154 | webkit32: {
155 | files: [{
156 | expand: true,
157 | cwd: '<%%=config.resources %>/node-webkit/MacOS32',
158 | dest: '<%%= config.distMac32 %>/',
159 | src: '**'
160 | }]
161 | },
162 | webkit64: {
163 | files: [{
164 | expand: true,
165 | cwd: '<%%=config.resources %>/node-webkit/MacOS64',
166 | dest: '<%%= config.distMac64 %>/',
167 | src: '**'
168 | }]
169 | },
170 | copyWinToTmp: {
171 | files: [{
172 | expand: true,
173 | cwd: '<%%= config.resources %>/node-webkit/Windows/',
174 | dest: '<%%= config.tmp %>/',
175 | src: '**'
176 | }]
177 | }
178 | },
179 | compress: {
180 | appToTmp: {
181 | options: {
182 | archive: '<%%= config.tmp %>/app.zip'
183 | },
184 | files: [{
185 | expand: true,
186 | cwd: '<%%= config.app %>',
187 | src: ['**']
188 | }]
189 | },
190 | finalWindowsApp: {
191 | options: {
192 | archive: '<%%= config.distWin %>/<%= appName %>.zip'
193 | },
194 | files: [{
195 | expand: true,
196 | cwd: '<%%= config.tmp %>',
197 | src: ['**']
198 | }]
199 | }
200 | },
201 | rename: {
202 | macApp32: {
203 | files: [{
204 | src: '<%%= config.distMac32 %>/node-webkit.app',
205 | dest: '<%%= config.distMac32 %>/<%= appName %>.app'
206 | }]
207 | },
208 | macApp64: {
209 | files: [{
210 | src: '<%%= config.distMac64 %>/node-webkit.app',
211 | dest: '<%%= config.distMac64 %>/<%= appName %>.app'
212 | }]
213 | },
214 | zipToApp: {
215 | files: [{
216 | src: '<%%= config.tmp %>/app.zip',
217 | dest: '<%%= config.tmp %>/app.nw'
218 | }]
219 | }
220 | }
221 | });
222 |
223 | grunt.registerTask('chmod32', 'Add lost Permissions.', function () {
224 | var fs = require('fs'),
225 | path = config.distMac32 + '/<%= appName %>.app/Contents/';
226 | if (fs.existsSync(path + 'Frameworks/node-webkit Helper EH.app/Contents/MacOS/node-webkit Helper EH')) {
227 | fs.chmodSync(path + 'Frameworks/node-webkit Helper EH.app/Contents/MacOS/node-webkit Helper EH', '555');
228 | } else {
229 | fs.chmodSync(path + 'Frameworks/nwjs Helper EH.app/Contents/MacOS/nwjs Helper EH', '555');
230 | }
231 | if (fs.existsSync(path + 'Frameworks/node-webkit Helper NP.app/Contents/MacOS/node-webkit Helper NP')) {
232 | fs.chmodSync(path + 'Frameworks/node-webkit Helper NP.app/Contents/MacOS/node-webkit Helper NP', '555');
233 | } else {
234 | fs.chmodSync(path + 'Frameworks/nwjs Helper NP.app/Contents/MacOS/nwjs Helper NP', '555');
235 | }
236 | if (fs.existsSync(path + 'Frameworks/node-webkit Helper.app/Contents/MacOS/node-webkit Helper')) {
237 | fs.chmodSync(path + 'Frameworks/node-webkit Helper.app/Contents/MacOS/node-webkit Helper', '555');
238 | } else {
239 | fs.chmodSync(path + 'Frameworks/nwjs Helper.app/Contents/MacOS/nwjs Helper', '555');
240 | }
241 | if (fs.existsSync(path + 'MacOS/node-webkit')) {
242 | fs.chmodSync(path + 'MacOS/node-webkit', '555');
243 | } else {
244 | fs.chmodSync(path + 'MacOS/nwjs', '555');
245 | }
246 | });
247 |
248 | grunt.registerTask('chmod64', 'Add lost Permissions.', function () {
249 | var fs = require('fs'),
250 | path = config.distMac64 + '/<%= appName %>.app/Contents/';
251 | if (fs.existsSync(path + 'Frameworks/node-webkit Helper EH.app/Contents/MacOS/node-webkit Helper EH')) {
252 | fs.chmodSync(path + 'Frameworks/node-webkit Helper EH.app/Contents/MacOS/node-webkit Helper EH', '555');
253 | } else {
254 | fs.chmodSync(path + 'Frameworks/nwjs Helper EH.app/Contents/MacOS/nwjs Helper EH', '555');
255 | }
256 | if (fs.existsSync(path + 'Frameworks/node-webkit Helper NP.app/Contents/MacOS/node-webkit Helper NP')) {
257 | fs.chmodSync(path + 'Frameworks/node-webkit Helper NP.app/Contents/MacOS/node-webkit Helper NP', '555');
258 | } else {
259 | fs.chmodSync(path + 'Frameworks/nwjs Helper NP.app/Contents/MacOS/nwjs Helper NP', '555');
260 | }
261 | if (fs.existsSync(path + 'Frameworks/node-webkit Helper.app/Contents/MacOS/node-webkit Helper')) {
262 | fs.chmodSync(path + 'Frameworks/node-webkit Helper.app/Contents/MacOS/node-webkit Helper', '555');
263 | } else {
264 | fs.chmodSync(path + 'Frameworks/nwjs Helper.app/Contents/MacOS/nwjs Helper', '555');
265 | }
266 | if (fs.existsSync(path + 'MacOS/node-webkit')) {
267 | fs.chmodSync(path + 'MacOS/node-webkit', '555');
268 | } else {
269 | fs.chmodSync(path + 'MacOS/nwjs', '555');
270 | }
271 | });
272 |
273 | grunt.registerTask('createLinuxApp', 'Create linux distribution.', function (version) {
274 | var done = this.async();
275 | var childProcess = require('child_process');
276 | var exec = childProcess.exec;
277 | var path = './' + (version === 'Linux64' ? config.distLinux64 : config.distLinux32);
278 | exec('mkdir -p ' + path + '; cp resources/node-webkit/' + version + '/nw.pak ' + path + ' && cp resources/node-webkit/' + version + '/nw ' + path + '/node-webkit && cp resources/node-webkit/' + version + '/icudtl.dat ' + path + '/icudtl.dat', function (error, stdout, stderr) {
279 | var result = true;
280 | if (stdout) {
281 | grunt.log.write(stdout);
282 | }
283 | if (stderr) {
284 | grunt.log.write(stderr);
285 | }
286 | if (error !== null) {
287 | grunt.log.error(error);
288 | result = false;
289 | }
290 | done(result);
291 | });
292 | });
293 |
294 | grunt.registerTask('createWindowsApp', 'Create windows distribution.', function () {
295 | var done = this.async();
296 | var concat = require('concat-files');
297 | concat([
298 | 'buildTmp/nw.exe',
299 | 'buildTmp/app.nw'
300 | ], 'buildTmp/<%= appName %>.exe', function () {
301 | var fs = require('fs');
302 | fs.unlink('buildTmp/app.nw', function (error, stdout, stderr) {
303 | if (stdout) {
304 | grunt.log.write(stdout);
305 | }
306 | if (stderr) {
307 | grunt.log.write(stderr);
308 | }
309 | if (error !== null) {
310 | grunt.log.error(error);
311 | done(false);
312 | } else {
313 | fs.unlink('buildTmp/nw.exe', function (error, stdout, stderr) {
314 | var result = true;
315 | if (stdout) {
316 | grunt.log.write(stdout);
317 | }
318 | if (stderr) {
319 | grunt.log.write(stderr);
320 | }
321 | if (error !== null) {
322 | grunt.log.error(error);
323 | result = false;
324 | }
325 | done(result);
326 | });
327 | }
328 | });
329 | });
330 | });
331 |
332 | grunt.registerTask('setVersion', 'Set version to all needed files', function (version) {
333 | var config = grunt.config.get(['config']);
334 | var appPath = config.app;
335 | var resourcesPath = config.resources;
336 | var mainPackageJSON = grunt.file.readJSON('package.json');
337 | var appPackageJSON = grunt.file.readJSON(appPath + '/package.json');
338 | var infoPlistTmp = grunt.file.read(resourcesPath + '/mac/Info.plist.tmp', {
339 | encoding: 'UTF8'
340 | });
341 | var infoPlist = grunt.template.process(infoPlistTmp, {
342 | data: {
343 | version: version
344 | }
345 | });
346 | mainPackageJSON.version = version;
347 | appPackageJSON.version = version;
348 | grunt.file.write('package.json', JSON.stringify(mainPackageJSON, null, 2), {
349 | encoding: 'UTF8'
350 | });
351 | grunt.file.write(appPath + '/package.json', JSON.stringify(appPackageJSON, null, 2), {
352 | encoding: 'UTF8'
353 | });
354 | grunt.file.write(resourcesPath + '/mac/Info.plist', infoPlist, {
355 | encoding: 'UTF8'
356 | });
357 | });
358 |
359 | grunt.registerTask('createPlistFile', 'set node webkit and app relevant information to a new plist file', function() {
360 | var metadata = grunt.file.readJSON('.yo-rc.json');
361 | var resourcesPath = config.resources;
362 | var nwExecuteable = 'nwjs';
363 | if (metadata.nodeWebkitVersion.indexOf('v0.8.') === 0 || metadata.nodeWebkitVersion.indexOf('v0.9.') === 0 || metadata.nodeWebkitVersion.indexOf('v0.10.') === 0 || metadata.nodeWebkitVersion.indexOf('v0.11.') === 0) {
364 | nwExecuteable = 'node-webkit';
365 | }
366 | var infoPlistTmp = grunt.file.read(resourcesPath + '/mac/Info.plist.tmp', {
367 | encoding: 'UTF8'
368 | });
369 | var infoPlist = grunt.template.process(infoPlistTmp, {
370 | data: {
371 | nwExecutableName: nwExecuteable
372 | }
373 | });
374 | grunt.file.write(resourcesPath + '/mac/Info.plist', infoPlist, {
375 | encoding: 'UTF8'
376 | });
377 | })
378 |
379 | grunt.registerTask('dist-linux', [
380 | 'jshint',
381 | 'clean:distLinux64',
382 | 'copy:appLinux',
383 | 'createLinuxApp:Linux64'
384 | ]);
385 |
386 | grunt.registerTask('dist-linux32', [
387 | 'jshint',
388 | 'clean:distLinux32',
389 | 'copy:appLinux32',
390 | 'createLinuxApp:Linux32'
391 | ]);
392 |
393 | grunt.registerTask('dist-win', [
394 | 'jshint',
395 | 'clean:distWin',
396 | 'copy:copyWinToTmp',
397 | 'compress:appToTmp',
398 | 'rename:zipToApp',
399 | 'createWindowsApp',
400 | 'compress:finalWindowsApp'
401 | ]);
402 |
403 | grunt.registerTask('dist-mac', [
404 | 'jshint',
405 | 'clean:distMac64',
406 | 'createPlistFile',
407 | 'copy:webkit64',
408 | 'copy:appMacos64',
409 | 'rename:macApp64',
410 | 'chmod64'
411 | ]);
412 |
413 | grunt.registerTask('dist-mac32', [
414 | 'jshint',
415 | 'clean:distMac32',
416 | 'createPlistFile',
417 | 'copy:webkit32',
418 | 'copy:appMacos32',
419 | 'rename:macApp32',
420 | 'chmod32'
421 | ]);
422 |
423 | grunt.registerTask('check', [
424 | 'jshint'
425 | ]);
426 |
427 | grunt.registerTask('dmg', 'Create dmg from previously created app folder in dist.', function () {
428 | var done = this.async();
429 | var createDmgCommand = 'resources/mac/package.sh "<%= appName %>"';
430 | require('child_process').exec(createDmgCommand, function (error, stdout, stderr) {
431 | var result = true;
432 | if (stdout) {
433 | grunt.log.write(stdout);
434 | }
435 | if (stderr) {
436 | grunt.log.write(stderr);
437 | }
438 | if (error !== null) {
439 | grunt.log.error(error);
440 | result = false;
441 | }
442 | done(result);
443 | });
444 | });
445 |
446 | };
447 |
--------------------------------------------------------------------------------