Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit e2c5eb7

Browse files
committed
chore(global): update index with Ionic global object
1 parent 32e4841 commit e2c5eb7

10 files changed

+224
-140
lines changed

src/core/bundle-components.ts

+7-19
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as nodeSass from 'node-sass';
66
import * as rollup from 'rollup';
77
import * as typescript from 'typescript';
88
import * as uglify from 'uglify-js';
9+
import * as cleanCss from 'clean-css';
910

1011

1112
export function bundleCoreComponents(context: BuildContext) {
@@ -20,6 +21,7 @@ export function bundleCoreComponents(context: BuildContext) {
2021
srcDir: context.coreDir,
2122
destDir: context.buildDir,
2223
packages: {
24+
cleanCss: cleanCss,
2325
fs: fs,
2426
path: path,
2527
nodeSass: nodeSass,
@@ -34,6 +36,11 @@ export function bundleCoreComponents(context: BuildContext) {
3436
results.errors.forEach((err: string) => {
3537
Logger.error(`compiler.bundle, results: ${err}`);
3638
});
39+
40+
} else if (results.componentRegistry) {
41+
// add the component registry to the global window.Ionic
42+
context.ionicGlobal = context.ionicGlobal || {};
43+
context.ionicGlobal['components'] = results.componentRegistry;
3744
}
3845
}).catch(err => {
3946
Logger.error(`compiler.bundle: ${err}`);
@@ -49,22 +56,3 @@ function getCoreCompiler(context: BuildContext): CoreCompiler {
4956
}
5057
return null;
5158
}
52-
53-
// In serve mode, we only want to do the look-up for the compiler once
54-
let cachedCompilerModuleResult: CompilerModuleResult = null;
55-
export function doesCompilerExist(context: BuildContext): boolean {
56-
if (!cachedCompilerModuleResult) {
57-
const result = getCoreCompiler(context);
58-
cachedCompilerModuleResult = {
59-
found: result ? true : false,
60-
module: result ? result : null
61-
};
62-
}
63-
64-
return cachedCompilerModuleResult.found;
65-
}
66-
67-
interface CompilerModuleResult {
68-
found: boolean;
69-
module: any;
70-
};

src/core/inject-script.spec.ts

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import { injectCoreHtml } from './inject-scripts';
2+
3+
4+
describe('Inject Scripts', () => {
5+
6+
describe('injectCoreHtml', () => {
7+
8+
it('should replace an existed injected script tag', () => {
9+
const inputHtml = '' +
10+
'<html>\n' +
11+
'<head>\n' +
12+
' <script data-ionic="inject">\n' +
13+
' alert(11111);\n' +
14+
' </script>\n' +
15+
'</head>\n' +
16+
'<body>\n' +
17+
'</body>\n' +
18+
'</html>';
19+
20+
const output = injectCoreHtml(inputHtml, ' <script data-ionic="inject">\n' +
21+
' alert(55555);\n' +
22+
' </script>');
23+
24+
expect(output).toEqual(
25+
'<html>\n' +
26+
'<head>\n' +
27+
' <script data-ionic="inject">\n' +
28+
' alert(55555);\n' +
29+
' </script>\n' +
30+
'</head>\n' +
31+
'<body>\n' +
32+
'</body>\n' +
33+
'</html>');
34+
});
35+
36+
it('should add script to top of file when no html tag', () => {
37+
const inputHtml = '' +
38+
'<body>\n' +
39+
'</body>';
40+
41+
const output = injectCoreHtml(inputHtml, '<injected></injected>');
42+
43+
expect(output).toEqual(
44+
'<injected></injected>\n' +
45+
'<body>\n' +
46+
'</body>');
47+
});
48+
49+
it('should add script below <html> with attributes', () => {
50+
const inputHtml = '' +
51+
'<html dir="rtl">\n' +
52+
'<body>\n' +
53+
'</body>\n' +
54+
'</html>';
55+
56+
const output = injectCoreHtml(inputHtml, '<injected></injected>');
57+
58+
expect(output).toEqual(
59+
'<html dir="rtl">\n' +
60+
'<injected></injected>\n' +
61+
'<body>\n' +
62+
'</body>\n' +
63+
'</html>');
64+
});
65+
66+
it('should add script below <html> when no head tag', () => {
67+
const inputHtml = '' +
68+
'<html>\n' +
69+
'<body>\n' +
70+
'</body>\n' +
71+
'</html>';
72+
73+
const output = injectCoreHtml(inputHtml, '<injected></injected>');
74+
75+
expect(output).toEqual(
76+
'<html>\n' +
77+
'<injected></injected>\n' +
78+
'<body>\n' +
79+
'</body>\n' +
80+
'</html>');
81+
});
82+
83+
it('should add script below <head>', () => {
84+
const inputHtml = '' +
85+
'<html>\n' +
86+
'<head>\n' +
87+
'</head>\n' +
88+
'<body>\n' +
89+
'</body>\n' +
90+
'</html>';
91+
92+
const output = injectCoreHtml(inputHtml, '<injected></injected>');
93+
94+
expect(output).toEqual(
95+
'<html>\n' +
96+
'<head>\n' +
97+
'<injected></injected>\n' +
98+
'</head>\n' +
99+
'<body>\n' +
100+
'</body>\n' +
101+
'</html>');
102+
});
103+
104+
it('should add script below <head> with attributes and all caps tag', () => {
105+
const inputHtml = '' +
106+
'<html>\n' +
107+
'<HEAD data-attr="yup">\n' +
108+
'</HEAD>\n' +
109+
'<body>\n' +
110+
'</body>\n' +
111+
'</html>';
112+
113+
const output = injectCoreHtml(inputHtml, '<injected></injected>');
114+
115+
expect(output).toEqual(
116+
'<html>\n' +
117+
'<HEAD data-attr="yup">\n' +
118+
'<injected></injected>\n' +
119+
'</HEAD>\n' +
120+
'<body>\n' +
121+
'</body>\n' +
122+
'</html>');
123+
});
124+
125+
});
126+
127+
});
128+
129+
130+

src/core/inject-scripts.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { BuildContext } from '../util/interfaces';
2+
import { buildIonicGlobal } from './ionic-global';
3+
import { readFileAsync, writeFileAsync } from '../util/helpers';
4+
import { join } from 'path';
5+
6+
7+
export function updateIndexHtml(context: BuildContext) {
8+
const indexPath = join(context.wwwDir, context.wwwIndex);
9+
10+
return readFileAsync(indexPath).then(indexHtml => {
11+
if (!indexHtml) {
12+
return Promise.resolve(null);
13+
}
14+
15+
indexHtml = injectCoreScripts(context, indexHtml);
16+
17+
return writeFileAsync(indexPath, indexHtml);
18+
});
19+
}
20+
21+
22+
export function injectCoreScripts(context: BuildContext, indexHtml: string) {
23+
const inject = [];
24+
25+
inject.push(` <script data-ionic="inject">`);
26+
27+
inject.push(` ${buildIonicGlobal(context)}`);
28+
29+
inject.push(` </script>`);
30+
31+
return injectCoreHtml(indexHtml, inject.join('\n'));
32+
}
33+
34+
35+
export function injectCoreHtml(indexHtml: string, inject: string) {
36+
// see if we can find an existing ionic script tag and replace it entirely
37+
const existingTag = indexHtml.match(/<script data-ionic="inject">[\s\S]*<\/script>/gi);
38+
if (existingTag) {
39+
return indexHtml.replace(existingTag[0], inject.trim());
40+
}
41+
42+
// see if we can find the head tag and inject it immediate below it
43+
const headTag = indexHtml.match(/<head[^>]*>/gi);
44+
if (headTag) {
45+
return indexHtml.replace(headTag[0], `${headTag[0]}\n${inject}`);
46+
}
47+
48+
// see if we can find the html tag and inject it immediate below it
49+
const htmlTag = indexHtml.match(/<html[^>]*>/gi);
50+
if (htmlTag) {
51+
return indexHtml.replace(htmlTag[0], `${htmlTag[0]}\n${inject}`);
52+
}
53+
54+
return `${inject}\n${indexHtml}`;
55+
}

src/core/ionic-global.spec.ts

+1-24
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,9 @@
11
import { BuildContext } from '../util/interfaces';
2-
import { buildIonicGlobal, prependIonicGlobal } from './ionic-global';
2+
import { buildIonicGlobal } from './ionic-global';
33

44

55
describe('Ionic Global', () => {
66

7-
describe('prependIonicGlobal', () => {
8-
9-
it('should prepend window.Ionic to code', () => {
10-
const ctx: BuildContext = {
11-
rootDir: '/Users/elliemae/myapp',
12-
wwwDir: '/Users/elliemae/myapp/www',
13-
buildDir: '/Users/elliemae/myapp/www/build'
14-
};
15-
16-
const code = 'var name = "Ellie Mae";';
17-
18-
const r = prependIonicGlobal(ctx, 'main.js', code);
19-
20-
expect(r.code.indexOf('Ionic') > -1).toBeTruthy();
21-
expect(r.map).toBeDefined();
22-
});
23-
24-
});
25-
26-
277
describe('buildIonicGlobal', () => {
288

299
it('should cache windowIonic', () => {
@@ -33,12 +13,9 @@ describe('Ionic Global', () => {
3313
buildDir: '/Users/elliemae/myapp/www/build'
3414
};
3515

36-
expect((<any>ctx).windowIonic).toBeUndefined();
37-
3816
const r = buildIonicGlobal(ctx);
3917

4018
expect(r).toBeDefined();
41-
expect((<any>ctx).windowIonic).toBeDefined();
4219
});
4320

4421
});

src/core/ionic-global.ts

+24-48
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,21 @@
11
import { BuildContext } from '../util/interfaces';
22
import { getSystemData, toUnixPath } from '../util/helpers';
3-
import { Logger } from '../logger/logger';
4-
import * as MagicString from 'magic-string';
5-
6-
7-
export function prependIonicGlobal(context: BuildContext, fileName: string, code: string) {
8-
const rtn: { code: string, map: any } = {
9-
code: code,
10-
map: undefined
11-
};
12-
13-
try {
14-
const ionicGlobal = buildIonicGlobal(context);
15-
16-
const s = new MagicString(code);
17-
18-
s.prepend(ionicGlobal);
19-
20-
rtn.code = s.toString();
21-
22-
rtn.map = s.generateMap({
23-
source: fileName,
24-
file: fileName,
25-
includeContent: true
26-
});
27-
28-
} catch (e) {
29-
Logger.error(`prependIonicGlobal: ${e}`);
30-
}
31-
32-
return rtn;
33-
}
343

354

365
export function buildIonicGlobal(context: BuildContext) {
37-
if ((<any>context).windowIonic) {
38-
// just a quick way to cache this to avoid unnecessary readFiles
39-
return (<any>context).windowIonic;
40-
}
6+
context.ionicGlobal = context.ionicGlobal || {};
417

8+
// gather data to add to window.Ionic
429
const systemData = getSystemData(context.rootDir);
10+
if (systemData.ionicFramework) {
11+
context.ionicGlobal['version'] = `'${systemData.ionicFramework}'`;
12+
}
13+
if (systemData.angularCore) {
14+
context.ionicGlobal['angular'] = `'${systemData.angularCore}'`;
15+
}
16+
if (systemData.ionicNative) {
17+
context.ionicGlobal['ionicNative'] = `'${systemData.ionicNative}'`;
18+
}
4319

4420
let staticDir = toUnixPath(context.buildDir.replace(context.wwwDir, ''));
4521
staticDir += '/';
@@ -48,19 +24,19 @@ export function buildIonicGlobal(context: BuildContext) {
4824
staticDir = staticDir.substring(1);
4925
}
5026

51-
let output = `
52-
(function(w){
53-
var i = w.Ionic = w.Ionic || {};
54-
${systemData.ionicFramework ? `i.version = '${systemData.ionicFramework}';` : ''}
55-
${systemData.angularCore ? `i.angular = '${systemData.angularCore}';` : ''}
56-
${systemData.ionicNative ? `i.ionicNative = '${systemData.ionicNative}';` : ''}
57-
i.staticDir = '${staticDir}';
58-
})(window);`;
27+
context.ionicGlobal['staticDir'] = `'${staticDir}'`;
28+
29+
// output the JS
30+
let o = [
31+
'(function(w){',
32+
'var i=w.Ionic=w.Ionic||{};'
33+
];
34+
35+
Object.keys(context.ionicGlobal).forEach(key => {
36+
o.push(`i.${key}=${context.ionicGlobal[key]};`);
37+
});
5938

60-
// real quick minification hacks
61-
output = output.replace('var i', 'var_i');
62-
output = output.replace(/\s/g, '');
63-
output = output.replace('var_i', 'var i');
39+
o.push('})(window);');
6440

65-
return (<any>context).windowIonic = output;
41+
return o.join('');
6642
}

src/postprocess.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Logger } from './logger/logger';
22
import { BuildContext } from './util/interfaces';
3+
import { updateIndexHtml } from './core/inject-scripts';
34
import { purgeSourceMapsIfNeeded } from './util/source-maps';
45
import { removeUnusedFonts } from './optimization/remove-unused-fonts';
56

@@ -18,6 +19,7 @@ export function postprocess(context: BuildContext) {
1819
function postprocessWorker(context: BuildContext) {
1920
return Promise.all([
2021
purgeSourceMapsIfNeeded(context),
21-
removeUnusedFonts(context)
22+
removeUnusedFonts(context),
23+
updateIndexHtml(context)
2224
]);
2325
}

0 commit comments

Comments
 (0)