Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit ee2bc6a

Browse files
committed
docs(cb-third-party-lib) create a third party lib
s s s s s c s c s s s s s s s s s s s s s s s s s s s s s s s
1 parent 74ef87f commit ee2bc6a

29 files changed

+702
-3
lines changed

gulpfile.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ var regularPlunker = require(path.resolve(TOOLS_PATH, 'plunker-builder/regularPl
5151
var embeddedPlunker = require(path.resolve(TOOLS_PATH, 'plunker-builder/embeddedPlunker'));
5252
var fsUtils = require(path.resolve(TOOLS_PATH, 'fs-utils/fsUtils'));
5353

54+
var publish = require(path.resolve(EXAMPLES_PATH + '/cb-third-party-lib/hero-profile/publish'));
55+
5456
const WWW = argv.page ? 'www-pages' : 'www'
5557

5658
const isSilent = !!argv.silent;
@@ -464,7 +466,9 @@ gulp.task('add-example-boilerplate', function(done) {
464466
fsUtils.addSymlink(realPath, linkPath);
465467
});
466468

467-
return buildStyles(copyExampleBoilerplate, done);
469+
publish().then(function(){
470+
return buildStyles(copyExampleBoilerplate, done);
471+
});
468472
});
469473

470474

public/docs/_examples/_boilerplate/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"build:webpack": "rimraf dist && webpack --config config/webpack.prod.js --bail",
1919
"build:cli": "ng build",
2020
"build:aot": "ngc -p tsconfig-aot.json && rollup -c rollup-config.js",
21+
"build:aot:jit": "npm run build:aot && npm run tsc",
2122
"copy-dist-files": "node ./copy-dist-files.js",
2223
"i18n": "ng-xi18n"
2324
},

public/docs/_examples/_boilerplate/systemjs.config.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626

