Skip to content

Commit

Permalink
feat: --skip-config option for skipping config.xml read/write
Browse files Browse the repository at this point in the history
Also clean up some docs and config structure.
  • Loading branch information
imhoffd committed Mar 23, 2020
1 parent 58fb49e commit 6250426
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 74 deletions.
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Resource Generator

This tool will crop and resize JPEG and PNG source images to generate images for modern iOS and Android devices. It will also register the generated images in `config.xml` so that Cordova projects are updated accordingly.
This tool will crop and resize JPEG and PNG source images to generate icons and splash screens for modern iOS, Android, and Windows. `cordova-res` was developed for use with Cordova, but Capacitor and other native runtimes are supported.

## Install

Expand All @@ -10,7 +10,7 @@ $ npm install -g cordova-res

## Usage

`cordova-res` must run at the root of a Cordova project, such as:
`cordova-res` expects a Cordova project structure such as:

```
resources/
Expand All @@ -19,8 +19,9 @@ resources/
config.xml
```

* `resources/icon.png` must be at least 1024×1024px
* `resources/splash.png` must be at least 2732×2732px
* `resources/icon.(png|jpg)` must be at least 1024×1024px
* `resources/splash.(png|jpg)` must be at least 2732×2732px
* `config.xml` is optional. If present, the generated images are registered accordingly

To generate resources with all the default options, just run:

Expand All @@ -34,7 +35,7 @@ $ cordova-res
$ cordova-res ios
```

Otherwise, `cordova-res` looks for platforms in `config.xml` (e.g. `<platform name="ios">`) and generates resources only for them.
Otherwise, if `config.xml` exists, `cordova-res` will look for platforms (e.g. `<platform name="ios">`) and generate resources only for the configured platforms.

#### Documentation

Expand All @@ -55,7 +56,20 @@ A color may also be used for the icon background by specifying the `--icon-backg

Regular Android icons will still be generated as a fallback for Android devices that do not support adaptive icons.

:memo: **Note**: Cordova 9+ and `cordova-android` 8+ is required.
:memo: **Note**: For Cordova apps, Cordova 9+ and `cordova-android` 8+ is required.

### Capacitor

