├── .eslintignore
├── .gitignore
├── images
├── icon.png
├── image.png
├── splash.png
└── Google
│ └── 7Inch.png
├── .npmignore
├── CONTRIBUTING.md
├── .editorconfig
├── mediagen-config.json
├── test
└── specs
│ ├── mediagen-config.json
│ ├── app.spec.js
│ └── screenshots.spec.js
├── .travis.yml
├── LICENSE
├── lib
├── store_images.js
├── generate_image_sets.js
├── resize.js
├── splash_images.js
└── generate_icon_sets.js
├── ISSUE_TEMPLATE.md
├── Jenkinsfile
├── package.json
├── CHANGELOG.md
├── .eslintrc
├── README.md
├── screenshots.js
└── tns-media-gen.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/*{.,-}min.js
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .tmp/
3 | app/
4 | dist/
5 | node_modules/
6 | media/
7 |
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypery2k/nativescript-media-generator/HEAD/images/icon.png
--------------------------------------------------------------------------------
/images/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypery2k/nativescript-media-generator/HEAD/images/image.png
--------------------------------------------------------------------------------
/images/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypery2k/nativescript-media-generator/HEAD/images/splash.png
--------------------------------------------------------------------------------
/images/Google/7Inch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hypery2k/nativescript-media-generator/HEAD/images/Google/7Inch.png
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .tmp/
3 | app/
4 | dist/
5 | node_modules/
6 | images/
7 | media/
8 | screenshots/
9 | test/
10 | Jenkinsfile
11 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | First search if the issue is already described!
2 |
3 | If not create a new issue:
4 |
5 | * Tell about your environment:
6 | * node version
7 | * cordova version
8 | * used platform and version
9 | * Describe your issue
10 | * describe your steps leading to the issue
11 | * attach error logs or screenshots
12 | * if possible provide test case or screenshots
13 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 |
9 | # Change these settings to your own preference
10 | indent_style = space
11 | indent_size = 2
12 |
13 | # We recommend you to keep these unchanged
14 | end_of_line = lf
15 | insert_final_newline = true
16 | charset = utf-8
17 | trim_trailing_whitespace = true
18 | max_line_length = 140
19 |
20 | [*.{js, ts}]
21 | quote_type = single
22 |
23 | [*.md]
24 | trim_trailing_whitespace = false
25 |
26 | [{package.json,.travis.yml}]
27 | indent_style = space
28 | indent_size = 2
29 |
--------------------------------------------------------------------------------
/mediagen-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": {
3 | "filename": "icon.png",
4 | "background": "fff"
5 | },
6 | "splash": {
7 | "filename": "splash.png",
8 | "background": "fff"
9 | },
10 | "customImages": [
11 | {
12 | "width": 120,
13 | "height": 120,
14 | "path": "../../Media/custom",
15 | "filename": "outputFilename.png",
16 | "source": {
17 | "filename": "image.png",
18 | "background": "fff"
19 | }
20 | }
21 | ],
22 | "screenshots": [
23 | {
24 | "url": "http://www.google.com",
25 | "name": "homepage"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/test/specs/mediagen-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "icon": {
3 | "filename": "icon.png",
4 | "background": "fff"
5 | },
6 | "splash": {
7 | "filename": "splash.png",
8 | "background": "fff"
9 | },
10 | "customImages": [
11 | {
12 | "width": 120,
13 | "height": 120,
14 | "path": "../Media/custom",
15 | "filename": "outputFilename.png",
16 | "source": {
17 | "filename": "image.png",
18 | "background": "fff"
19 | }
20 | }
21 | ],
22 | "screenshots": [
23 | {
24 | "url": "http://www.google.com",
25 | "name": "homepage"
26 | }
27 | ]
28 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | os: osx
2 | osx_image: xcode8.3
3 | sudo: false
4 | language: objective-c
5 |
6 | env:
7 | matrix:
8 | - NODE_VERSION="4" NPM_VERSION=3
9 | - NODE_VERSION="5" NPM_VERSION=3
10 | - NODE_VERSION="5" NPM_VERSION=4
11 | - NODE_VERSION="6" NPM_VERSION=3
12 | - NODE_VERSION="6" NPM_VERSION=4
13 |
14 | script:
15 | - npm install
16 | - npm run build
17 | - npm run test
18 | before_install:
19 | - source ~/.nvm/nvm.sh && nvm install $NODE_VERSION && nvm use $NODE_VERSION
20 | - PATH="`npm bin`:`npm bin -g`:$PATH"
21 | - npm install -g npm@$NPM_VERSION
22 | - brew update > /dev/null;
23 | - brew install jpeg python3 imagemagick
24 | # Show environment invo
25 | - node --version
26 | - npm --version
27 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Martin Reinhardt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/test/specs/app.spec.js:
--------------------------------------------------------------------------------
1 | var mediaGen = require('../../tns-media-gen');
2 |
3 | describe('main app', function() {
4 | describe('resize', function() {
5 | it('should not error out', function(done) {
6 | mediaGen.__resize(10, 10, "#fff", "images/icon.png", "output.png", "../../.tmp")
7 | .then(function(result) {
8 | expect(result).toBeDefined();
9 | done();
10 | })
11 | .catch(done);
12 | })
13 | });
14 |
15 | describe('generate', function() {
16 | it('should not error out', function(done) {
17 | mediaGen.__generate()
18 | .then(function(result) {
19 | done();
20 | })
21 | .catch(done)
22 | })
23 | });
24 |
25 | describe('genConfig', function() {
26 | it('should not error out', function(done) {
27 | mediaGen.__genConfig()
28 | .then(function(result) {
29 | expect(result).toBe('success');
30 | done();
31 | })
32 | .catch(done);
33 | })
34 | })
35 | });
--------------------------------------------------------------------------------
/lib/store_images.js:
--------------------------------------------------------------------------------
1 | module.exports = function storeImagesGenerator(config, mediaPath) {
2 | return [
3 | //Android Store Icons
4 | {
5 | width: 512,
6 | height: 512,
7 | path: "../../" + mediaPath + "/android/store",
8 | filename: "512.png",
9 | source: process.argv[2] || config.icon || config.image
10 | }, {
11 | width: 1024,
12 | height: 500,
13 | path: "../../" + mediaPath + "/android/store",
14 | filename: "1024x500.png",
15 | source: process.argv[2] || config.splash || config.image
16 | }, {
17 | width: 180,
18 | height: 120,
19 | path: "../../" + mediaPath + "/android/store",
20 | filename: "180x120.png",
21 | source: process.argv[2] || config.splash || config.image
22 | },
23 |
24 | //Apple store icons
25 | {
26 | width: 1024,
27 | height: 1024,
28 | path: "../../" + mediaPath + "/ios/store",
29 | filename: "1024x1024-AppIcon.jpg",
30 | source: process.argv[2] || config.icon || config.image
31 | }
32 | ];
33 | }
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | > ℹ Please fill out this template when filing an issue.
2 | > All lines beginning with an ℹ symbol instruct you with what info we expect. You can delete those lines once you've filled in the info.
3 | >
4 | > Per our [*CONTRIBUTING guidelines](https://github.com/hypery2k/nativescript-media-generator/master/CONTRIBUTING.md), we use GitHub for
5 | > bugs and feature requests, not general support. Other issues should be opened on Stack Overflow with the tag `nativescript`.
6 | >
7 | > Please remove this line and everything above it before submitting.
8 |
9 | * [ ] I've read, understood, and done my best to follow the [*CONTRIBUTING guidelines](https://github.com/hypery2k/nativescript-media-generator/master/CONTRIBUTING.md).
10 |
11 | ## What did you do?
12 |
13 | ℹ Please replace this with what you did.
14 |
15 | ## What did you expect to happen?
16 |
17 | ℹ Please replace this with what you expected to happen.
18 |
19 | ## What happened instead?
20 |
21 | ℹ Please replace this with of what happened instead.
22 |
23 | ## Your Environment
24 |
25 | **NativeScript version:**
26 | **Java version:**
27 | **NodeJS and NPM version:**
28 | **Platform(s) running:**
29 |
30 | ## Demo Project
31 |
32 | ℹ Please link to or upload a project we can download that reproduces the issue.
33 |
--------------------------------------------------------------------------------
/Jenkinsfile:
--------------------------------------------------------------------------------
1 | properties properties: [
2 | [$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '30', numToKeepStr: '10']],
3 | [$class: 'GithubProjectProperty', displayName: '', projectUrlStr: 'https://github.com/hypery2k/nativescript-media-generator'],
4 | ]
5 |
6 | @Library('mare-build-library')
7 | def nodeJS = new de.mare.ci.jenkins.NodeJS()
8 |
9 | node {
10 | def buildNumber = env.BUILD_NUMBER
11 | def branchName = env.BRANCH_NAME
12 | def mvnHome = '/opt/dev/apache-maven-3.3.1'
13 | def workspace = env.WORKSPACE
14 | def buildUrl = env.BUILD_URL
15 | env.PATH="${env.JAVA_HOME}/bin:${mvnHome}/bin:${env.PATH}"
16 |
17 | // PRINT ENVIRONMENT TO JOB
18 | echo "workspace directory is $workspace"
19 | echo "build URL is $buildUrl"
20 | echo "build Number is $buildNumber"
21 | echo "branch name is $branchName"
22 | echo "PATH is $env.PATH"
23 |
24 | try {
25 |
26 | stage('Checkout') {
27 | checkout scm
28 | }
29 |
30 | stage('Build') {
31 | sh "npm install"
32 | }
33 |
34 | stage('Test') {
35 | wrap([$class: 'Xvfb']) {
36 | sh "npm run test"
37 | junit 'dist/reports/TEST-*.xml'
38 | }
39 | }
40 |
41 | stage('Publish NPM snapshot') {
42 | nodeJS.publishSnapshot('', buildNumber, branchName)
43 | }
44 |
45 | } catch (e) {
46 | mail subject: "${env.JOB_NAME} (${env.BUILD_NUMBER}): Error on build", to: 'github@martinreinhardt-online.de', body: "Please go to ${env.BUILD_URL}."
47 | throw e
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/lib/generate_image_sets.js:
--------------------------------------------------------------------------------
1 | var q = require('q'),
2 | path = require('path'),
3 | fs = require('fs'),
4 | gm = require('gm').subClass({ imageMagick: true });
5 |
6 | module.exports = function generateImageSets(filename, source, iOSPath) { /*eslint complexity: [error, 22]*/
7 | return [
8 | //IOS Images
9 | {
10 | width: "24.5%", // max 466
11 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
12 | filename: filename,
13 | source: source
14 | }, {
15 | width: "49%", // max 932
16 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
17 | filename: filename.replace('.', '@2x.'),
18 | source: source
19 | }, {
20 | width: "73.6%", // max 1398
21 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
22 | filename: filename.replace('.', '@3x.'),
23 | source: source
24 | },
25 |
26 | //Android
27 | {
28 | width: "75%", // max 1425
29 | path: "Android/drawable-hdpi",
30 | filename: filename,
31 | source: source
32 | }, {
33 | width: "50%", // max 950
34 | path: "Android/drawable-mdpi",
35 | filename: filename,
36 | source: source
37 | }, {
38 | width: "100%", // max 1900
39 | path: "Android/drawable-xhdpi",
40 | filename: filename,
41 | source: source
42 | }, {
43 | width: "70%", // max 1331
44 | path: "Android/drawable-xxhdpi",
45 | filename: filename,
46 | source: source
47 | }, {
48 | width: "93.4%", // max 1775
49 | path: "Android/drawable-xxxhdpi",
50 | filename: filename,
51 | source: source
52 | }
53 |
54 | ]
55 | }
--------------------------------------------------------------------------------
/test/specs/screenshots.spec.js:
--------------------------------------------------------------------------------
1 | var screenshots = require('../../screenshots'),
2 | fs = require('fs');
3 |
4 | var settings = {
5 | url: 'http://www.google.com',
6 | width: 1280,
7 | height: 720,
8 | path: "images/Google",
9 | fileName: '7Inch.png'
10 | };
11 |
12 | xdescribe('Screenshots', function () {
13 | describe('generate', function () {
14 | it('should return no errors', function (done) {
15 | screenshots.generate(settings.url, settings.width, settings.height, 1, settings.path, settings.fileName)
16 | .then(function (result) {
17 | console.log('==>' + result)
18 | expect(result.success).toBeDefined();
19 | })
20 | .catch(function (error) {
21 | throw new error;
22 | })
23 | .done(function () { done() });
24 | }, 30000);
25 |
26 | it('should have created a file', function (done) {
27 | fs.exists(settings.path + "/" + settings.fileName, function (result) {
28 | expect(result).toBeTruthy();
29 | done();
30 | });
31 | }, 30000);
32 |
33 | it('should die when nothing is supplied', function (done) {
34 | screenshots.generate()
35 | .then(function (result) {
36 | fail("Should not have worked");
37 | })
38 | .catch(function (err) {
39 | expect(err).toBeDefined();
40 | done();
41 | });
42 | }, 30000);
43 | });
44 |
45 | describe('generate all', function () {
46 | screenshots.pages.push({ url: "http://www.google.com", name: "home" });
47 |
48 | it('should return', function (done) {
49 | expect(screenshots.generateAll()).toBeTruthy();
50 | done();
51 | }, 30000);
52 |
53 | it('should have created a file', function (done) {
54 | fs.exists("Media/android/screenshots/10in/android-10in-1280x720-google.png", function (result) {
55 | expect(result).toBeTruthy();
56 | done();
57 | });
58 | }, 30000);
59 | });
60 |
61 | });
62 |
--------------------------------------------------------------------------------
/lib/resize.js:
--------------------------------------------------------------------------------
1 | var q = require('q'),
2 | path = require('path'),
3 | fs = require('fs'),
4 | gm = require('gm').subClass({ imageMagick: true }),
5 | mkdirp = require('mkdirp');
6 |
7 | module.exports = function resize(width, height, bgColour, imagePath, outputFilename, outputPath) {
8 | var deferred = q.defer(),
9 | filepath = path.join(process.cwd(), imagePath);
10 | gm(filepath).size(function(error, size) {
11 |
12 | if (error) {
13 | console.error("GM Error", error);
14 | deferred.reject(error);
15 | } else {
16 |
17 | // current image size
18 | var imageWidth = size.width;
19 | var imageHeight = size.height;
20 | var ratio = width / height,
21 | imageRatio = imageWidth / imageHeight;
22 | var image = this;
23 |
24 | if (isNaN(parseFloat(width))) {
25 | var percentage = '' + width;
26 | width = imageWidth * (parseInt(percentage.substring(0, percentage.indexOf("%")), 0) / 100);
27 | }
28 | // center placement
29 | if (ratio >= 1) {
30 | //Landscape or square
31 | var newWidth = height * imageRatio;
32 |
33 | if (newWidth >= width) {
34 | this.resize(width);
35 | } else {
36 | this.resize(null, height);
37 | }
38 |
39 |
40 | } else {
41 | var newHeight = width / imageRatio;
42 |
43 | if (newHeight >= height) {
44 | this.resize(null, height);
45 | } else {
46 | this.resize(width);
47 | }
48 |
49 | }
50 |
51 | var x = (width / 2) - (imageWidth / 2);
52 | var y = (height / 2) - (imageHeight / 2);
53 |
54 | mkdirp(path.join(process.cwd(), "app", "App_Resources", outputPath), function() {
55 | image.background(bgColour)
56 | .gravity('Center')
57 | .extent(width, height)
58 | .write(path.join(process.cwd(), "app", "App_Resources", outputPath, outputFilename), function(error) {
59 | if (error) {
60 | console.error("Write file error", error);
61 | deferred.reject(error);
62 | } else {
63 | console.log(this.outname);
64 | deferred.resolve(this.outname);
65 | }
66 | });
67 | });
68 | }
69 |
70 | });
71 | return deferred.promise;
72 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "nativescript-media-generator",
3 | "version": "1.0.0",
4 | "description": "Generates NativeScript Media (Splashscreens, Icons,Images & Screenshots)",
5 | "main": "tns-media-gen.js",
6 | "bin": {
7 | "tns-media-gen": "tns-media-gen.js"
8 | },
9 | "preferGlobal": true,
10 | "scripts": {
11 | "clean": "npm i rimraf && rimraf node_modules dist app && npm i",
12 | "build": "npm run eslint",
13 | "pretest": "mkdir -p app/App_Resources/iOS && mkdir -p app/App_Resources/android",
14 | "test": "npm run pretest && jasmine-node --captureExceptions --color --junitreport --output dist/reports/ test/specs/",
15 | "eslint": "eslint \"*.js\"",
16 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r0 ",
17 | "changelog:add": "git add CHANGELOG.md && git commit -m 'updated CHANGELOG.md'",
18 | "release:pre": "npm run clean && npm run test",
19 | "release:post": "npm run changelog && npm run changelog:add",
20 | "release:major": "npm run release:pre && npm version major && npm run release:post && git push origin && git push origin --tags && npm run version-and-push",
21 | "release:minor": "npm run release:pre && npm version minor && npm run release:post && git push origin && git push origin --tags && npm run version-and-push",
22 | "release:patch": "npm run release:pre && npm version patch && npm run release:post && git push origin && git push origin --tags && npm run version-and-push",
23 | "version-and-push": "git push origin && git push origin --tags && npm run merge-and-publish",
24 | "merge-and-publish": "git checkout master && git merge develop && npm publish && git reset --hard && git clean -f"
25 | },
26 | "nativescript": {
27 | "platforms": {
28 | "ios": "1.1.0",
29 | "android": "1.1.0"
30 | }
31 | },
32 | "dependencies": {
33 | "async": "2.6.0",
34 | "filewalker": "0.1.3",
35 | "fs": "0.0.2",
36 | "gm": "1.23.1",
37 | "mkdirp": "0.5.1",
38 | "path": "0.12.7",
39 | "phantom": "4.0.12",
40 | "phantomjs-prebuilt": "2.1.16",
41 | "q": "1.5.1"
42 | },
43 | "devDependencies": {
44 | "conventional-changelog-cli": "1.3.12",
45 | "cross-env": "5.1.3",
46 | "eslint": "4.15.0",
47 | "eslint-loader": "1.9.0",
48 | "eslint-plugin-es6-recommended": "0.1.2",
49 | "eslint-plugin-import": "2.8.0",
50 | "jasmine-node": "1.14.5",
51 | "rimraf": "2.6.2"
52 | },
53 | "repository": {
54 | "type": "git",
55 | "url": "https://github.com/hypery2k/nativescript-media-generator.git"
56 | },
57 | "keywords": [
58 | "NativeScript",
59 | "icons",
60 | "splash",
61 | "screens",
62 | "images"
63 | ],
64 | "author": "Martin Reinhardt",
65 | "license": "MIT",
66 | "bugs": "https://github.com/hypery2k/nativescript-media-generator/issues",
67 | "homepage": "https://github.com/hypery2k/nativescript-media-generator",
68 | "engine-strict": true,
69 | "engines": {
70 | "node": ">= 4.4",
71 | "npm": ">= 3"
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # [1.0.0](https://github.com/hypery2k/nativescript-media-generator/compare/v0.2.4...v1.0.0) (2018-01-08)
3 |
4 |
5 | ### Bug Fixes
6 |
7 | * **config-error:** Resolve config not found error ([f2b6684](https://github.com/hypery2k/nativescript-media-generator/commit/f2b6684)), closes [#14](https://github.com/hypery2k/nativescript-media-generator/issues/14)
8 | * **convert-error:** Resolve resize error without giving width ([e73bed6](https://github.com/hypery2k/nativescript-media-generator/commit/e73bed6)), closes [#14](https://github.com/hypery2k/nativescript-media-generator/issues/14)
9 | * **node-env:** Correct command not found error ([4c264bc](https://github.com/hypery2k/nativescript-media-generator/commit/4c264bc)), closes [#14](https://github.com/hypery2k/nativescript-media-generator/issues/14)
10 | * **phantom-usage:** Use phantom 3.x to support node4+ ([2af5e89](https://github.com/hypery2k/nativescript-media-generator/commit/2af5e89))
11 |
12 |
13 | ### Features
14 |
15 | * **iPhoneX:** Support for iPhone X ([2c46388](https://github.com/hypery2k/nativescript-media-generator/commit/2c46388))
16 |
17 |
18 |
19 |
20 | ## [0.2.4](https://github.com/hypery2k/nativescript-media-generator/compare/v0.2.3...v0.2.4) (2017-03-02)
21 |
22 |
23 | ### Bug Fixes
24 |
25 | * **build:** Fix build error ([4ce81ae](https://github.com/hypery2k/nativescript-media-generator/commit/4ce81ae))
26 | * **build:** Fix build error ([cbf9d82](https://github.com/hypery2k/nativescript-media-generator/commit/cbf9d82))
27 | * **cli:** Fix binary command error ([a54e067](https://github.com/hypery2k/nativescript-media-generator/commit/a54e067)), closes [#13](https://github.com/hypery2k/nativescript-media-generator/issues/13)
28 |
29 |
30 |
31 |
32 | ## [0.2.3](https://github.com/hypery2k/nativescript-media-generator/compare/v0.2.2...v0.2.3) (2017-01-30)
33 |
34 |
35 | ### Bug Fixes
36 |
37 | * **node4:** Use older node for node4+ support ([a8ce11c](https://github.com/hypery2k/nativescript-media-generator/commit/a8ce11c))
38 | * **resizing:** Correct percentages for images ([27f7ad3](https://github.com/hypery2k/nativescript-media-generator/commit/27f7ad3))
39 |
40 |
41 |
42 |
43 | ## [0.2.2](https://github.com/hypery2k/nativescript-media-generator/compare/v0.2.1...v0.2.2) (2017-01-11)
44 |
45 |
46 | ### Bug Fixes
47 |
48 | * **splash-screen:** Correct android splash screen size ([f4f2d71](https://github.com/hypery2k/nativescript-media-generator/commit/f4f2d71))
49 |
50 |
51 |
52 |
53 | ## [0.2.1](https://github.com/hypery2k/nativescript-media-generator/compare/6aedc62...v0.2.1) (2016-12-13)
54 |
55 |
56 | ### Bug Fixes
57 |
58 | * **image-gen:** Correct property usage for image generation ([b21d7ce](https://github.com/hypery2k/nativescript-media-generator/commit/b21d7ce))
59 | * **module_missing:** Add missing async module ([6aedc62](https://github.com/hypery2k/nativescript-media-generator/commit/6aedc62))
60 | * **test:** Fix test errors ([a53c3b2](https://github.com/hypery2k/nativescript-media-generator/commit/a53c3b2))
61 | * **test:** FIx test errors ([3223ff6](https://github.com/hypery2k/nativescript-media-generator/commit/3223ff6))
62 |
63 |
64 | ### Features
65 |
66 | * **additional_images:** Allow additional images ([39673ca](https://github.com/hypery2k/nativescript-media-generator/commit/39673ca))
67 | * **images:** Support for images ([b2ba106](https://github.com/hypery2k/nativescript-media-generator/commit/b2ba106))
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/lib/splash_images.js:
--------------------------------------------------------------------------------
1 | module.exports = function splashImagesGenerator(config, mediaPath) {
2 | return [
3 | //iOS Splash
4 | {
5 | width: 640,
6 | height: 1136,
7 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
8 | filename: "Default-568h@2x.png",
9 | source: process.argv[2] || config.splash || config.image
10 | }, {
11 | width: 1024,
12 | height: 768,
13 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
14 | filename: "Default-Landscape.png",
15 | source: process.argv[2] || config.splash || config.image
16 | }, {
17 | width: 1536,
18 | height: 2048,
19 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
20 | filename: "Default-Portrait@2x.png",
21 | source: process.argv[2] || config.splash || config.image
22 | }, {
23 | width: 768,
24 | height: 1024,
25 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
26 | filename: "Default-Portrait.png",
27 | source: process.argv[2] || config.splash || config.image
28 | }, {
29 | width: 640,
30 | height: 960,
31 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
32 | filename: "Default@2x.png",
33 | source: process.argv[2] || config.splash || config.image
34 | }, {
35 | width: 320,
36 | height: 480,
37 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
38 | filename: "Default.png",
39 | source: process.argv[2] || config.splash || config.image
40 | }, {
41 | width: 750,
42 | height: 1344,
43 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
44 | filename: "Default-667h.png",
45 | source: process.argv[2] || config.splash || config.image
46 | }, {
47 | width: 1242,
48 | height: 2208,
49 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
50 | filename: "Default-736h.png",
51 | source: process.argv[2] || config.splash || config.image
52 | }, {
53 | width: 2208,
54 | height: 1242,
55 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
56 | filename: "Default-Landscape-736h.png",
57 | source: process.argv[2] || config.splash || config.image
58 | }, {
59 | width: 768,
60 | height: 1024,
61 | path: "iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset",
62 | filename: "LaunchScreen-AspectFill.png",
63 | source: process.argv[2] || config.splash || config.image
64 | }, {
65 | width: 1536,
66 | height: 2048,
67 | path: "iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset",
68 | filename: "LaunchScreen-AspectFill@2x.png",
69 | source: process.argv[2] || config.splash || config.image
70 | }, {
71 | width: 384,
72 | height: 512,
73 | path: "iOS/Assets.xcassets/LaunchScreen.Center.imageset",
74 | filename: "LaunchScreen-Center.png",
75 | source: process.argv[2] || config.splash || config.image
76 | }, {
77 | width: 768,
78 | height: 1024,
79 | path: "iOS/Assets.xcassets/LaunchScreen.Center.imageset",
80 | filename: "LaunchScreen-Center@2x.png",
81 | source: process.argv[2] || config.splash || config.image
82 | }, {
83 | width: 1125,
84 | height: 2436,
85 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
86 | filename: "Default-1125h.png",
87 | source: process.argv[2] || config.splash || config.image
88 | }, {
89 | width: 2436,
90 | height: 1125,
91 | path: "iOS/Assets.xcassets/LaunchImage.launchimage",
92 | filename: "Default-Landscape-X.png",
93 | source: process.argv[2] || config.splash || config.image
94 | },
95 | // Android
96 | {
97 | width: 480,
98 | path: "Android/drawable-mdpi",
99 | filename: "splash.png",
100 | source: process.argv[2] || config.splash || config.image
101 | },
102 | {
103 | width: 800,
104 | path: "Android/drawable-hdpi",
105 | filename: "splash.png",
106 | source: process.argv[2] || config.splash || config.image
107 | }, {
108 | width: 960,
109 | path: "Android/drawable-xhdpi",
110 | filename: "splash.png",
111 | source: process.argv[2] || config.splash || config.image
112 | }, {
113 | width: 1600,
114 | path: "Android/drawable-xxhdpi",
115 | filename: "splash.png",
116 | source: process.argv[2] || config.splash || config.image
117 | }, {
118 | width: 1920,
119 | path: "Android/drawable-xxxhdpi",
120 | filename: "splash.png",
121 | source: process.argv[2] || config.splash || config.image
122 | }
123 |
124 | ];
125 | }
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | plugins: [
2 | "import",
3 | "es6-recommended"
4 | ]
5 |
6 | parserOptions: {
7 | ecmaVersion: 6,
8 | sourceType: "module"
9 | }
10 |
11 | ecmaFeatures:
12 | modules: true
13 | jsx: true
14 |
15 | env:
16 | amd: true
17 | browser: true
18 | es6: true
19 | jquery: false
20 | node: true
21 |
22 | # http://eslint.org/docs/rules/
23 | rules:
24 | import/no-unresolved: [2, {commonjs: true, amd: true}]
25 | import/named: 2
26 | import/namespace: 2
27 | import/default: 2
28 | import/export: 2
29 | # Possible Errors
30 | comma-dangle: [2, never]
31 | no-cond-assign: 2
32 | no-console: 0
33 | no-constant-condition: 2
34 | no-control-regex: 2
35 | no-debugger: 2
36 | no-dupe-args: 2
37 | no-dupe-keys: 2
38 | no-duplicate-case: 2
39 | no-empty-character-class: 2
40 | no-ex-assign: 2
41 | no-extra-boolean-cast: 2
42 | no-extra-parens: 0
43 | no-extra-semi: 2
44 | no-func-assign: 2
45 | no-inner-declarations: [2, functions]
46 | no-invalid-regexp: 2
47 | no-irregular-whitespace: 2
48 | no-negated-in-lhs: 2
49 | no-obj-calls: 2
50 | no-regex-spaces: 2
51 | no-sparse-arrays: 2
52 | no-unexpected-multiline: 2
53 | no-unreachable: 2
54 | use-isnan: 2
55 | valid-jsdoc: 0
56 | valid-typeof: 2
57 |
58 | # Best Practices
59 | accessor-pairs: 2
60 | block-scoped-var: 0
61 | complexity: [2, 8]
62 | consistent-return: 0
63 | curly: 0
64 | default-case: 0
65 | dot-location: 0
66 | dot-notation: 0
67 | eqeqeq: 2
68 | guard-for-in: 2
69 | no-alert: 2
70 | no-caller: 2
71 | no-case-declarations: 2
72 | no-div-regex: 2
73 | no-else-return: 0
74 | no-empty-pattern: 2
75 | no-eq-null: 2
76 | no-eval: 2
77 | no-extend-native: 2
78 | no-extra-bind: 2
79 | no-fallthrough: 2
80 | no-floating-decimal: 0
81 | no-implicit-coercion: 0
82 | no-implied-eval: 2
83 | no-invalid-this: 0
84 | no-iterator: 2
85 | no-labels: 0
86 | no-lone-blocks: 2
87 | no-loop-func: 2
88 | no-magic-number: 0
89 | no-multi-spaces: 0
90 | no-multi-str: 0
91 | no-native-reassign: 2
92 | no-new-func: 2
93 | no-new-wrappers: 2
94 | no-new: 2
95 | no-octal-escape: 2
96 | no-octal: 2
97 | no-proto: 2
98 | no-redeclare: 2
99 | no-return-assign: 2
100 | no-script-url: 2
101 | no-self-compare: 2
102 | no-sequences: 0
103 | no-throw-literal: 0
104 | no-unused-expressions: 2
105 | no-useless-call: 2
106 | no-useless-concat: 2
107 | no-void: 2
108 | no-warning-comments: 0
109 | no-with: 2
110 | radix: 2
111 | vars-on-top: 0
112 | wrap-iife: 2
113 | yoda: 0
114 |
115 | # Strict
116 | strict: 0
117 |
118 | # Variables
119 | init-declarations: 0
120 | no-catch-shadow: 2
121 | no-delete-var: 2
122 | no-label-var: 2
123 | no-shadow-restricted-names: 2
124 | no-shadow: 0
125 | no-undef-init: 2
126 | no-undef: 0
127 | no-undefined: 0
128 | no-unused-vars: 0
129 | no-use-before-define: 0
130 |
131 | # Node.js and CommonJS
132 | callback-return: 2
133 | global-require: 2
134 | handle-callback-err: 2
135 | no-mixed-requires: 0
136 | no-new-require: 0
137 | no-path-concat: 2
138 | no-process-exit: 2
139 | no-restricted-modules: 0
140 | no-sync: 0
141 |
142 | # Stylistic Issues
143 | array-bracket-spacing: 0
144 | block-spacing: 0
145 | brace-style: 0
146 | camelcase: 0
147 | comma-spacing: 0
148 | comma-style: 0
149 | computed-property-spacing: 0
150 | consistent-this: 0
151 | eol-last: 0
152 | func-names: 0
153 | func-style: 0
154 | id-length: 0
155 | id-match: 0
156 | indent: 0
157 | jsx-quotes: 0
158 | key-spacing: 0
159 | linebreak-style: 0
160 | lines-around-comment: 0
161 | max-depth: 0
162 | max-len: 0
163 | max-nested-callbacks: 0
164 | max-params: 0
165 | max-statements: [2, 30]
166 | new-cap: 0
167 | new-parens: 0
168 | newline-after-var: 0
169 | no-array-constructor: 0
170 | no-bitwise: 0
171 | no-continue: 0
172 | no-inline-comments: 0
173 | no-lonely-if: 0
174 | no-mixed-spaces-and-tabs: 0
175 | no-multiple-empty-lines: 0
176 | no-negated-condition: 0
177 | no-nested-ternary: 0
178 | no-new-object: 0
179 | no-plusplus: 0
180 | no-restricted-syntax: 0
181 | no-spaced-func: 0
182 | no-ternary: 0
183 | no-trailing-spaces: 0
184 | no-underscore-dangle: 0
185 | no-unneeded-ternary: 0
186 | object-curly-spacing: 0
187 | one-var: 0
188 | operator-assignment: 0
189 | operator-linebreak: 0
190 | padded-blocks: 0
191 | quote-props: 0
192 | quotes: 0
193 | require-jsdoc: 0
194 | semi-spacing: 0
195 | semi: 0
196 | sort-vars: 0
197 | space-after-keywords: 0
198 | space-before-blocks: 0
199 | space-before-function-paren: 0
200 | space-before-keywords: 0
201 | space-in-parens: 0
202 | space-infix-ops: 0
203 | space-return-throw-case: 0
204 | space-unary-ops: 0
205 | spaced-comment: 0
206 | wrap-regex: 0
207 |
208 | # ECMAScript 6
209 | arrow-body-style: 0
210 | arrow-parens: 0
211 | arrow-spacing: 0
212 | constructor-super: 0
213 | generator-star-spacing: 0
214 | no-arrow-condition: 0
215 | no-class-assign: 0
216 | no-const-assign: 0
217 | no-dupe-class-members: 0
218 | no-this-before-super: 0
219 | no-var: 0
220 | object-shorthand: 0
221 | prefer-arrow-callback: 0
222 | prefer-const: 0
223 | prefer-reflect: 0
224 | prefer-spread: 0
225 | prefer-template: 0
226 | require-yield: 0
227 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NativeScript Media Generator
2 |
3 | [](https://greenkeeper.io/)
4 | [](https://travis-ci.org/hypery2k/nativescript-media-generator) [](http://badge.fury.io/js/nativescript-media-generator) [](https://david-dm.org/hypery2k/nativescript-media-generator) [](https://david-dm.org/hypery2k/nativescript-media-generator#info=devDependencies)
5 |
6 | [](https://www.bountysource.com/trackers/11673029-hypery2k-nativescript-media-generatorerator?utm_source=11673029&utm_medium=shield&utm_campaign=TRACKER_BADGE) [](https://flattr.com/submit/auto?user_id=mreinhardt&url=https://github.com/hypery2k/nativescript-media-generator&title=badges&language=&tags=github&category=software)
7 |
8 | > CLI Utility that generates NativeScript image assets required for images, icons, and splash screens.
9 |
10 | [](https://nodei.co/npm/nativescript-media-generator/)
11 |
12 | It requires your logo to have a solid background colour but does not distort or lose any image content so everything is at the maximum size without loss.
13 |
14 | ## Installation
15 |
16 | Need imagemagick
17 |
18 | On Debian/Ubuntu:
19 |
20 | ```bash
21 | sudo apt-get install imagemagick
22 | ```
23 |
24 | on OS X:
25 |
26 | ```bash
27 | brew install imagemagick
28 | ```
29 |
30 | ```bash
31 | $ npm install -g nativescript-media-generator
32 | ```
33 |
34 | Once installed, cd to the root of your NativeScript application and run:
35 | ```bash
36 | $ tns-media-gen
37 | ```
38 |
39 |
40 | Or if you want to use the development version (nightly build), which maybe not stable!:
41 |
42 | ```
43 | tns plugin add nativescript-media-generator@next
44 | ```
45 |
46 | ### Usage
47 |
48 | If using this plugin, we recommand an **1900x2850** Portrait Area as basis layout.
49 |
50 | ```bash
51 | $ tns-media-gen logo.jpg fff
52 | ```
53 |
54 | To create the config
55 |
56 | ```bash
57 | $ tns-media-gen init
58 | ```
59 |
60 | If you have created a `mediagen-config.json` file (see below), you can just run:
61 | ```bash
62 | $ tns-media-gen
63 | ```
64 |
65 | This will overwrite all logos and splash screen images in the `/app` directory with the correct sizes and in the correct location for NativeScript (As at 3.5)
66 | > The recommended image or logo size is 2000px x 2000px. Its not a problem if the logo isn't square.
67 |
68 | It also creates a `/Media` directory that has images for the Apple and Android stores such as an app icon.
69 |
70 | ## Custom Assets
71 | You can create additional custom images if you need to submit to alternative app stores or have other needs that we haven't thought of yet.
72 |
73 | Simply go to your project directory and run
74 | ```bash
75 | $ tns-media-gen init
76 | ```
77 |
78 | It will create an example file called `mediagen-config.json` which you can now edit. Add as many or few files as you need to the array.
79 |
80 | > Note: The default path for files is the `/platforms` directory, you might need to use `../` as in the example below
81 |
82 | ### Example `mediagen-config.json`
83 | ```javascript
84 | {
85 | "mediaPath": "media",
86 | "icon": {
87 | "filename": "etc/images/icon.png",
88 | "background": "fff"
89 | },
90 | "splash": {
91 | "filename": "etc/images/splash.png",
92 | "background": "fff"
93 | },
94 | "images": [
95 | {
96 | "filename": "icon.png",
97 | "alias": "logo.png"
98 | },
99 | {
100 | "filename": "icon.png",
101 | "alias": "logo_login.png"
102 | }
103 | ]
104 | }
105 | ```
106 |
107 | ## Screenshots (Experimental)
108 | Screenshots are a new feature that use PhantomJS to quickly generate a number of the screenshot assets you need when submitting to the app store. You need your local development server running when you execute `mediagen` so it can access the NativeScript versions of the files. Of course this won't be able to access a number of things in lots of apps but hopefully it should get you up on the app store pretty quickly.
109 | This is still pretty experimental, and also please be aware that it may seem to hang for a minute or so before you see the screenshots being generated (it does need to visit the page each time!)
110 |
111 |
112 | ## Config
113 | The config variables are below:
114 | - mediaPath: path to the output folder
115 | - icon: icon image
116 | - filename: path to source filename
117 | - background: solid colour in hex
118 | - splash: splash image
119 | - filename: path to source filename
120 | - background: solid colour in hex
121 | - images: an array of images which should generate for both platforms (**NOTE**: The biggest resolutution (100%) needed is 640dpi)
122 | - filename: the output file name with extension
123 | - alias to use (target filename)
124 | - custom images: an array of custom image objects for additional media if desired
125 | - width: the width of the image in pixels
126 | - height: the height of the image in pixels
127 | - path: the directory to save the output
128 | - filename: the output file name with extension
129 | - source: the source file, same definition as an icon or splash above
130 | - filename: path to source filename
131 | - background: solid colour in hex
132 | - screenshots: An array of screenshot objects
133 | - url: url to your local development server
134 | - name: name of the page for easy reference later on
135 |
--------------------------------------------------------------------------------
/lib/generate_icon_sets.js:
--------------------------------------------------------------------------------
1 | var q = require('q'),
2 | path = require('path'),
3 | fs = require('fs'),
4 | gm = require('gm').subClass({ imageMagick: true });
5 |
6 | module.exports = function generateIconSets(filename, source, iOSPath) { /*eslint complexity: [error, 22]*/
7 | return [
8 | //IOS Icons
9 | {
10 | width: 180,
11 | height: 180,
12 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
13 | filename: filename.replace('.', '-60@3x.'),
14 | source: source
15 | }, {
16 | width: 120,
17 | height: 120,
18 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
19 | filename: filename.replace('.', '-60@2x.'),
20 | source: source
21 | }, {
22 | width: 40,
23 | height: 40,
24 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
25 | filename: filename.replace('.', '-40.'),
26 | source: source
27 | }, {
28 | width: 80,
29 | height: 80,
30 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
31 | filename: filename.replace('.', '-40@2x.'),
32 | source: source
33 | }, {
34 | width: 120,
35 | height: 120,
36 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
37 | filename: filename.replace('.', '-40@3x.'),
38 | source: source
39 | }, {
40 | width: 50,
41 | height: 50,
42 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
43 | filename: filename.replace('.', '-50.'),
44 | source: source
45 | }, {
46 | width: 100,
47 | height: 100,
48 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
49 | filename: filename.replace('.', '-50@2x.'),
50 | source: source
51 | }, {
52 | width: 60,
53 | height: 60,
54 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
55 | filename: filename.replace('.', '-60.'),
56 | source: source
57 | }, {
58 | width: 72,
59 | height: 72,
60 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
61 | filename: filename.replace('.', '-72.'),
62 | source: source
63 | }, {
64 | width: 144,
65 | height: 144,
66 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
67 | filename: filename.replace('.', '-72@2x.'),
68 | source: source
69 | }, {
70 | width: 76,
71 | height: 76,
72 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
73 | filename: filename.replace('.', '-76.'),
74 | source: source
75 | }, {
76 | width: 152,
77 | height: 152,
78 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
79 | filename: filename.replace('.', '-76@2x.'),
80 | source: source
81 | }, {
82 | width: 167,
83 | height: 167,
84 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
85 | filename: filename.replace('.', '-83.5@2x.'),
86 | source: source
87 | }, {
88 | width: 120,
89 | height: 120,
90 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
91 | filename: filename.replace('.', '-120.'),
92 | source: source
93 | }, {
94 | width: 29,
95 | height: 29,
96 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
97 | filename: filename.replace('.', '-29.'),
98 | source: source
99 | }, {
100 | width: 58,
101 | height: 58,
102 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
103 | filename: filename.replace('.', '-29@2x.'),
104 | source: source
105 | }, {
106 | width: 87,
107 | height: 87,
108 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
109 | filename: filename.replace('.', '-29@3x.'),
110 | source: source
111 | }, {
112 | width: 57,
113 | height: 57,
114 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
115 | filename: filename.replace('.', '-57.'),
116 | source: source
117 | }, {
118 | width: 114,
119 | height: 114,
120 | path: 'iOS/Assets.xcassets' + (iOSPath ? '/' + iOSPath : ''),
121 | filename: filename.replace('.', '-57@2x.'),
122 | source: source
123 | },
124 |
125 | //Android
126 | {
127 | width: 72,
128 | height: 72,
129 | path: "Android/drawable-hdpi",
130 | filename: filename,
131 | source: source
132 | }, {
133 | width: 48,
134 | height: 48,
135 | path: "Android/drawable-mdpi",
136 | filename: filename,
137 | source: source
138 | }, {
139 | width: 96,
140 | height: 96,
141 | path: "Android/drawable-xhdpi",
142 | filename: filename,
143 | source: source
144 | }, {
145 | width: 144,
146 | height: 144,
147 | path: "Android/drawable-xxhdpi",
148 | filename: filename,
149 | source: source
150 | }, {
151 | width: 345,
152 | height: 345,
153 | path: "Android/drawable-xxxhdpi",
154 | filename: filename,
155 | source: source
156 | }
157 |
158 | ]
159 | }
--------------------------------------------------------------------------------
/screenshots.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var phantom = require('phantom'),
4 | path = require('path'),
5 | q = require('q'),
6 | mkdirp = require('mkdirp'),
7 | async = require('async'),
8 | pkg = require('./package.json'),
9 | config = require(process.cwd() + "/mediagen-config");
10 |
11 | var ph;
12 | var mediaPath = config.mediaPath || 'Media';
13 |
14 | function evaluate(page, func) {
15 | var args = [].slice.call(arguments, 2);
16 | var fn = "function() { return (" + func.toString() + ").apply(this, " + JSON.stringify(args) + ");}";
17 | return page.evaluate(fn);
18 | }
19 |
20 | var output = {
21 | generate: function (url, width, height, devicePixelRatio, savePath, saveFilename) {
22 | var deferred = q.defer();
23 |
24 | if (!url || !width || !height || !savePath || !saveFilename) {
25 | deferred.reject({
26 | error: "A required argument is missing"
27 | });
28 | return deferred.promise;
29 | }
30 | if (!ph) {
31 | phantom.create(function (newPh) {
32 | ph = newPh;
33 | doGen();
34 | })
35 | } else {
36 | doGen();
37 | }
38 |
39 | function doGen() {
40 | ph.createPage(function (page) {
41 | page.setViewportSize(width, height, function () {
42 | page.open(url, function () {
43 | if (devicePixelRatio && devicePixelRatio !== 1) {
44 | evaluate(page, function (devicePixelRatio) {
45 | document.body.style.webkitTransform = "scale(" + devicePixelRatio + ")";
46 | document.body.style.webkitTransformOrigin = "0% 0%";
47 | document.body.style.width = (100 / devicePixelRatio) + "%";
48 | }, devicePixelRatio);
49 | }
50 | mkdirp(path.resolve(__dirname, savePath), function (err) {
51 | if (err) {
52 | deferred.reject(err);
53 | }
54 | page.render(savePath + "/" + saveFilename, {
55 | format: 'jpg',
56 | quality: '60'
57 | }, function (err) {
58 | console.log("Generated screenshot", url, savePath, saveFilename);
59 | if (err) {
60 | deferred.reject(err);
61 | } else {
62 | deferred.resolve({
63 | success: true
64 | });
65 | }
66 | page.close();
67 | });
68 | });
69 | });
70 | });
71 | });
72 | }
73 |
74 | return deferred.promise;
75 | },
76 | generateAll: function () {
77 | var deferred = q.defer();
78 | async.eachLimit(output.screenshots, 1, function (item, cb1) {
79 | async.eachLimit(output.pages, 1, function (page, cb2) {
80 | output.generate(page.url, item.width, item.height, item.devicePixelRatio, item.savePath, item.filename + page.name + ".jpg")
81 | .then(function (result) {
82 | cb2();
83 | })
84 | .catch(cb2)
85 | }, function (err) {
86 | cb1(err);
87 | })
88 | }, function (err) {
89 | if (ph) ph.exit();
90 | if (err) {
91 | deferred.reject(err);
92 | } else {
93 | deferred.resolve(true);
94 | }
95 | });
96 | return deferred.promise;
97 | },
98 | pages: [],
99 | screenshots: [{
100 | filename: "android-10in-1280x720-land",
101 | width: 1280,
102 | height: 720,
103 | savePath: mediaPath + '/android/screenshots/10in'
104 | }, {
105 | filename: "android-10in-2048x1152-land",
106 | width: 2048,
107 | height: 1152,
108 | savePath: mediaPath + '/android/screenshots/10in'
109 | }, {
110 | filename: "android-7in-1280x800-land",
111 | width: 1280,
112 | height: 800,
113 | savePath: mediaPath + '/android/screenshots/7in'
114 | }, {
115 | filename: "android-10in-1280x720-port",
116 | width: 720,
117 | height: 1280,
118 | savePath: mediaPath + '/android/screenshots/10in'
119 | }, {
120 | filename: "android-10in-2048x1152-port",
121 | width: 1152,
122 | height: 2048,
123 | savePath: mediaPath + '/android/screenshots/10in'
124 | }, {
125 | filename: "android-7in-1280x800-port",
126 | width: 800,
127 | height: 1280,
128 | savePath: mediaPath + '/android/screenshots/7in'
129 | }, {
130 | filename: "android-4in-1280x720-land",
131 | width: 1920,
132 | height: 1080,
133 | savePath: mediaPath + '/android/screenshots/4in'
134 | }, {
135 | filename: "android-4in-1280x720-port",
136 | width: 1080,
137 | height: 1920,
138 | savePath: mediaPath + '/android/screenshots/4in'
139 | }, {
140 | filename: "ipad-1024x768-land",
141 | width: 1024,
142 | height: 768,
143 | savePath: mediaPath + '/ios/screenshots/ipad'
144 | }, {
145 | filename: "ipadretina-2048x1536-land",
146 | width: 2048,
147 | height: 1536,
148 | devicePixelRatio: 2,
149 | savePath: mediaPath + '/ios/screenshots/ipadRetina'
150 | }, {
151 | filename: "iphone4-960x640-land",
152 | width: 960,
153 | height: 640,
154 | savePath: mediaPath + '/ios/screenshots/iphone4'
155 | }, {
156 | filename: "iphone5-1136x640-land",
157 | width: 1136,
158 | height: 640,
159 | savePath: mediaPath + '/ios/screenshots/iphone5'
160 | }, {
161 | filename: "ipad-1024x768-port",
162 | width: 768,
163 | height: 1024,
164 | savePath: mediaPath + '/ios/screenshots/ipad'
165 | }, {
166 | filename: "ipadretina-2048x1536-port",
167 | width: 1536,
168 | height: 2048,
169 | devicePixelRatio: 2,
170 | savePath: mediaPath + '/ios/screenshots/ipadRetina'
171 | }, {
172 | filename: "iphone4-640x960-port",
173 | width: 640,
174 | height: 960,
175 | savePath: mediaPath + '/ios/screenshots/iphone4'
176 | }, {
177 | filename: "iphone5-640x1136-port",
178 | width: 640,
179 | height: 1136,
180 | savePath: mediaPath + '/ios/screenshots/iphone5'
181 | }, {
182 | filename: "iphone6p-1242x2208-port",
183 | width: 1242,
184 | height: 2208,
185 | savePath: mediaPath + '/ios/screenshots/iphone6p'
186 | }, {
187 | filename: "iphone6p-2208x1242-land",
188 | width: 2208,
189 | height: 1242,
190 | savePath: mediaPath + '/ios/screenshots/iphone6p'
191 | }, {
192 | filename: "iphone6-1334x750-land",
193 | width: 1334,
194 | height: 750,
195 | savePath: mediaPath + '/ios/screenshots/iphone6'
196 | }, {
197 | filename: "iphone6-750x1334-port",
198 | width: 750,
199 | height: 1334,
200 | savePath: mediaPath + '/ios/screenshots/iphone6'
201 | }]
202 | };
203 | module.exports = output;
204 |
--------------------------------------------------------------------------------
/tns-media-gen.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | "use strict";
4 |
5 | var gm = require('gm').subClass({ imageMagick: true }),
6 | mkdirp = require('mkdirp'),
7 | path = require('path'),
8 | fs = require('fs'),
9 | screenshots = require('./screenshots'),
10 | q = require('q'),
11 | resize = require('./lib/resize'),
12 | generateImageSets = require('./lib/generate_image_sets'),
13 | generateIconSets = require('./lib/generate_icon_sets'),
14 | storeImagesGenerator = require('./lib/store_images'),
15 | splashImagesGenerator = require('./lib/splash_images'),
16 | config,
17 | mediaPath;
18 |
19 |
20 | function generate() {
21 | var deferred = q.defer();
22 |
23 | fs.readdir(path.join(process.cwd(), "app", "App_Resources", "iOS"), function(err, result) { /*eslint complexity: [error, 55]*/
24 |
25 | if (err) {
26 | throw err;
27 | } else {
28 |
29 | if (!config && config.image) config.image = {
30 | filename: "./icon.png"
31 | };
32 |
33 | var storeImages = storeImagesGenerator(config, mediaPath),
34 | splashImages = splashImagesGenerator(config, mediaPath),
35 | source = process.argv[2] || config.icon || config.image,
36 | images = generateIconSets('icon-20.png', source, 'AppIcon.appiconset')
37 |
38 | images.push({
39 | width: 1024,
40 | height: 1024,
41 | path: 'iOS/Assets.xcassets/AppIcon.appiconset',
42 | filename: "icon-1024.png",
43 | source: source
44 | });
45 | images.push({
46 | width: 180,
47 | height: 180,
48 | path: 'iOS/Assets.xcassets/AppIcon.appiconset',
49 | filename: "icon-60@3x.png",
50 | source: source
51 | });
52 |
53 | images = images.concat(splashImages);
54 |
55 | if (config.screenshots && config.screenshots.length) {
56 | screenshots.pages = config.screenshots;
57 | }
58 |
59 |
60 | if (config.images) {
61 | config.images.forEach(function(item) {
62 | var additionalImages = generateImageSets(item.alias ? item.alias : item.filename, { filename: item.filename });
63 | additionalImages.forEach(function(additionalImage) {
64 | images.push(additionalImage);
65 | });
66 | });
67 | }
68 |
69 | if (config.customImages) {
70 | config.customImages.forEach(function(item) {
71 | images.push(item);
72 | });
73 | }
74 |
75 |
76 | if (!process.argv[2] && !config.image && (!config.icon && !config.splash)) {
77 | console.log('You must specify a filename as the second argument, or in a config file');
78 | } else if (!process.argv[3] && !config.background && (!config.icon && !config.splash)) {
79 | console.log("Please specify a background colour in hex values as the third argument, or in a config file");
80 | } else {
81 |
82 | var totalImages = images.length + (screenshots.pages.length * screenshots.screenshots.length);
83 | console.log("------------------------------");
84 | console.log(" nativescript-media-generator");
85 | console.log("------------------------------");
86 | console.log("Generating " + totalImages + " images so you don't have to");
87 | console.log("------------------------------");
88 | screenshots.generateAll();
89 | images.forEach(function(image) {
90 | var background, sourceImage;
91 | if (process.argv[2]) {
92 | /*
93 | Legacy Configuration
94 | */
95 | if (process.argv[3]) {
96 | background = process.argv[3];
97 | } else {
98 | background = config.background;
99 | }
100 | if (process.argv[2]) {
101 | sourceImage = process.argv[2];
102 | } else {
103 | sourceImage = config.image;
104 | }
105 | } else {
106 | if (image.source) {
107 | sourceImage = image.source.filename;
108 | background = image.source.background;
109 | }
110 | }
111 | if (sourceImage) {
112 | resize(image.width, image.height, '#' + background, sourceImage, image.filename, image.path);
113 |
114 | }
115 | });
116 | deferred.resolve();
117 | }
118 | }
119 | });
120 | return deferred.promise;
121 | }
122 |
123 | function genConfig() {
124 | var deferred = q.defer();
125 | var destFile = path.join(process.cwd(), "mediagen-config.json");
126 |
127 | fs.writeFile(destFile, JSON.stringify({
128 | "icon": { "filename": "icon.png", "background": "fff" },
129 | "splash": { "filename": "splash.png", "background": "fff" },
130 | "customImages": [{
131 | "width": 120,
132 | "height": 120,
133 | "path": "../../" + mediaPath + "/custom",
134 | "filename": "outputFilename.png",
135 | "source": { "filename": "image.png", "background": "fff" }
136 | }],
137 | "screenshots": [{ "url": "http://www.google.com", "name": "homepage" }]
138 | }, null, 4), function() {
139 | deferred.resolve("success");
140 | });
141 | console.log("Created `mediagen-config.json` file in the current directory.");
142 | return deferred.promise;
143 | }
144 |
145 | try { /*eslint global-require: off*/
146 | config = require(process.cwd() + "/mediagen-config");
147 | mediaPath = config.mediaPath || 'Media';
148 | } catch (e) {
149 | if (process.argv[2] !== "init") {
150 | console.log("Could not find configuration file. To create one run `$ mediagen init`");
151 | }
152 | }
153 |
154 | switch (process.argv[2]) {
155 | case "init":
156 | genConfig();
157 | break;
158 | default:
159 | generate();
160 | }
161 |
162 | module.exports = {
163 | __resize: resize,
164 | __generate: generate,
165 | __genConfig: genConfig
166 | };
--------------------------------------------------------------------------------