2727
// other libraries
2828
'rxjs': 'npm:rxjs',
29-
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
29+
'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js',
30+
'hero-profile': 'npm:hero-profile/bundles/hero-profile.umd.js'
3031
},
3132
// packages tells the System loader how to load when no filename and/or no extension
3233
packages: {

public/docs/_examples/_boilerplate/tsconfig.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"compileOnSave": true,
1717
"exclude": [
1818
"node_modules/*",
19-
"**/*-aot.ts"
19+
"**/*-aot.ts",
20+
"app-aot"
2021
]
2122
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
**/*.ngfactory.ts
2+
**/*.metadata.json
3+
**/*.css.shim.ts
4+
*.js
5+
!/hero-profile/rollup-config.js
6+
!/hero-profile/publish.js
7+
!/hero-profile/inline-resources.js
8+
!/hero-profile/package.json
9+
!ts/rollup-config.js
10+
**/umd-temp
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
'use strict'; // necessary for es6 output in node
2+
3+
import { browser, element, by } from 'protractor';
4+
5+
describe('Third Party Lib Cookbook', function () {
6+
7+
let expectedMsgAoT = 'Library consumed by AoT application';
8+
let expectedMsgJiT = 'Library consumed by JiT application';
9+
10+
beforeEach(function () {
11+
browser.get('');
12+
});
13+
14+
it(`should load AoT compiled version`, function () {
15+
expect(element(by.css('.aot')).getText()).toEqual(expectedMsgAoT);
16+
});
17+
18+
it('should load JiT compiled version', function () {
19+
expect(element(by.css('.jit')).getText()).toEqual(expectedMsgJiT);
20+
});
21+
22+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/*#docregion*/
2+
.bio {
3+
border: 1px solid black;
4+
padding: 10px;
5+
width: 300px;
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!--#docregion-->
2+
<div class="bio">
3+
<h1>Featured Hero</h1>
4+
5+
<h3>{{hero.name}}</h3>
6+
<div>{{hero.bio}}</div>
7+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// #docregion
2+
import { Component, Input } from '@angular/core';
3+
4+
import { Hero } from './hero';
5+
6+
@Component({
7+
moduleId: module.id,
8+
selector: 'hero-profile',
9+
templateUrl: 'hero-profile.component.html',
10+
styleUrls: ['hero-profile.component.css']
11+
})
12+
export class HeroProfileComponent {
13+
@Input() hero: Hero;
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// #docregion
2+
import { NgModule } from '@angular/core';
3+
4+
import { HeroProfileComponent } from './hero-profile.component';
5+
6+
@NgModule({
7+
declarations: [HeroProfileComponent],
8+
exports: [HeroProfileComponent]
9+
})
10+
export class HeroProfileModule {
11+
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// #docregion
2+
export class Hero {
3+
constructor(public name: string, public bio: string) {}
4+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// #docregion
2+
export { HeroProfileComponent } from './hero-profile.component';
3+
export { HeroProfileModule } from './hero-profile.module';
4+
export { Hero } from './hero';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// #docregion
2+
'use strict';
3+
4+
const fs = require('fs');
5+
const path = require('path');
6+
const glob = require('glob');
7+
8+
/**
9+
* Simple Promiseify function that takes a Node API and return a version that supports promises.
10+
* We use promises instead of synchronized functions to make the process less I/O bound and
11+
* faster. It also simplify the code.
12+
*/
13+
function promiseify(fn) {
14+
return function() {
15+
const args = [].slice.call(arguments, 0);
16+
return new Promise((resolve, reject) => {
17+
fn.apply(this, args.concat([function (err, value) {
18+
if (err) {
19+
reject(err);
20+
} else {
21+
resolve(value);
22+
}
23+
}]));
24+
});
25+
};
26+
}
27+
28+
const readFile = promiseify(fs.readFile);
29+
const writeFile = promiseify(fs.writeFile);
30+
31+
32+
function inlineResources(globs) {
33+
if (typeof globs == 'string') {
34+
globs = [globs];
35+
}
36+
37+
/**
38+
* For every argument, inline the templates and styles under it and write the new file.
39+
*/
40+
return Promise.all(globs.map(pattern => {
41+
if (pattern.indexOf('*') < 0) {
42+
// Argument is a directory target, add glob patterns to include every files.
43+
pattern = path.join(pattern, '**', '*');
44+
}
45+
46+
const files = glob.sync(pattern, {})
47+
.filter(name => /\.js$/.test(name)); // Matches only JavaScript files.
48+
49+
// Generate all files content with inlined templates.
50+
return Promise.all(files.map(filePath => {
51+
return readFile(filePath, 'utf-8')
52+
.then(content => inlineResourcesFromString(content, url => {
53+
return path.join(path.dirname(filePath), url);
54+
}))
55+
.then(content => writeFile(filePath, content))
56+
.catch(err => {
57+
console.error('An error occured: ', err);
58+
});
59+
}));
60+
}));
61+
}
62+
63+
/**
64+
* Inline resources from a string content.
65+
* @param content {string} The source file's content.
66+
* @param urlResolver {Function} A resolver that takes a URL and return a path.
67+
* @returns {string} The content with resources inlined.
68+
*/
69+
function inlineResourcesFromString(content, urlResolver) {
70+
// Curry through the inlining functions.
71+
return [
72+
inlineTemplate,
73+
inlineStyle,
74+
removeModuleId
75+
].reduce((content, fn) => fn(content, urlResolver), content);
76+
}
77+
78+
if (require.main === module) {
79+
inlineResources(process.argv.slice(2));
80+
}
81+
82+
83+
/**
84+
* Inline the templates for a source file. Simply search for instances of `templateUrl: ...` and
85+
* replace with `template: ...` (with the content of the file included).
86+
* @param content {string} The source file's content.
87+
* @param urlResolver {Function} A resolver that takes a URL and return a path.
88+
* @return {string} The content with all templates inlined.
89+
*/
90+
function inlineTemplate(content, urlResolver) {
91+
return content.replace(/templateUrl:\s*'([^']+?\.html)'/g, function(m, templateUrl) {
92+
const templateFile = urlResolver(templateUrl);
93+
const templateContent = fs.readFileSync(templateFile, 'utf-8');
94+
const shortenedTemplate = templateContent
95+
.replace(/([\n\r]\s*)+/gm, ' ')
96+
.replace(/"/g, '\\"');
97+
return `template: "${shortenedTemplate}"`;
98+
});
99+
}
100+
101+
102+
/**
103+
* Inline the styles for a source file. Simply search for instances of `styleUrls: [...]` and
104+
* replace with `styles: [...]` (with the content of the file included).
105+
* @param urlResolver {Function} A resolver that takes a URL and return a path.
106+
* @param content {string} The source file's content.
107+
* @return {string} The content with all styles inlined.
108+
*/
109+
function inlineStyle(content, urlResolver) {
110+
return content.replace(/styleUrls:\s*(\[[\s\S]*?\])/gm, function(m, styleUrls) {
111+
const urls = eval(styleUrls);
112+
return 'styles: ['
113+
+ urls.map(styleUrl => {
114+
const styleFile = urlResolver(styleUrl);
115+
const styleContent = fs.readFileSync(styleFile, 'utf-8');
116+
const shortenedStyle = styleContent
117+
.replace(/([\n\r]\s*)+/gm, ' ')
118+
.replace(/"/g, '\\"');
119+
return `"${shortenedStyle}"`;
120+
})
121+
.join(',\n')
122+
+ ']';
123+
});
124+
}
125+
126+
127+
/**
128+
* Remove every mention of `moduleId: module.id`.
129+
* @param content {string} The source file's content.
130+
* @returns {string} The content with all moduleId: mentions removed.
131+
*/
132+
function removeModuleId(content) {
133+
return content.replace(/\s*moduleId:\s*module\.id\s*,?\s*/gm, '');
134+
}
135+
136+
module.exports = inlineResources;
137+
module.exports.inlineResourcesFromString = inlineResourcesFromString;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "hero-profile",
3+
"version": "0.0.1",
4+
"main": "bundles/hero-profile.umd.js",
5+
"module": "index.js",
6+
"typings": "index.d.ts",
7+
"author": "",
8+
"licenses": [
9+
{
10+
"type": "MIT",
11+
"url": "https://github.com/angular/angular.io/blob/master/LICENSE"
12+
}
13+
]
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// #docregion
2+
function publish() {
3+
var inlineResources = require('./inline-resources');
4+
5+
// AoT compile
6+
var spawnNgc = require( 'child_process' ).spawnSync;
7+
var ngc = spawnNgc('./public/docs/_examples/node_modules/.bin/ngc', ['-p', './public/docs/_examples/cb-third-party-lib/hero-profile/tsconfig-aot.json']);
8+
9+
// Copy to node_modules
10+
var fs = require('fs');
11+
var del = require('del');
12+
13+
var node_modules_root = './public/docs/_examples/node_modules/hero-profile/';
14+
15+
del.sync(node_modules_root, {force:true});
16+
17+
fs.mkdirSync(node_modules_root);
18+
fs.mkdirSync(node_modules_root + 'bundles');
19+
20+
var aotFiles = [
21+
'hero-profile.component.html',
22+
'hero-profile.component.css',
23+
24+
'hero-profile.component.d.ts',
25+
'hero-profile.module.d.ts',
26+
'hero.d.ts',
27+
'index.d.ts',
28+
29+
'hero-profile.component.js',
30+
'hero-profile.module.js',
31+
'hero.js',
32+
'index.js',
33+
34+
'index.metadata.json',
35+
'hero-profile.module.metadata.json',
36+
'hero-profile.component.metadata.json',
37+
38+
'package.json'
39+
]
40+
41+
aotFiles.map(function(f) {
42+
var path = f.split('/');
43+
var release = node_modules_root + path[path.length-1];
44+
fs.createReadStream('./public/docs/_examples/cb-third-party-lib/hero-profile/' + f).pipe(fs.createWriteStream(release));
45+
});
46+
47+
return inlineResources('./public/docs/_examples/cb-third-party-lib/hero-profile/hero-profile.component.*').then(function(){
48+
49+
// Create umd bundle
50+
var spawnRollup = require( 'child_process' ).spawnSync;
51+
var rollup = spawnRollup('./public/docs/_examples/node_modules/.bin/rollup', ['-c', './public/docs/_examples/cb-third-party-lib/hero-profile/rollup-config.js']);
52+
53+
var umd = './public/docs/_examples/cb-third-party-lib/hero-profile/bundles/hero-profile.umd.js';
54+
fs.createReadStream(umd).pipe(fs.createWriteStream(node_modules_root + 'bundles/hero-profile.umd.js'));
55+
56+
});
57+
}
58+
59+
module.exports = publish;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// #docregion
2+
export default {
3+
entry: './public/docs/_examples/cb-third-party-lib/hero-profile/index.js',
4+
dest: './public/docs/_examples/cb-third-party-lib/hero-profile/bundles/hero-profile.umd.js',
5+
format: 'umd',
6+
moduleName: 'ng.heroProfile',
7+
globals: {
8+
'@angular/core': 'ng.core'
9+
}
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"compilerOptions": {
3+
"target": "es5",
4+
"module": "es2015",
5+
"moduleResolution": "node",
6+
"sourceMap": true,
7+
"declaration": true,
8+
"emitDecoratorMetadata": true,
9+
"experimentalDecorators": true,
10+
"noImplicitAny": true,
11+
"typeRoots": [
12+
"../../node_modules/@types/"
13+
]
14+
},
15+
"files": [
16+
"index.ts"
17+
],
18+
"angularCompilerOptions": {
19+
"genDir": "aot",
20+
"skipMetadataEmit" : false
21+
}
22+
}

0 commit comments

Comments
 (0)