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