UNPKG

8.96 kBJavaScriptView Raw
1var through2 = require("through2");
2var GulpFile = require("vinyl");
3var { readFileSync } = require("fs");
4var { concat } = require("lodash");
5var glob = require("glob");
6var { generateIndexHtmlContent } = require("./html");
7
8var {
9 generatePreloadFile,
10 findAllImportModules,
11 findAllUi5StandardModules,
12 findAllUi5ViewModules,
13 fetchAllResource,
14 resolveUI5Module,
15 findAllLibraries,
16 readURLFromCache,
17 readBinary,
18 persistCache
19} = require("./ui5");
20
21var path = require("path");
22
23var { bundleModule } = require("./thirdparty");
24
25var defaultResourceRoot = "https://openui5.hana.ondemand.com/resources/";
26
27module.exports = function({
28 sourceDir,
29 preload = false,
30 outputFilePath,
31 thirdpartyLibPath = ".",
32 ui5ResourceRoot = defaultResourceRoot,
33 projectNameSpace: projectNameSpace = "",
34 additionalModules = [],
35 additionalResources = [],
36 theme,
37 title,
38 production = false,
39 withLoadingSpinner = false,
40 bootScript,
41 bootScriptPath,
42 offline = false,
43 library = false
44}) {
45 if (!ui5ResourceRoot.endsWith("/")) {
46 ui5ResourceRoot = `${ui5ResourceRoot}/`;
47 }
48 var namepath = projectNameSpace.replace(/\./g, "/");
49
50 var targetJSPath = thirdpartyLibPath;
51
52 if (targetJSPath.endsWith("/") || targetJSPath.startsWith("/")) {
53 throw new Error(
54 `Not accept path :${thirdpartyLibPath}, please give thirdpartyLibPath like lib |_thirdparty | other/lib`
55 );
56 }
57
58 return through2.obj(async function(file, encoding, cb) {
59 try {
60
61 var libs = [];
62
63 var thirdpartyLibs = [];
64
65 /**
66 * distinct dependencies for this project
67 */
68 var distinctDeps = new Set(additionalModules);
69
70 // preload js module
71 var preloadPromise = new Promise((resolve, reject) => {
72 glob(`${sourceDir}/**/*.?(js|jsx|ts|tsx|mjs)`, async(err, files) => {
73 try {
74
75 if (err) {
76 reject(err);
77 return;
78 }
79
80 var allDeps = files.map(f => {
81
82 var mName = f.replace(sourceDir, namepath);
83 var source = readFileSync(f, { encoding: "utf-8" });
84
85 return concat(
86 findAllImportModules(source, mName),
87 findAllUi5StandardModules(source, mName)
88 );
89
90 });
91
92 concat(...allDeps).forEach(d => {
93 d = path.normalize(d).replace(path.normalize(sourceDir), namepath).replace(/\\/g, "/");
94 if (d.startsWith("sap")) {
95 distinctDeps.add(d);
96 } else if (!d.startsWith(namepath) && !d.startsWith("./") && !d.startsWith("../")) {
97 thirdpartyLibs.push(d);
98 }
99 });
100
101 resolve();
102
103 } catch (e) {
104
105 reject(e);
106
107 }
108 });
109 });
110
111 // preload xml view
112 var preloadProjectPromise = new Promise((resolve, reject) => {
113 glob(`${sourceDir}/**/*.+(view|fragment).xml`, async(err, files) => {
114 if (err) {
115 reject(err);
116 } else {
117 var allDeps = await Promise.all(files.map(f => {
118 var mName = f.replace(sourceDir, namepath);
119 var source = readFileSync(f, { encoding: "utf-8" });
120 return findAllUi5ViewModules(source, mName);
121 }));
122 concat(...allDeps).forEach(d => {
123 if (d.startsWith("sap")) {
124 distinctDeps.add(d);
125 }
126 });
127 resolve();
128 }
129 });
130 });
131
132 // await analyze project modules
133 await Promise.all([preloadPromise, preloadProjectPromise]);
134
135 var thirdPartyDepsObject = {};
136 var thirdPartyDepsCode = {};
137
138 if (thirdpartyLibs) {
139 try {
140 await Promise.all(
141 thirdpartyLibs.map(async packageDepName => {
142 // removing non-alphanumeric chars
143 thirdPartyDepsObject[packageDepName] = `${thirdpartyLibPath}/${packageDepName}`;
144 // use original dep name to resolve dep
145 const code = await bundleModule(packageDepName, production);
146 thirdPartyDepsCode[`${packageDepName}`] = code;
147 this.push(
148 new GulpFile({
149 path: `${targetJSPath}/${packageDepName}.js`,
150 contents: Buffer.from(code)
151 })
152 );
153 })
154 );
155 } catch (error) {
156 cb(error);
157 }
158 }
159
160 if (preload) {
161
162 // generate preload file
163 var modules = await resolveUI5Module(Array.from(distinctDeps), ui5ResourceRoot);
164
165 libs = await findAllLibraries(Object.keys(modules));
166
167 additionalResources = additionalResources.concat(libs.map(l => `${l}/messagebundle_zh_CN.properties`));
168 additionalResources = additionalResources.concat(libs.map(l => `${l}/messagebundle_en.properties`));
169 additionalResources = additionalResources.concat(libs.map(l => `${l}/messagebundle.properties`));
170 additionalResources = additionalResources.concat(libs.map(l => `${l}/messagebundle_en_US.properties`));
171 additionalResources = additionalResources.concat(libs.map(l => `${l}/messagebundle_en_UK.properties`));
172
173 var resources = await fetchAllResource(additionalResources, ui5ResourceRoot);
174
175 modules = Object.assign(modules, thirdPartyDepsCode);
176
177 this.push(
178 new GulpFile({
179 path: "preload.js",
180 contents: Buffer.from(
181 generatePreloadFile(
182 modules,
183 resources
184 )
185 )
186 })
187 );
188
189 } else {
190 libs = findAllLibraries(distinctDeps);
191 }
192
193 var cssLinks = [];
194
195 if (offline) {
196 var uiCoreContent = await readURLFromCache(`${ui5ResourceRoot}sap-ui-core.js`);
197 var corePreloadContent = await readURLFromCache(`${ui5ResourceRoot}sap/ui/core/library-preload.js`);
198
199 var offlineFiles = [
200 `sap/ui/core/themes/${theme}/fonts/72-Regular.woff2`,
201 `sap/ui/core/themes/${theme}/fonts/72-Regular.woff`,
202 `sap/ui/core/themes/${theme}/fonts/72-Regular-full.woff2`,
203 `sap/ui/core/themes/${theme}/fonts/72-Regular-full.woff`,
204 `sap/ui/core/themes/${theme}/fonts/72-Bold.woff2`,
205 `sap/ui/core/themes/${theme}/fonts/72-Bold.woff`,
206 `sap/ui/core/themes/${theme}/fonts/72-Bold-full.woff2`,
207 `sap/ui/core/themes/${theme}/fonts/72-Bold-full.woff`,
208 "sap/ui/core/themes/base/fonts/SAP-icons.woff2",
209 "sap/ui/core/themes/base/fonts/SAP-icons.woff",
210 "sap/ui/core/themes/base/fonts/SAP-icons.ttf",
211 "sap/ui/core/cldr/zh_CN.json",
212 "sap-ui-version.json"
213 ];
214
215 var files = await Promise.all(
216 concat(
217 libs.map(async l => ({
218 target: `resources/${l}/themes/${theme}/library.css`,
219 content: Buffer.from(await readURLFromCache(`${ui5ResourceRoot}${l}/themes/${theme}/library.css`))
220 })),
221 libs.map(async l => ({
222 target: `resources/${l}/themes/${theme}/library-parameters.json`,
223 content: Buffer.from(await readURLFromCache(`${ui5ResourceRoot}${l}/themes/${theme}/library-parameters.json`))
224 })),
225 offlineFiles.map(async fontPath => ({ target: `resources/${fontPath}`, content: await readBinary(`${ui5ResourceRoot}${fontPath}`) }))
226 )
227 );
228
229
230 this.push(
231 new GulpFile({
232 path: "resources/sap-ui-core.js",
233 contents: Buffer.from(uiCoreContent)
234 })
235 );
236 this.push(
237 new GulpFile({
238 path: "resources/sap/ui/core/library-preload.js",
239 contents: Buffer.from(corePreloadContent)
240 })
241 );
242 files.forEach(f => {
243 this.push(
244 new GulpFile({
245 path: f.target,
246 contents: f.content
247 })
248 );
249 });
250 cssLinks = libs.map(l => `./resources/${l}/themes/${theme}/library.css`);
251 } else {
252 cssLinks = libs.map(l => `${ui5ResourceRoot}${l}/themes/${theme}/library.css`);
253 }
254
255 if (!library) {
256
257 var indexHtml = generateIndexHtmlContent({
258 resourceRoot: ui5ResourceRoot,
259 projectNameSpace: projectNameSpace,
260 theme: theme,
261 title: title,
262 bootScript,
263 bootScriptPath,
264 preload,
265 offline,
266 withLoadingSpinner,
267 inlineCssLink: cssLinks,
268 resourceRoots: {
269 [projectNameSpace]: ".",
270 ...thirdPartyDepsObject
271 }
272 });
273
274 this.push(
275 new GulpFile({
276 path: outputFilePath || "index.html",
277 contents: Buffer.from(indexHtml)
278 })
279 );
280
281 }
282
283
284 persistCache.Persist();
285
286 cb();
287
288 } catch (err) {
289
290 cb(err);
291
292 }
293 });
294
295};
296
297module.exports.componentPreload = require("./component_preload");