Skip to content

Commit

Permalink
feature(umd): Universal Module Definition builds (#78)
Browse files Browse the repository at this point in the history
* updated package.json in platform/core with rc6 and alpha8-1

* added glob and rollup dependencies

* updated typings with hammerjs so lib build doesnt fail

* first draft of inline and rollup to umd files

* updated finish-release script, updated RELEASE.md
  • Loading branch information
emoralesb05 authored and kyleledbetter committed Sep 14, 2016
1 parent ab67c40 commit 23007cd
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 52 deletions.
1 change: 1 addition & 0 deletions build.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module.exports = {
packagejson: [
'src/**/**/package.json'
],
deployed: 'deploy/platform/',
tsfiles: [
'src/typings.d.ts',
'!src/main.ts',
Expand Down
47 changes: 5 additions & 42 deletions docs/RELEASE.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,23 @@
# Release Guide for the Platform
* [Manual Release](#manual-release)
* [Automatic Release](#automatic-release)

## Manual Release

* [Testing](#testing)
* [Bump Version](#bump-version)
* [Build](#build)
* [Release](#release)

#### Testing

Ensure that the code passes all tests before continuing.
Execute `npm test` to test the code with `tslint` and `karma`, provided the code has `[name].component.spec.ts` unit test files.

#### Bump Version

First, double check what kind of release is going to be published. It varies if its a `dev`, `patch`, `minor`, `major` or `[version]` release.
Execute `npm run bump-[dev|patch|minor|major]` to bump the release or execute `gulp bump-version --ver [version]`.
NOTE: Caution when using this command, since it will change the version on every module's package.json within `src/platform`.

#### Build

The building process has 4 steps:
1. Removes `deploy/` dir so that we guarantee there are no stale artifacts.
2. Compiles `.ts` files within `src/platform/*`, and creates compiled files into `deploy/`. (retaining dir structure)
3. Compiles `.scss` files within `src/platform/*`, and creates compiled files into `deploy/`. (retaining dir structure)
4. Moves `package.json`, `README.md`, additional `.js` files and `.html` files into `deploy/`. (retaining dir structure)

Execute `npm run build` to build the code you want to release.

#### Release

Execute `npm run publish` to publish to NPM. At the moment it goes into every package within `deploy/platform` that has a `package.json` file and publishes into [public NPM registry](https://www.npmjs.com/).
It will fail to publish if you try to upload a version that already exists in the registry. Use wisely.

NOTE: Tagging version and merging to master/develop would have to be done manually.

## Automatic Release
## Release

* [Start Release](#start-release)
* [Finish Release](#finish-release)

#### Start Release

Execute `npm run start-release -- [version]` to start the automatic release process. The steps executed are:
1. Creating a `release/[version]` branch using `git flow release`.
1. Creating a `release/v[version]` branch using `git flow release`.
2. Bumping its version to [version] release and commiting bumped version files.
3. Publishing `release/[version]` branch into repository.
4. Executes `npm run test`.
3. Publishing `release/v[version]` branch into repository.
4. Executes `npm run tslint` and `npm run test`.

The release is published in case there is a need for any additional tests, version fixes or bug fixes. This can be added before it is actually released.

#### Finish Release

Execute `npm run finish-release -- [version]` to start the automatic publishing process. The steps executed are:
Execute `git flow release finish v[version]` and `npm run finish-release` to start the automatic publishing process. The steps executed are:
1. Finishes, tags and deletes the `release/[version]` branch.
2. Pushes the new `[version]` tag into the repository.
3. Merges release into `develop` and pushes changes to repository.
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
"codelyzer": "0.0.28",
"del": "2.2.0",
"ember-cli-inject-live-reload": "1.4.0",
"glob": "^6.0.4",
"gulp": "3.9.1",
"gulp-bump": "2.1.0",
"gulp-help": "1.6.1",
Expand All @@ -122,6 +123,9 @@
"phantomjs-prebuilt": "2.1.7",
"protractor": "4.0.7",
"require-dir": "0.3.0",
"rollup": "^0.35.9",
"rollup-plugin-commonjs": "4.1.0",
"rollup-plugin-node-resolve": "2.0.0",
"semver": "5.2.0",
"ts-node": "0.9.3",
"tslint": "^3.15.1",
Expand Down
8 changes: 6 additions & 2 deletions scripts/build-release
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ rm -rf ./deploy

# Perform a build.
gulp build

echo "Platform compiled..."
# Inline the css and html into the component files.
echo "ToDo inline replace"
gulp inline-resource-files
echo "Files inlined..."
# Bundle
gulp rollup-code
echo "Bundled..."
9 changes: 3 additions & 6 deletions scripts/finish-release
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
#!/bin/bash
version=$1

set -e

echo "Finished release v$version"
git flow release finish v$version

echo "Pushed tag v$version to main repo"
echo "Pushed tag to main repo"
git push --tags

echo "Pushing changes into develop"
git checkout develop
git push origin develop

echo "Pushing changes into master"
git checkout master
git push origin master

echo "Building master branch"
Expand Down
9 changes: 9 additions & 0 deletions scripts/inline-resource-files.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
'use strict';

var gulp = require('gulp-help')(require('gulp'));
var inlineResources = require('./inline-resources.js');
var config = require('../build.conf');

gulp.task('inline-resource-files', 'Inline resouces files into JS files', function() {
inlineResources([config.paths.deployed]);
});
116 changes: 116 additions & 0 deletions scripts/inline-resources.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
'use strict';
const fs = require('fs');
const path = require('path');
const glob = require('glob');

/**
* Simple Promiseify function that takes a Node API and return a version that supports promises.
* We use promises instead of synchronized functions to make the process less I/O bound and
* faster. It also simplify the code.
*/
function promiseify(fn) {
return function() {
const args = [].slice.call(arguments, 0);
return new Promise((resolve, reject) => {
fn.apply(this, args.concat([function (err, value) {
if (err) {
reject(err);
} else {
resolve(value);
}
}]));
});
};
}

const readFile = promiseify(fs.readFile);
const writeFile = promiseify(fs.writeFile);

function inlineResources(globs) {
/**
* For every argument, inline the templates and styles under it and write the new file.
*/
for (let pattern of globs) {
if (pattern.indexOf('*') < 0) {
// Argument is a directory target, add glob patterns to include every files.
pattern = path.join(pattern, '**', '*');
}

const files = glob.sync(pattern, {})
.filter(name => /\.js$/.test(name)); // Matches only JavaScript files.

// Generate all files content with inlined templates.
files.forEach(filePath => {
readFile(filePath, 'utf-8')
.then(content => inlineTemplate(filePath, content))
.then(content => inlineStyle(filePath, content))
.then(content => removeModuleId(filePath, content))
.then(content => writeFile(filePath, content))
.catch(err => {
console.error('An error occured: ', err);
});
});
}
}

if (require.main === module) {
inlineResources(process.argv.slice(2));
}


/**
* Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and
* replace with `template: ...` (with the content of the file included).
* @param filePath {string} The path of the source file.
* @param content {string} The source file's content.
* @return {string} The content with all templates inlined.
*/
function inlineTemplate(filePath, content) {
return content.replace(/templateUrl:\s*'([^']+?\.html)'/g, function(m, templateUrl) {
const templateFile = path.join(path.dirname(filePath), templateUrl);
const templateContent = fs.readFileSync(templateFile, 'utf-8');
const shortenedTemplate = templateContent
.replace(/([\n\r]\s*)+/gm, ' ')
.replace(/"/g, '\\"');
return `template: "${shortenedTemplate}"`;
});
}


/**
* Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and
* replace with `styles: [...]` (with the content of the file included).
* @param filePath {string} The path of the source file.
* @param content {string} The source file's content.
* @return {string} The content with all styles inlined.
*/
function inlineStyle(filePath, content) {
return content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, function(m, styleUrls) {
const urls = eval(styleUrls);
return 'styles: ['
+ urls.map(styleUrl => {
const styleFile = path.join(path.dirname(filePath), styleUrl);
const styleContent = fs.readFileSync(styleFile, 'utf-8');
const shortenedStyle = styleContent
.replace(/([\n\r]\s*)+/gm, ' ')
.replace(/"/g, '\\"');
return `"${shortenedStyle}"`;
})
.join(',\n')
+ ']';
});
}


/**
* Remove every mention of `moduleId: module.id`.
* @param _ {string} The file path of the source file, currently ignored.
* @param content {string} The source file's content.
* @returns {string} The content with all moduleId: mentions removed.
*/
function removeModuleId(_, content) {
return content.replace(/\s*moduleId:\s*module\.id\s*,?\s*/gm, '');
}


module.exports = inlineResources;
94 changes: 94 additions & 0 deletions scripts/rollup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
'use strict';

const gulp = require('gulp-help')(require('gulp'));
const fs = require('fs');
const rollup = require('rollup').rollup;
const commonjs = require('rollup-plugin-commonjs');
const nodeResolve = require('rollup-plugin-node-resolve');
const path = require('path');
const config = require('../build.conf');

function camelCase(str) {
return str.replace(/-(\w)/g, (_, letter) => {
return letter.toUpperCase();
})
}

gulp.task('rollup-code', '', function() {
const components = fs.readdirSync(config.paths.deployed)
.filter(componentName => (fs.statSync(path.join(config.paths.deployed, componentName))).isDirectory());

const globals = {
// Angular dependencies
'@angular/core': 'ng.core',
'@angular/common': 'ng.common',
'@angular/forms': 'ng.forms',
'@angular/http': 'ng.http',
'@angular/router': 'ng.router',
'@angular/platform-browser': 'ng.platformBrowser',
'@angular/platform-browser-dynamic': 'ng.platformBrowserDynamic',

// Angular dependencies

'@angular2-material/button': 'md.button',
'@angular2-material/button-toggle': 'md.buttonToggle',
'@angular2-material/card': 'md.card',
'@angular2-material/checkbox': 'md.checkbox',
'@angular2-material/core': 'md.core',
'@angular2-material/grid-list': 'md.gridList',
'@angular2-material/icon': 'md.icon',
'@angular2-material/input': 'md.input',
'@angular2-material/list': 'md.list',
'@angular2-material/menu': 'md.menu',
'@angular2-material/progress-bar': 'md.progressBar',
'@angular2-material/progress-circle': 'md.progressCircle',
'@angular2-material/radio': 'md.radio',
'@angular2-material/sidenav': 'md.sidenav',
'@angular2-material/slider': 'md.slider',
'@angular2-material/slide-toggle': 'md.slideToggle',
'@angular2-material/tabs': 'md.tabs',
'@angular2-material/toolbar': 'md.toolbar',
'@angular2-material/tooltip': 'md.tooltip',

// Rxjs dependencies
'rxjs/Subject': 'Rx',
'rxjs/add/observable/forkJoin': 'Rx.Observable',
'rxjs/add/observable/of': 'Rx.Observable',
'rxjs/add/operator/toPromise': 'Rx.Observable.prototype',
'rxjs/add/operator/map': 'Rx.Observable.prototype',
'rxjs/add/operator/filter': 'Rx.Observable.prototype',
'rxjs/add/operator/do': 'Rx.Observable.prototype',
'rxjs/add/operator/share': 'Rx.Observable.prototype',
'rxjs/add/operator/finally': 'Rx.Observable.prototype',
'rxjs/add/operator/catch': 'Rx.Observable.prototype',
'rxjs/Observable': 'Rx'
};
components.forEach(name => {
globals[`@covalent/${name}`] = `td.${camelCase(name)}`
});

// Build all of them asynchronously.
return components.reduce((previous, name) => {
return previous
.then(() => {
return rollup({
entry: path.join(config.paths.deployed, name, 'index.js'),
context: 'window',
external: Object.keys(globals).concat(components.map(name => `@covalent/${name}`)),
plugins: [
commonjs({ jsnext: true, main: true }),
]
});
})
.then((bundle) => {
const result = bundle.generate({
moduleName: `td.${camelCase(name)}`,
format: 'umd',
exports: 'named',
globals
});
const outputPath = path.join(config.paths.deployed, name, `${name}.umd.js`);
fs.writeFileSync( outputPath, result.code );
});
}, Promise.resolve());
});
1 change: 0 additions & 1 deletion src/platform/markdown/markdown.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@
code:before,
code:after {
letter-spacing: -0.2em;
content: "\00a0";
}

pre>code {
Expand Down
3 changes: 2 additions & 1 deletion typings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"selenium-webdriver": "registry:dt/selenium-webdriver#2.44.0+20160317120654"
},
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160725163759"
"core-js": "registry:dt/core-js#0.0.0+20160725163759",
"hammerjs": "registry:dt/hammerjs#2.0.8+20160724063812"
}
}

0 comments on commit 23007cd

Please sign in to comment.