diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md new file mode 100644 index 0000000..2a8de96 --- /dev/null +++ b/ISSUE_TEMPLATE.md @@ -0,0 +1,23 @@ +### Issue Description +[Explain] + +### APEX Front-End Boost Version +[Example: v2.1.1] + +### Operating System +[Example: Windows] + +### Node Version +[Example: v4.4.5] + +### Browser +[Example: Chrome v50] + +### APEX Version +[Example: v5.0.3] + +### Web Server +[Example: ORDS 3.0.3, Tomcat 7] + +### Your `config.json` file +[Paste code] diff --git a/README.md b/README.md index e2d2c3c..ed1b6cc 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,33 @@ [![Build Status](https://travis-ci.org/OraOpenSource/apex-frontend-boost.svg?branch=master)](https://travis-ci.org/OraOpenSource/apex-frontend-boost) [![Dependency Status](https://david-dm.org/OraOpenSource/apex-frontend-boost.svg)](https://david-dm.org/OraOpenSource/apex-frontend-boost) -APEX Front-End Boost makes coding faster, easier, and prettier. This productivity tool helps you work with static files (`js`, `css`, `images`, etc.) more efficiently within an APEX application. - +- [What APEX Front-End Boost is](#what-apex-front-end-boost-is) + - [What APEX Front-End Boost does](#what-apex-front-end-boost-does) + - [How APEX Front-End Boost helps you](#how-apex-front-end-boost-helps-you) + - [Other benefits](#other-benefits) +- [Project Sponsors](#project-sponsors) +- [System Requirements](#system-requirements) +- [Install](#install) + - [via Git](#via-git) + - [via npm](#via-npm) +- [Upgrade](#upgrade) + - [via Git](#via-git) + - [via npm](#via-npm) +- [Configuration](#configuration) +- [APEX Application Setup](#apex-application-setup) +- [Run](#run) +- [Usage](#usage) +- [Features](#features) +- [Changelog](#changelog) + +## What APEX Front-End Boost is APEX Front-End Boost is a personal local web server that hosts and distributes your files to your APEX application. +APEX Front-End Boost makes coding faster, easier, and prettier. This productivity tool helps you work with static files (`js`, `css`, `images`, etc.) more efficiently within an APEX application. + ![demo](/media/demo-main.gif) -## What APEX Front-End Boost does +#### What APEX Front-End Boost does - Minifies `js` and `css`. - Generates `js` and `css` sourcemaps. - Adds `css` vendor prefixes. @@ -18,8 +38,9 @@ APEX Front-End Boost is a personal local web server that hosts and distributes y - Generates APEX Theme Roller configuration. *(optional)* - Transforms `css` to RTL format. *(optional)* - Adds a standardized header comment block to `js` and `css` files. *(optional)* +- Minifies images seamlessly *(optional)* -## How APEX Front-End Boost helps you +#### How APEX Front-End Boost helps you - Cut down on front-end development time. - Enhance your application performance due to smaller file sizes. - Keep coding in your favorite code editor, without having to constantly upload anything to APEX or a web server. @@ -27,6 +48,7 @@ APEX Front-End Boost is a personal local web server that hosts and distributes y - Stop affecting other developers. **Any development done within APEX Front-End Boost affects you and only you**. - Be notified of `js` and `css` errors as you save. +#### Other benefits It makes responsive development easier by synchronizing multiple devices together. Your desktop, tablet and mobile device will imitate each others actions (scrolling, clicking, typing) as long as you've got APEX Front-End Boost running. It eliminates the need for refreshing the browser. As soon as you save your code in the text editor, you get automatic code injection / reloading in the browser. @@ -39,16 +61,46 @@ Thanks to [Insum Solutions](http://insum.ca/) for sponsoring this project. - [Oracle APEX](https://apex.oracle.com) 5 (or more) for [Application Setup Option 1](/docs/apex-setup.md) - [Oracle APEX](https://apex.oracle.com) 4-5 (or more) for [Application Setup Option 2](/docs/apex-setup.md) +*Having `Cross Origin Sharing Requests` issues? [See CORS documentation](/docs/cors.md).* + ## Install -On the command line: +- Open the command line +- Go to the APEX Front-End Boost directory + +#### via Git +```bash +git clone https://github.com/OraOpenSource/apex-frontend-boost.git +cd apex-frontend-boost +npm install +``` + +#### via npm ```bash npm install apex-frontend-boost ``` +*Note: installing via npm automatically creates a `\node_modules\` directory and installs APEX Front-End Boost within. Please use only if you understand what that entails, otherwise use the Git method.* + *Having problems installing on Windows? [See documentation](/docs/windows.md).* *Having problems installing on Linux? [See documentation](/docs/linux.md).* +## Upgrade +- Open the command line +- Go to your APEX Front-End Boost directory + +#### via Git +```bash +git fetch origin +git reset --hard origin/master +npm install +``` + +#### via npm +```bash +npm install apex-frontend-boost +``` + ## Configuration You need to configure APEX Front-End Boost for your project(s). [See documentation](/docs/config.json.md). @@ -65,16 +117,21 @@ There are two options to setup your application: Review the [APEX Setup](/docs/apex-setup.md) docs to choose the most appropriate option for your project. ## Run -`npm start -- --project=yourProjectName` +**On the command line:** +```bash +npm start -- --project=yourProjectName +``` -**Running on Windows?** +**or use Windows shortcut:** - Launch `apex-frontend-boost.bat` - Enter project name -**Running on Linux/OSx?** +**or use Linux/OS X shortcut:** - Execute `./apex-frontend-boost.sh` - Enter project name +*Note: If you encounter errors while executing the steps above, you may need to use an elevated command line (run as administrator).* + ## Usage From the `src` folder you can create, edit or delete any files in: ``` @@ -96,8 +153,7 @@ APEX Front-End Boost will automatically compile your files to this folder struct |-lib ``` -### Self-Signed SSL Browser Warning -[See documentation](/docs/ssl-warning.md). +*Having problems regarding Self-Signed SSL Browser Warning? [See documentation](/docs/ssl-warning.md).* ## Features - [Browsersync](http://www.browsersync.io/) @@ -109,6 +165,7 @@ APEX Front-End Boost will automatically compile your files to this folder struct - [Sourcemaps](https://www.npmjs.com/package/gulp-sourcemaps) - [Header](https://github.com/tracker1/gulp-header) - [RTLCSS](https://github.com/MohammadYounes/rtlcss) +- [imagemin](https://github.com/sindresorhus/gulp-imagemin) - More... [See features examples](/docs/examples.md). diff --git a/changelog.md b/changelog.md index fd1f144..e6d9647 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,15 @@ # Changelog +## 2.1.1 +- Greatly enhanced the project error handling to provide more details and hints to the user. +- The `/src/` folder is now automatically created if it doesn't exist yet. +- Added `.sass` file support in addition to the existing `.scss` support. +- Docs: Added a documentation notice on ORDS issues. +- Docs: Added an advice to use an elevated command line (run as admin). +- Docs: Changed some of the project terminology. +- Docs: Provided two different installation options (Git and npm). +- Docs: Enhanced the documentation for `config.json` +- Created project issue template for better support going forward. + ## 2.1.0 - Project is now available on npm - Fixed a bug preventing from doing POST on Chrome diff --git a/default.json b/default.json index d8251b2..1849667 100644 --- a/default.json +++ b/default.json @@ -2,10 +2,6 @@ "appURL": "", "srcFolder": "src", "distFolder": "dist", - "header": { - "enabled": false, - "packageJsonPath": "" - }, "jsConcat": { "enabled": false, "finalName": "app" @@ -34,7 +30,14 @@ "finalName": "themeroller", "files" : [] }, + "header": { + "enabled": false, + "packageJsonPath": "" + }, "rtl": { "enabled": false + }, + "imageOptimization": { + "enabled": false } } diff --git a/docs/config.json.md b/docs/config.json.md index 2678de4..50a668e 100644 --- a/docs/config.json.md +++ b/docs/config.json.md @@ -35,10 +35,6 @@ It is only mandatory to fill out the `appURL` in `config.json`. The rest is opti "appURL": "", "srcFolder": "src", "distFolder": "dist", - "header": { - "enabled": false, - "packageJsonPath": "" - }, "jsConcat": { "enabled": false, "finalName": "app" @@ -67,42 +63,43 @@ It is only mandatory to fill out the `appURL` in `config.json`. The rest is opti "finalName": "themeroller", "files" : [] }, + "header": { + "enabled": false, + "packageJsonPath": "" + }, "rtl": { "enabled": false + }, + "imageOptimization": { + "enabled": false } } ``` ## Read below for more information about each fields. -### Application +### Global -**`appURL`** : `string`, default `` -> This is the URL to your APEX application homepage. - -**`srcFolder`** : `string`, default `src` -> This is the path to your application src folder. -> If nothing is filled, the current repository will be used with the `/src/` folder. -> This is the URL to your APEX application homepage. - -**`distFolder`** : `string`, default `dist` -> This is the path to your application dist folder. -> If nothing is filled, the current repository will be used with the `/dist/` folder. +Name | Type | Default | Description +--- | --- | -- | +`appURL` | string | | This is the URL to your APEX application homepage. +`srcFolder` | string | `src` | This is the path to your application src folder. If nothing is filled, the current repository will be used with the `/src/` folder. This is the URL to your APEX application homepage. +`distFolder` | string | `dist` | This is the path to your application dist folder. If nothing is filled, the current repository will be used with the `/dist/` folder. ### Header -**`header.enabled`** : `boolean`, default `false` -> Turns on and off the automatic header comment block feature. +Name | Type | Default | Description +-- | -- | -- | -- +`header.enabled` | boolean | `false` | Turns on and off the automatic header comment block feature. +`header.packageJsonPath` | string | | Represents the path to your project's `package.json` file. Only applies if `header.enabled` is `true`. -**`header.packageJsonPath`** : `string` -> Represents the path to your project's `package.json` file. -> Only applies if `header.enabled` is `true`. > Will output a standardized comment block at the start of `js` and `css` files. > Example: ```js /*! * apex-frontend-boost - Enhance your productivity with a complete Front-End Stack for Oracle APEX development - * @version v2.0.0 + * @author OraOpenSource + * @version v2.2 * @link https://github.com/OraOpenSource/apex-frontend-boost * @license MIT */ @@ -110,77 +107,68 @@ It is only mandatory to fill out the `appURL` in `config.json`. The rest is opti ### Javascript Concatenation -**`jsConcat.enabled`** : `boolean`, default `false` -> Turns on and off the javascript concatenation feature. - -**`jsConcat.finalName`** : `string`, default `app` -> Represents the name of the final file, after concatenation. -> Only applies if `jsConcat.enabled` is `true`. -> Will become `app.js` and `app.min.js` +Name | Type | Default | Description +-- | -- | -- | -- +`jsConcat.enabled` | boolean | `false` | Turns on and off the javascript concatenation feature. +`jsConcat.finalName` | string | `app` | Represents the name of the final file, after concatenation. Only applies if `jsConcat.enabled` is `true`. Will become `app.js` and `app.min.js` ### CSS Concatenation -**`cssConcat.enabled`** : `boolean`, default `false` -> Turns on and off the css concatenation feature. - -**`cssConcat.finalName`** : `string`, default `app` -> Represents the name of the final file, after concatenation. -> Only applies if `cssConcat.enabled` is `true`. -> Will become `app.css` and `app.min.css` +Name | Type | Default | Description +-- | -- | -- | -- +`cssConcat.enabled` | boolean | `false` | Turns on and off the javascript concatenation feature. +`cssConcat.finalName` | string | `app` | Represents the name of the final file, after concatenation. Only applies if `cssConcat.enabled` is `true`. Will become `app.css` and `app.min.css` ### Sass -**`sass.enabled`** : `boolean`, default `false` -> Turns on and off the sass parsing feature. - -**`sass.includePath`** : `string` -> Include a path to an external sass folder. Allows to use the `@import` feature from within that folder. +Name | Type | Default | Description +-- | -- | -- | -- +`sass.enabled` | boolean | `false` | Turns on and off the sass parsing feature. +`sass.includePath` | string | | Include a path to an external sass folder. Allows to use the `@import` feature from within that folder. -*When using Sass, please ensure that Less is turned off.* +> When using Sass, please ensure that Less is turned off. ### Less -**`less.enabled`** : `boolean`, default `false` -> Turns on and off the less parsing feature. - -**`less.includePath`** : `string` -> Include a path to an external less folder. Allows to use the `@import` feature from within that folder. +Name | Type | Default | Description +-- | -- | -- | -- +`less.enabled` | boolean | `false` | Turns on and off the less parsing feature. +`less.includePath` | string | | Include a path to an external less folder. Allows to use the `@import` feature from within that folder. -*When using Less, please ensure that Sass is turned off.* +> When using Less, please ensure that Sass is turned off. ### Browsersync -**`browsersync.enabled`** : `boolean`, default `false` -> Turns on and off the browsersync feature. - -**`browsersync.port`** : `int`, default `3000` -> This is the port that browsersync uses to serve your static files. - -**`browsersync.uiPort`** : `int`, default `3001` -> Browsersync includes a user-interface that is accessed via a separate port. - -**`browsersync.weinrePort`** : `int`, default `8080` -> This is the weinre port that browsersync uses. +Name | Type | Default | Description +-- | -- | -- | -- +`browsersync.enabled` | boolean | `false` | Turns on and off the browsersync feature. +`browsersync.port` | int | `3000` | This is the port that browsersync uses to serve your static files. +`browsersync.uiPort` | int | `3001` | Browsersync includes a user-interface that is accessed via a separate port. +`browsersync.weinrePort` | int | `8080` | This is the weinre port that browsersync uses. +`browsersync.notify` | boolean | `true` | This option makes browsersync alert you when a file is dynamically injected to you browser. -**`browsersync.notify`** : `boolean`, default `true` -> This option makes browsersync alert you when a file is dynamically injected to you browser. > Useful for Javascript & CSS development, as you won't have to manually refresh your browser. ### Theme Roller -**`themeroller.enabled`** : `boolean`, default `false` -> Turns on and off the Theme Roller feature. This will generate a `less` file that you can import into your application theme style. It will add editable variables to theme roller. - -**`themeroller.finalName`** : `string`, default `themeroller` -> Represents the name of the final less file, after concatenation from the array `themeroller.paths`. -> Only applies if `themeroller.enabled` is `true`. - -**`themeroller.paths`** : `array` -> Include the order of `scss` files to be parsed by theme roller. +Name | Type | Default | Description +-- | -- | -- | -- +`themeroller.enabled` | boolean | `false` | Turns on and off the Theme Roller feature. This will generate a `less` file that you can import into your application theme style. It will add editable variables to theme roller. +`themeroller.finalName` | string | `themeroller` | Represents the name of the final less file, after concatenation from the array `themeroller.paths`. Only applies if `themeroller.enabled` is `true`. `themeroller.paths` | array | | Include the order of `scss` files to be parsed by theme roller. ### RTLCSS -**`rtl.enabled`** : `boolean`, default `false` -> Turns on and off automatic `css` transformation from Left-To-Right (LTR) to Right-To-Left (RTL) languages. +Name | Type | Default | Description +-- | -- | -- | -- +`rtl.enabled` | boolean | `false` | Turns on and off automatic `css` transformation from Left-To-Right (LTR) to Right-To-Left (RTL) languages. + > Produces a `.rtl` version of your css files > Example: `app.css` also produces `app.rtl.css` + +### Image Optimization + +Name | Type | Default | Description +-- | -- | -- | -- +`imageOptimization.enabled` | boolean | `false` | Turns on and off automatic image lossless optimizers. + +> Minifies images in the `/img/` folder. diff --git a/docs/cors.md b/docs/cors.md new file mode 100644 index 0000000..8dd493e --- /dev/null +++ b/docs/cors.md @@ -0,0 +1,16 @@ +## Cross Origin Sharing Requests + +Starting from ORDS `3.0.3`, a new security rule concerning `Cross Origin Sharing Requests` conflicts with APEX Front-End Boost when using a VM through port forwarding: + +> 403 Forbidden +> The request cannot be processed because this resource does not support Cross Origin Sharing requests, or the request Origin is not authorized to access this resource. If ords is being reverse proxied ensure the front end server is propagating the host name, for mod_proxy ensure ProxyPreserveHost is set to On + +This occurs when the server is using ORDS `3.0.3`, `3.0.4` or `3.0.5`. + +For Apache, please follow the message and set the ProxyPreserveHost parameter to On. + +Otherwise until then please use ORDS `3.0.2` or less, as the error does **NOT** occur. + +Here are some related forum topics: +- https://community.oracle.com/thread/3906326 +- https://community.oracle.com/message/13659147 diff --git a/gulpfile.js b/gulpfile.js index df467ee..470fc1b 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -14,67 +14,71 @@ var gulp = require('gulp'), util = require('./lib/util'), scssToLess = require('./lib/scssToLess'), rtlcss = require('./lib/rtlcss'); + validate = require('jsonschema').validate, + schema = require('./lib/defaultSchema'), + fs = require("fs"), + mkdirp = require('mkdirp'); +const chalk = require('chalk'); // 2. PREREQUISITES AND ERROR HANDLING -var defaultConfig = require('./default'), - userConfig = require('./config'), - config = extend(true, {}, defaultConfig, userConfig[argv.project]); -// command line syntax -if (typeof argv.project == "undefined") { - console.log("The correct syntax is: npm start -- --project=yourProjectName"); - process.exit(1); -} +// read the user config.json +var userConfigJSON = fs.readFileSync("config.json"); -// project exists -if (typeof userConfig[argv.project] == "undefined") { - console.log("Project", argv.project ,"doesn't exists in your config.json file."); - process.exit(1); +// validates if user config.json is valid JSON +if (!util.isValidJSON(userConfigJSON)) { + console.log(chalk.red.bold("Your config.json file is not a valid JSON object.")); + console.log(chalk.red.bold("Try using a JSON Linter such as: http://jsonlint.com/")); + process.exit(); } -// sass or less, not both -if (config.sass.enabled && config.less.enabled) { - console.log("Choose either Sass or Less (not both) as the CSS preprocessor for project", argv.project); - process.exit(1); +// validates command line syntax +if (typeof argv.project == "undefined") { + console.log(chalk.red.bold("The correct syntax is: npm start -- --project=yourProjectName")); + process.exit(); } -// missing project appURL -if (util.isEmptyObject(config.appURL)) { - console.log("Missing appURL in your config.json file."); -} +// import default config and user config +var defaultConfig = require('./default'), + userConfig = require('./config'); -// missing project srcFolder -if (util.isEmptyObject(config.srcFolder)) { - console.log("Missing srcFolder in your config.json file."); +// validate if project exists +if (typeof userConfig[argv.project] == "undefined") { + console.log(chalk.red.bold("Project", argv.project, "doesn't exist in your config.json file.")); + process.exit(); } -// missing project distFolder -if (util.isEmptyObject(config.distFolder)) { - console.log("Missing distFolder in your config.json file."); +// user config json schema validation +var userConfigSchema = validate(userConfig[argv.project], schema); +if (userConfigSchema.errors.length > 0) { + console.log(chalk.red.bold("Your config.json file is not valid. See errors below:")); + console.log(userConfigSchema.errors.map(function(elem){ + return (elem.property + " " + elem.message).replace("instance", argv.project); + }).join("\n")); + process.exit(); } -if((util.isEmptyObject(config.appURL)) -|| (util.isEmptyObject(config.srcFolder)) -|| (util.isEmptyObject(config.distFolder))) { - process.exit(1); +// merge default config with user config +var config = extend(true, {}, defaultConfig, userConfig[argv.project]); + +// sass or less, not both +if (config.sass.enabled && config.less.enabled) { + console.log(chalk.red.bold("Choose either Sass or Less (not both) as the CSS preprocessor for project", argv.project)); + process.exit(); } // missing project header.packageJsonPath if (config.header.enabled) { - if (util.isEmptyObject(config.header.packageJsonPath)) { - console.log("Missing packageJsonPath in your config.json file."); - process.exit(1); - } else { - var pkg = require(config.header.packageJsonPath + "package.json"); - var banner = ['/*!', - ' * <%= pkg.name %> - <%= pkg.description %>', - ' * @version v<%= pkg.version %>', - ' * @link <%= pkg.homepage %>', - ' * @license <%= pkg.license %>', - ' */', - ''].join('\n'); - } + var pkg = require(config.header.packageJsonPath + "package.json"); + var banner = ['/*!', + ' * <%= pkg.name %> - <%= pkg.description %>', + ' * @author v<%= pkg.author %>', + ' * @version v<%= pkg.version %>', + ' * @link <%= pkg.homepage %>', + ' * @license <%= pkg.license %>', + ' */', + ''].join('\n'); } // 3. SETTINGS VARIABLES @@ -87,6 +91,7 @@ var paths = { js: path.normalize('/js/'), css: path.normalize('/css/'), scss: path.normalize('/scss/'), + sass: path.normalize('/sass/'), less: path.normalize('/less/'), img: path.normalize('/img/'), lib: path.normalize('/lib/') @@ -96,6 +101,7 @@ var paths = { js: path.normalize('*.js'), css: path.normalize('*.css'), scss: path.normalize('*.scss'), + sass: path.normalize('*.sass'), less: path.normalize('*.less'), all: path.normalize('*.*'), }, @@ -123,6 +129,30 @@ var paths = { next(); }; +// build directory structure +// js img and lib are mandatory +var dirs = [ + paths.src + assets.js, + paths.src + assets.img, + paths.src + assets.lib +]; + +// sass less and css are based on user config +if (config.sass.enabled || config.less.enabled) { + if (config.sass.enabled) { + dirs.push(paths.src + assets.scss); + } else { + dirs.push(paths.src + assets.less); + } +} else { + dirs.push(paths.src + assets.css); +} + +// create directory structure if doesn't exist yet +for (var i = 0; i < dirs.length; i++) { + mkdirp.sync(dirs[i]); +} + // 4. TASKS // cleans the dist directory gulp.task('clean-dist', function() { @@ -153,18 +183,22 @@ gulp.task('js-browsersync', ['js'], function() { browsersync.reload(); }); -// scss +// style gulp.task('style', function() { var sourceFiles; if (config.sass.enabled) { - sourceFiles = paths.src + assets.scss + files.scss; + sourceFiles = [ + paths.src + assets.scss + files.scss, + paths.src + assets.sass + files.sass + ]; } else if (config.less.enabled) { sourceFiles = paths.src + assets.less + files.less; } else { sourceFiles = paths.src + assets.css + files.css; } + // creates the source stream that will be used for unmin and min versions var sourceStream = gulp.src(sourceFiles) .pipe(plugins.plumber()) .pipe(plugins.if(config.header.enabled, plugins.header(banner, { pkg : pkg } ))) @@ -173,12 +207,14 @@ gulp.task('style', function() { .pipe(plugins.if(config.less.enabled, plugins.less(lessOptions))) .pipe(plugins.if(config.cssConcat.enabled, plugins.concat(config.cssConcat.finalName + '.css'))); + // creates the unmin css var unmin = sourceStream .pipe(plugins.clone()) .pipe(plugins.autoprefixer()) .pipe(plugins.size(sizeOptions)) .pipe(plugins.sourcemaps.write(paths.sourcemaps)); + // creates the min css var min = sourceStream .pipe(plugins.clone()) .pipe(plugins.autoprefixer()) @@ -187,6 +223,7 @@ gulp.task('style', function() { .pipe(plugins.size(sizeOptions)) .pipe(plugins.sourcemaps.write(paths.sourcemaps)); + // adds the unmin and the min version to the stream return merge(unmin, min) .pipe(clip()) .pipe(gulp.dest(paths.dist + assets.css)) @@ -200,6 +237,7 @@ gulp.task('style', function() { // copy img files as is gulp.task('img', function() { return gulp.src(paths.src + assets.img + allSubFolders + files.all) + .pipe(plugins.if(config.imageOptimization.enabled, plugins.imagemin())) .pipe(gulp.dest(paths.dist + assets.img)); }); @@ -242,12 +280,14 @@ gulp.task('watch', function() { var jsWatch = (config.browsersync.enabled ? ['js-browsersync'] : ['js']); gulp.watch(allSubFolders + files.js, { cwd: paths.src + assets.js }, jsWatch); gulp.watch(allSubFolders + files.scss, { cwd: paths.src + assets.scss }, ['style']); + gulp.watch(allSubFolders + files.sass, { cwd: paths.src + assets.sass }, ['style']); gulp.watch(allSubFolders + files.less, { cwd: paths.src + assets.less }, ['style']); gulp.watch(allSubFolders + files.css, { cwd: paths.src + assets.css }, ['style']); // theme roller support if (config.themeroller.enabled) { gulp.watch(allSubFolders + files.scss, { cwd: paths.src + assets.scss }, ['themeroller']); + gulp.watch(allSubFolders + files.sass, { cwd: paths.src + assets.sass }, ['themeroller']); gulp.watch(allSubFolders + files.less, { cwd: paths.src + assets.less }, ['themeroller']); } @@ -273,6 +313,9 @@ gulp.task('default', function() { // run tasks runSequence('clean-dist', tasks, 'watch', function() { - console.log("APEX Front-End Boost has successfully processed your files."); + console.log(chalk.green.bold("APEX Front-End Boost has successfully processed your files.")); + console.log(chalk.cyan.bold("Now open up your favorite code editor and modify any file within:")); + console.log(dirs); + console.log(chalk.cyan.bold("All files belonging in the directories above are made available to use in APEX")); }); }); diff --git a/lib/defaultSchema.json b/lib/defaultSchema.json new file mode 100644 index 0000000..52d9ca0 --- /dev/null +++ b/lib/defaultSchema.json @@ -0,0 +1,128 @@ +{ + "type": "object", + "properties": { + "appURL": { + "type": "string" + }, + "srcFolder": { + "type": "string" + }, + "distFolder": { + "type": "string" + }, + "jsConcat": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "finalName": { + "type": "string" + } + } + }, + "cssConcat": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "finalName": { + "type": "string" + } + } + }, + "sass": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "includePath": { + "type": "string" + } + } + }, + "less": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "includePath": { + "type": "string" + } + } + }, + "browsersync": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "uiPort": { + "type": "integer" + }, + "weinrePort": { + "type": "integer" + }, + "notify": { + "type": "boolean" + } + } + }, + "themeroller": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "finalName": { + "type": "string" + }, + "files": { + "type": "array", + "items": {} + } + } + }, + "header": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "packageJsonPath": { + "type": "string" + } + }, + "required": [ + "packageJsonPath" + ] + }, + "rtl": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "imageOptimization": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + } + }, + "required": [ + "appURL", + "srcFolder", + "distFolder" + ] +} diff --git a/lib/util.js b/lib/util.js index feebc9e..4ddeacf 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,5 +1,16 @@ module.exports = { - isEmptyObject: function (obj) { - return !Object.keys(obj).length; - } + // validates if an object is empty (true), otherwise (false) + isEmptyObject: function(obj) { + return !Object.keys(obj).length; + }, + + // parses the user config.json and validates json + isValidJSON: function(obj) { + try { + JSON.parse(obj); + return true; + } catch (e) { + return false; + } + } }; diff --git a/package.json b/package.json index 9a252f9..3e7a1e5 100644 --- a/package.json +++ b/package.json @@ -1,59 +1,63 @@ { - "name": "apex-frontend-boost", - "author": "OraOpenSource", - "version": "2.1.0", - "description": "Enhance your productivity with a complete Front-End Stack for Oracle APEX development", - "license": "MIT", - "keywords": [ - "oracle", - "apex", - "orclapex", - "css", - "javascript", - "front-end", - "responsive", - "framework", - "web" - ], - "repository": { - "type": "git", - "url": "https://github.com/OraOpenSource/apex-frontend-boost.git" - }, - "bugs": { - "url": "https://github.com/OraOpenSource/apex-frontend-boost/issues" - }, - "scripts": { - "start": "gulp", - "postinstall": "node generateConfig.js" - }, - "dependencies": { - "browser-sync": "2.12.x", - "del": "2.2.x", - "gulp": "3.9.x", - "gulp-autoprefixer": "3.1.x", - "gulp-clip-empty-files": "0.1.x", - "gulp-concat": "2.6.x", - "gulp-if": "2.0.x", - "gulp-jshint": "2.0.x", - "gulp-load-plugins": "1.2.x", - "gulp-cssnano": "2.1.x", - "gulp-plumber": "1.1.x", - "gulp-rename": "1.2.x", - "gulp-sass": "2.3.x", - "gulp-less": "3.0.x", - "gulp-size": "2.1.x", - "gulp-sourcemaps": "2.0.0-alpha", - "gulp-uglify": "1.5.x", - "gulp-util": "3.0.x", - "gulp-clone": "1.0.x", - "gulp-header": "1.7.x", - "jshint": "2.x", - "jshint-stylish": "2.1.x", - "run-sequence": "1.1.x", - "yargs": "4.6.x", - "node.extend": "1.1.x", - "merge-stream": "1.0.x", - "rtlcss": "2.0.x", - "through2": "2.0.x" - } + "name": "apex-frontend-boost", + "author": "OraOpenSource", + "version": "2.1.1", + "description": "Enhance your productivity with a complete Front-End Stack for Oracle APEX development", + "license": "MIT", + "keywords": [ + "oracle", + "apex", + "orclapex", + "css", + "javascript", + "front-end", + "responsive", + "framework", + "web" + ], + "repository": { + "type": "git", + "url": "https://github.com/OraOpenSource/apex-frontend-boost.git" + }, + "bugs": { + "url": "https://github.com/OraOpenSource/apex-frontend-boost/issues" + }, + "scripts": { + "start": "gulp", + "postinstall": "node generateConfig.js" + }, + "dependencies": { + "browser-sync": "2.13.x", + "chalk": "1.1.x", + "del": "2.2.x", + "gulp": "3.9.x", + "gulp-autoprefixer": "3.1.x", + "gulp-clip-empty-files": "0.1.x", + "gulp-clone": "1.0.x", + "gulp-concat": "2.6.x", + "gulp-cssnano": "2.1.x", + "gulp-header": "1.8.x", + "gulp-if": "2.0.x", + "gulp-imagemin": "3.0.x", + "gulp-jshint": "2.0.x", + "gulp-less": "3.1.x", + "gulp-load-plugins": "1.2.x", + "gulp-plumber": "1.1.x", + "gulp-rename": "1.2.x", + "gulp-sass": "2.3.x", + "gulp-size": "2.1.x", + "gulp-sourcemaps": "2.0.0-alpha", + "gulp-uglify": "1.5.x", + "gulp-util": "3.0.x", + "jshint": "2.x", + "jshint-stylish": "2.2.x", + "jsonschema": "1.1.x", + "merge-stream": "1.0.x", + "mkdirp": "0.5.x", + "node.extend": "1.1.x", + "rtlcss": "2.0.x", + "run-sequence": "1.2.x", + "through2": "2.0.x", + "yargs": "4.7.x" + } }