UNPKG

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