UNPKG

8.25 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var fs_1 = require("fs");
4var path_1 = require("path");
5var Constants = require("./util/constants");
6var interfaces_1 = require("./util/interfaces");
7var helpers_1 = require("./util/helpers");
8var logger_1 = require("./logger/logger");
9function templateUpdate(changedFiles, context) {
10 try {
11 var changedTemplates = changedFiles.filter(function (changedFile) { return changedFile.ext === '.html'; });
12 var start = Date.now();
13 var bundleFiles = context.fileCache.getAll().filter(function (file) { return file.path.indexOf(context.buildDir) >= 0 && path_1.extname(file.path) === '.js'; });
14 // update the corresponding transpiled javascript file with the template changed (inline it)
15 // as well as the bundle
16 for (var _i = 0, changedTemplates_1 = changedTemplates; _i < changedTemplates_1.length; _i++) {
17 var changedTemplateFile = changedTemplates_1[_i];
18 var file = context.fileCache.get(changedTemplateFile.filePath);
19 if (!updateCorrespondingJsFile(context, file.content, changedTemplateFile.filePath)) {
20 throw new Error("Failed to inline template " + changedTemplateFile.filePath);
21 }
22 // find the corresponding bundles
23 for (var _a = 0, bundleFiles_1 = bundleFiles; _a < bundleFiles_1.length; _a++) {
24 var bundleFile = bundleFiles_1[_a];
25 var newContent = replaceExistingJsTemplate(bundleFile.content, file.content, changedTemplateFile.filePath);
26 if (newContent && newContent !== bundleFile.content) {
27 context.fileCache.set(bundleFile.path, { path: bundleFile.path, content: newContent });
28 fs_1.writeFileSync(bundleFile.path, newContent);
29 }
30 }
31 }
32 // awesome, all good and template updated in the bundle file
33 var logger = new logger_1.Logger("template update");
34 logger.setStartTime(start);
35 // congrats, all good
36 changedTemplates.forEach(function (changedTemplate) {
37 logger_1.Logger.debug("templateUpdate, updated: " + changedTemplate.filePath);
38 });
39 context.templateState = interfaces_1.BuildState.SuccessfulBuild;
40 logger.finish();
41 return Promise.resolve();
42 }
43 catch (ex) {
44 logger_1.Logger.debug("templateUpdate error: " + ex.message);
45 context.transpileState = interfaces_1.BuildState.RequiresBuild;
46 context.deepLinkState = interfaces_1.BuildState.RequiresBuild;
47 context.bundleState = interfaces_1.BuildState.RequiresUpdate;
48 return Promise.resolve();
49 }
50}
51exports.templateUpdate = templateUpdate;
52function updateCorrespondingJsFile(context, newTemplateContent, existingHtmlTemplatePath) {
53 var moduleFileExtension = helpers_1.changeExtension(helpers_1.getStringPropertyValue(Constants.ENV_NG_MODULE_FILE_NAME_SUFFIX), '.js');
54 var javascriptFiles = context.fileCache.getAll().filter(function (file) { return path_1.dirname(file.path) === path_1.dirname(existingHtmlTemplatePath) && path_1.extname(file.path) === '.js' && !file.path.endsWith(moduleFileExtension); });
55 for (var _i = 0, javascriptFiles_1 = javascriptFiles; _i < javascriptFiles_1.length; _i++) {
56 var javascriptFile = javascriptFiles_1[_i];
57 var newContent = replaceExistingJsTemplate(javascriptFile.content, newTemplateContent, existingHtmlTemplatePath);
58 if (newContent && newContent !== javascriptFile.content) {
59 javascriptFile.content = newContent;
60 // set the file again to generate a new timestamp
61 // do the same for the typescript file just to invalidate any caches, etc.
62 context.fileCache.set(javascriptFile.path, javascriptFile);
63 var typescriptFilePath = helpers_1.changeExtension(javascriptFile.path, '.ts');
64 context.fileCache.set(typescriptFilePath, context.fileCache.get(typescriptFilePath));
65 return true;
66 }
67 }
68 return false;
69}
70function inlineTemplate(sourceText, sourcePath) {
71 var componentDir = path_1.parse(sourcePath).dir;
72 var match;
73 var replacement;
74 var lastMatch = null;
75 while (match = getTemplateMatch(sourceText)) {
76 if (match.component === lastMatch) {
77 // panic! we don't want to melt any machines if there's a bug
78 logger_1.Logger.debug("Error matching component: " + match.component);
79 return sourceText;
80 }
81 lastMatch = match.component;
82 if (match.templateUrl === '') {
83 logger_1.Logger.error("Error @Component templateUrl missing in: \"" + sourcePath + "\"");
84 return sourceText;
85 }
86 replacement = updateTemplate(componentDir, match);
87 if (replacement) {
88 sourceText = sourceText.replace(match.component, replacement);
89 }
90 }
91 return sourceText;
92}
93exports.inlineTemplate = inlineTemplate;
94function updateTemplate(componentDir, match) {
95 var htmlFilePath = path_1.join(componentDir, match.templateUrl);
96 try {
97 var templateContent = fs_1.readFileSync(htmlFilePath, 'utf8');
98 return replaceTemplateUrl(match, htmlFilePath, templateContent);
99 }
100 catch (e) {
101 logger_1.Logger.error("template error, \"" + htmlFilePath + "\": " + e);
102 }
103 return null;
104}
105exports.updateTemplate = updateTemplate;
106function replaceTemplateUrl(match, htmlFilePath, templateContent) {
107 var orgTemplateProperty = match.templateProperty;
108 var newTemplateProperty = getTemplateFormat(htmlFilePath, templateContent);
109 return match.component.replace(orgTemplateProperty, newTemplateProperty);
110}
111exports.replaceTemplateUrl = replaceTemplateUrl;
112function replaceExistingJsTemplate(existingSourceText, newTemplateContent, htmlFilePath) {
113 var prefix = getTemplatePrefix(htmlFilePath);
114 var startIndex = existingSourceText.indexOf(prefix);
115 var isStringified = false;
116 if (startIndex === -1) {
117 prefix = stringify(prefix);
118 isStringified = true;
119 }
120 startIndex = existingSourceText.indexOf(prefix);
121 if (startIndex === -1) {
122 return null;
123 }
124 var suffix = getTemplateSuffix(htmlFilePath);
125 if (isStringified) {
126 suffix = stringify(suffix);
127 }
128 var endIndex = existingSourceText.indexOf(suffix, startIndex + 1);
129 if (endIndex === -1) {
130 return null;
131 }
132 var oldTemplate = existingSourceText.substring(startIndex, endIndex + suffix.length);
133 var newTemplate = getTemplateFormat(htmlFilePath, newTemplateContent);
134 if (isStringified) {
135 newTemplate = stringify(newTemplate);
136 }
137 var lastChange = null;
138 while (existingSourceText.indexOf(oldTemplate) > -1 && existingSourceText !== lastChange) {
139 lastChange = existingSourceText = existingSourceText.replace(oldTemplate, newTemplate);
140 }
141 return existingSourceText;
142}
143exports.replaceExistingJsTemplate = replaceExistingJsTemplate;
144function stringify(str) {
145 str = JSON.stringify(str);
146 return str.substr(1, str.length - 2);
147}
148function getTemplateFormat(htmlFilePath, content) {
149 // turn the template into one line and espcape single quotes
150 content = content.replace(/\r|\n/g, '\\n');
151 content = content.replace(/\'/g, '\\\'');
152 return getTemplatePrefix(htmlFilePath) + "'" + content + "'" + getTemplateSuffix(htmlFilePath);
153}
154exports.getTemplateFormat = getTemplateFormat;
155function getTemplatePrefix(htmlFilePath) {
156 return "template:/*ion-inline-start:\"" + path_1.resolve(htmlFilePath) + "\"*/";
157}
158function getTemplateSuffix(htmlFilePath) {
159 return "/*ion-inline-end:\"" + path_1.resolve(htmlFilePath) + "\"*/";
160}
161function getTemplateMatch(str) {
162 var match = COMPONENT_REGEX.exec(str);
163 if (match) {
164 return {
165 start: match.index,
166 end: match.index + match[0].length,
167 component: match[0],
168 templateProperty: match[3],
169 templateUrl: match[5].trim()
170 };
171 }
172 return null;
173}
174exports.getTemplateMatch = getTemplateMatch;
175var COMPONENT_REGEX = /Component\s*?\(\s*?(\{([\s\S]*?)(\s*templateUrl\s*:\s*(['"`])(.*?)(['"`])\s*?)([\s\S]*?)}\s*?)\)/m;