To use `cordova-res` in Capacitor and other native runtimes, it is recommended to use `--skip-config` (skips reading & writing to Cordova's `config.xml` file) and `--copy` (copies generated resources into native projects).

For example, to generate icons and splash screens for iOS and Android in Capacitor, run:

```bash
$ cordova-res ios --skip-config --copy
$ cordova-res android --skip-config --copy
```

You can use `--ios-project` and `--android-project` to specify the native project directories into which these resources are copied. By default, `cordova-res` copies Android resources into `android/` and iOS resources into `ios/` (the directories Capacitor uses).

### Tips

Expand Down
113 changes: 107 additions & 6 deletions src/__tests__/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,122 @@ import { Options } from '..';
import { generateRunOptions, parseOptions } from '../cli';
import { Platform } from '../platform';

function generatePlatformsConfig(resourcesDirectory: string) {
return {
android: {
'adaptive-icon': {
background: {
sources: [
`${resourcesDirectory}/android/icon-background.png`,
`${resourcesDirectory}/android/icon-background.jpg`,
`${resourcesDirectory}/android/icon-background.jpeg`,
],
},
foreground: {
sources: [
`${resourcesDirectory}/android/icon-foreground.png`,
`${resourcesDirectory}/android/icon-foreground.jpg`,
`${resourcesDirectory}/android/icon-foreground.jpeg`,
],
},
icon: {
sources: [
`${resourcesDirectory}/android/icon.png`,
`${resourcesDirectory}/android/icon.jpg`,
`${resourcesDirectory}/android/icon.jpeg`,
`${resourcesDirectory}/icon.png`,
`${resourcesDirectory}/icon.jpg`,
`${resourcesDirectory}/icon.jpeg`,
],
},
},
icon: {
sources: [
`${resourcesDirectory}/android/icon.png`,
`${resourcesDirectory}/android/icon.jpg`,
`${resourcesDirectory}/android/icon.jpeg`,
`${resourcesDirectory}/icon.png`,
`${resourcesDirectory}/icon.jpg`,
`${resourcesDirectory}/icon.jpeg`,
],
},
splash: {
sources: [
`${resourcesDirectory}/android/splash.png`,
`${resourcesDirectory}/android/splash.jpg`,
`${resourcesDirectory}/android/splash.jpeg`,
`${resourcesDirectory}/splash.png`,
`${resourcesDirectory}/splash.jpg`,
`${resourcesDirectory}/splash.jpeg`,
],
},
},
ios: {
icon: {
sources: [
`${resourcesDirectory}/ios/icon.png`,
`${resourcesDirectory}/ios/icon.jpg`,
`${resourcesDirectory}/ios/icon.jpeg`,
`${resourcesDirectory}/icon.png`,
`${resourcesDirectory}/icon.jpg`,
`${resourcesDirectory}/icon.jpeg`,
],
},
splash: {
sources: [
`${resourcesDirectory}/ios/splash.png`,
`${resourcesDirectory}/ios/splash.jpg`,
`${resourcesDirectory}/ios/splash.jpeg`,
`${resourcesDirectory}/splash.png`,
`${resourcesDirectory}/splash.jpg`,
`${resourcesDirectory}/splash.jpeg`,
],
},
},
windows: {
icon: {
sources: [
`${resourcesDirectory}/windows/icon.png`,
`${resourcesDirectory}/windows/icon.jpg`,
`${resourcesDirectory}/windows/icon.jpeg`,
`${resourcesDirectory}/icon.png`,
`${resourcesDirectory}/icon.jpg`,
`${resourcesDirectory}/icon.jpeg`,
],
},
splash: {
sources: [
`${resourcesDirectory}/windows/splash.png`,
`${resourcesDirectory}/windows/splash.jpg`,
`${resourcesDirectory}/windows/splash.jpeg`,
`${resourcesDirectory}/splash.png`,
`${resourcesDirectory}/splash.jpg`,
`${resourcesDirectory}/splash.jpeg`,
],
},
},
};
}

describe('cordova-res', () => {

describe('cli', () => {

describe('parseOptions', () => {

const DEFAULT_OPTIONS: Options = {
directory: process.cwd(),
logstream: process.stdout,
errstream: process.stderr,
resourcesDirectory: 'resources',
nativeProject: {
enabled: false,
androidProjectDirectory: '',
iosProjectDirectory: '',
platforms: generatePlatformsConfig('resources'),
projectConfig: {
android: { directory: 'android' },
ios: { directory: 'ios' },
windows: { directory: 'windows' },
},
skipConfig: false,
copy: false,
};

it('should parse default options with no arguments', () => {
Expand All @@ -27,7 +128,7 @@ describe('cordova-res', () => {
it('should parse options for android', () => {
const args = ['android'];
const result = parseOptions(args);
expect(result).toEqual({ ...DEFAULT_OPTIONS, platforms: { android: generateRunOptions(Platform.ANDROID, 'resources', args) } });
expect(result).toEqual({ ...DEFAULT_OPTIONS, platforms: { android: generateRunOptions(Platform.ANDROID, 'resources', args), }, projectConfig: { android: { directory: 'android' } } });
});

it('should parse default options when the first argument is not a platform', () => {
Expand All @@ -39,7 +140,7 @@ describe('cordova-res', () => {
it('should accept --resources flag', () => {
const args = ['--resources', 'res'];
const result = parseOptions(args);
expect(result).toEqual({ ...DEFAULT_OPTIONS, resourcesDirectory: 'res' });
expect(result).toEqual({ ...DEFAULT_OPTIONS, platforms: generatePlatformsConfig('res'), resourcesDirectory: 'res' });
});

it('should log to stderr with --json flag', () => {
Expand Down
43 changes: 31 additions & 12 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import et from 'elementtree';

import { Options, PlatformOptions } from '.';
import type { NativeProjectConfigByPlatform, Options, PlatformOptions } from '.';
import { getPlatforms } from './config';
import { BadInputError } from './error';
import { NativeProject } from './native';
import { AdaptiveIconResourceOptions, Platform, RunPlatformOptions, SimpleResourceOptions, filterSupportedPlatforms, validatePlatforms } from './platform';
import { NativeProjectConfig } from './native';
import { AdaptiveIconResourceOptions, PLATFORMS, Platform, RunPlatformOptions, SimpleResourceOptions, filterSupportedPlatforms, validatePlatforms } from './platform';
import { DEFAULT_RESOURCES_DIRECTORY, RESOURCE_TYPES, ResourceKey, ResourceType, Source, SourceType, validateResourceTypes } from './resources';
import { getOptionValue } from './utils/cli';

Expand All @@ -24,23 +24,21 @@ export async function resolveOptions(args: readonly string[], directory: string,
};
}

export function parseOptions(args: readonly string[]): Options {
export function parseOptions(args: readonly string[]): Required<Options> {
const json = args.includes('--json');
const resourcesDirectory = getOptionValue(args, '--resources', DEFAULT_RESOURCES_DIRECTORY);
const platformArg = args[0] ? args[0] : undefined;
const platformList = validatePlatforms(platformArg && !platformArg.startsWith('-') ? [platformArg] : []);
const nativeProject: Readonly<NativeProject> = {
enabled: args.includes('--copy'),
androidProjectDirectory: getOptionValue(args, '--android-project', ''),
iosProjectDirectory: getOptionValue(args, '--ios-project', ''),
};
const platformList = validatePlatforms(platformArg && !platformArg.startsWith('-') ? [platformArg] : PLATFORMS);

return {
directory: getDirectory(),
resourcesDirectory,
logstream: json ? process.stderr : process.stdout,
errstream: process.stderr,
...platformList.length > 0 ? { platforms: generatePlatformOptions(platformList, resourcesDirectory, args) } : {},
nativeProject,
platforms: generatePlatformOptions(platformList, resourcesDirectory, args),
projectConfig: generatePlatformProjectOptions(platformList, args),
skipConfig: parseSkipConfigOption(args),
copy: parseCopyOption(args),
};
}

Expand All @@ -51,6 +49,13 @@ export function generatePlatformOptions(platforms: readonly Platform[], resource
}, {} as PlatformOptions);
}

export function generatePlatformProjectOptions(platforms: readonly Platform[], args: readonly string[]): NativeProjectConfigByPlatform {
return platforms.reduce((acc, platform) => {
acc[platform] = generateNativeProjectConfig(platform, args);
return acc;
}, {} as NativeProjectConfigByPlatform);
}

export function generateRunOptions(platform: Platform, resourcesDirectory: string, args: readonly string[]): RunPlatformOptions {
const typeOption = getOptionValue(args, '--type');
const types = validateResourceTypes(typeOption ? [typeOption] : RESOURCE_TYPES);
Expand All @@ -62,6 +67,20 @@ export function generateRunOptions(platform: Platform, resourcesDirectory: strin
};
}

export function generateNativeProjectConfig(platform: Platform, args: readonly string[]): NativeProjectConfig {
const directory = getOptionValue(args, `--${platform}-project`, platform);

return { directory };
}

export function parseCopyOption(args: readonly string[]): boolean {
return args.includes('--copy');
}

export function parseSkipConfigOption(args: readonly string[]): boolean {
return args.includes('--skip-config');
}

export function parseAdaptiveIconResourceOptions(platform: Platform, resourcesDirectory: string, args: readonly string[]): AdaptiveIconResourceOptions | undefined {
if (platform !== Platform.ANDROID) {
return;
Expand Down
7 changes: 4 additions & 3 deletions src/help.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const help = `
Usage: cordova-res [ios|android] [options]
Usage: cordova-res [ios|android|windows] [options]
Generate Cordova resources for native platforms.
Expand Down Expand Up @@ -28,15 +28,16 @@ const help = `
--type <icon|splash|adaptive-icon> ... Only generate one type of resource
--resources <path> ................... Use specified directory as resources directory
--skip-config ........................ Skip reading/writing to 'config.xml'
--icon-source <path> ................. Use specified file for icon source image
--splash-source <path> ............... Use specified file for splash source image
--icon-foreground-source <path> ...... Use file for foreground of adaptive icon
--icon-background-source <path|hex> .. Use file or color for background of adaptive icon
--copy ............................... Enable process of copying generated resources to native projects
--android-project <path> ............. Use specified directory for Android native project (default: 'android')
--copy ............................... Copy generated resources to native projects
--ios-project <path> ................. Use specified directory for iOS native project (default: 'ios')
--android-project <path> ............. Use specified directory for Android native project (default: 'android')
-h, --help ........................... Print help for the platform, then quit
--version ............................ Print version, then quit
Expand Down
Loading

0 comments on commit 6250426

Please sign in to comment.