react-native-bootsplash 5.0.0-beta.4 → 5.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -6
- package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashDialog.java +8 -4
- package/android/src/main/java/com/zoontek/rnbootsplash/RNBootSplashModuleImpl.java +1 -0
- package/android/src/main/res/drawable/transparent_pixel.png +0 -0
- package/android/src/main/res/values/public.xml +2 -0
- package/android/src/main/res/values/styles.xml +11 -4
- package/android/src/main/res/values-v23/styles.xml +11 -0
- package/android/src/main/res/values-v27/styles.xml +8 -0
- package/android/src/main/res/values-v31/styles.xml +3 -1
- package/dist/commonjs/NativeRNBootSplash.web.js +43 -0
- package/dist/commonjs/NativeRNBootSplash.web.js.map +1 -0
- package/dist/commonjs/addon/index.js +82 -1
- package/dist/commonjs/addon/index.js.map +1 -1
- package/dist/commonjs/generate.js +139 -28
- package/dist/commonjs/generate.js.map +1 -1
- package/dist/module/NativeRNBootSplash.web.js +36 -0
- package/dist/module/NativeRNBootSplash.web.js.map +1 -0
- package/dist/module/addon/index.js +82 -1
- package/dist/module/addon/index.js.map +1 -1
- package/dist/module/generate.js +138 -28
- package/dist/module/generate.js.map +1 -1
- package/dist/typescript/NativeRNBootSplash.web.d.ts +10 -0
- package/dist/typescript/NativeRNBootSplash.web.d.ts.map +1 -0
- package/dist/typescript/addon/index.d.ts +1 -1
- package/dist/typescript/addon/index.d.ts.map +1 -1
- package/dist/typescript/generate.d.ts +18 -6
- package/dist/typescript/generate.d.ts.map +1 -1
- package/package.json +14 -11
- package/react-native.config.js +15 -10
- package/src/NativeRNBootSplash.web.ts +42 -0
- package/src/generate.ts +182 -48
package/src/generate.ts
CHANGED
|
@@ -5,18 +5,20 @@ import {
|
|
|
5
5
|
} from "@react-native-community/cli-types";
|
|
6
6
|
import detectIndent from "detect-indent";
|
|
7
7
|
import fs from "fs-extra";
|
|
8
|
+
import { parse as parseHtml } from "node-html-parser";
|
|
8
9
|
import path from "path";
|
|
9
10
|
import pc from "picocolors";
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
11
|
+
import { Options as PrettierOptions } from "prettier";
|
|
12
|
+
import htmlPlugin from "prettier/parser-html";
|
|
13
|
+
import cssPlugin from "prettier/parser-postcss";
|
|
14
|
+
import prettier from "prettier/standalone";
|
|
15
|
+
import sharp, { Sharp } from "sharp";
|
|
16
|
+
import { dedent } from "ts-dedent";
|
|
17
|
+
import formatXml, { XMLFormatterOptions } from "xml-formatter";
|
|
18
|
+
import { Manifest } from ".";
|
|
14
19
|
|
|
15
20
|
const workingPath = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd();
|
|
16
21
|
|
|
17
|
-
export const androidColorRegex =
|
|
18
|
-
/<color name="bootsplash_background">#\w+<\/color>/g;
|
|
19
|
-
|
|
20
22
|
export type Color = {
|
|
21
23
|
hex: string;
|
|
22
24
|
rgb: { R: string; G: string; B: string };
|
|
@@ -54,7 +56,8 @@ const getStoryboard = ({
|
|
|
54
56
|
const logoX = (frameWidth - logoWidth) / 2;
|
|
55
57
|
const logoY = (frameHeight - logoHeight) / 2;
|
|
56
58
|
|
|
57
|
-
return
|
|
59
|
+
return dedent`
|
|
60
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
58
61
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
|
|
59
62
|
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
|
60
63
|
<dependencies>
|
|
@@ -123,17 +126,13 @@ export const writeJson = (file: string, json: object) => {
|
|
|
123
126
|
|
|
124
127
|
export const readXml = (file: string) => {
|
|
125
128
|
const xml = fs.readFileSync(file, "utf-8");
|
|
129
|
+
const { indent } = detectIndent(xml);
|
|
126
130
|
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
indentation: "",
|
|
131
|
-
lineSeparator: "",
|
|
132
|
-
whiteSpaceAtEndOfSelfclosingTag: true,
|
|
133
|
-
});
|
|
131
|
+
const formatOptions: XMLFormatterOptions = {
|
|
132
|
+
indentation: indent || " ",
|
|
133
|
+
};
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
return { minified, indentation };
|
|
135
|
+
return { root: parseHtml(xml), formatOptions };
|
|
137
136
|
};
|
|
138
137
|
|
|
139
138
|
export const writeXml = (
|
|
@@ -141,7 +140,7 @@ export const writeXml = (
|
|
|
141
140
|
xml: string,
|
|
142
141
|
options?: XMLFormatterOptions,
|
|
143
142
|
) => {
|
|
144
|
-
const formatted =
|
|
143
|
+
const formatted = formatXml(xml, {
|
|
145
144
|
collapseContent: true,
|
|
146
145
|
forceSelfClosingEmptyTag: true,
|
|
147
146
|
indentation: " ",
|
|
@@ -154,6 +153,35 @@ export const writeXml = (
|
|
|
154
153
|
logWrite(file);
|
|
155
154
|
};
|
|
156
155
|
|
|
156
|
+
export const readHtml = (file: string) => {
|
|
157
|
+
const html = fs.readFileSync(file, "utf-8");
|
|
158
|
+
const { type, amount } = detectIndent(html);
|
|
159
|
+
|
|
160
|
+
const formatOptions: PrettierOptions = {
|
|
161
|
+
useTabs: type === "tab",
|
|
162
|
+
tabWidth: amount || 2,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return { root: parseHtml(html), formatOptions };
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
export const writeHtml = (
|
|
169
|
+
file: string,
|
|
170
|
+
html: string,
|
|
171
|
+
options?: Omit<PrettierOptions, "parser" | "plugins">,
|
|
172
|
+
) => {
|
|
173
|
+
const formatted = prettier.format(html, {
|
|
174
|
+
parser: "html",
|
|
175
|
+
plugins: [htmlPlugin, cssPlugin],
|
|
176
|
+
tabWidth: 2,
|
|
177
|
+
useTabs: false,
|
|
178
|
+
...options,
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
fs.writeFileSync(file, formatted, "utf-8");
|
|
182
|
+
logWrite(file);
|
|
183
|
+
};
|
|
184
|
+
|
|
157
185
|
const ensureSupportedFormat = async (
|
|
158
186
|
name: string,
|
|
159
187
|
image: Sharp | undefined,
|
|
@@ -240,19 +268,41 @@ const getIOSProjectPath = (ios: IOSProjectConfig): string | undefined => {
|
|
|
240
268
|
}
|
|
241
269
|
};
|
|
242
270
|
|
|
271
|
+
const getHtmlTemplatePath = (html: string): string | undefined => {
|
|
272
|
+
const htmlTemplatePath = path.resolve(workingPath, html);
|
|
273
|
+
|
|
274
|
+
if (!fs.existsSync(htmlTemplatePath)) {
|
|
275
|
+
log.warn(
|
|
276
|
+
`No ${path.relative(
|
|
277
|
+
workingPath,
|
|
278
|
+
htmlTemplatePath,
|
|
279
|
+
)} file found. Skipping HTML + CSS generation…`,
|
|
280
|
+
);
|
|
281
|
+
} else {
|
|
282
|
+
return htmlTemplatePath;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
243
286
|
export type AddonConfig = {
|
|
244
287
|
licenseKey: string;
|
|
245
288
|
|
|
246
289
|
androidResPath: string | undefined;
|
|
247
290
|
iosProjectPath: string | undefined;
|
|
291
|
+
htmlTemplatePath: string | undefined;
|
|
248
292
|
assetsOutputPath: string | undefined;
|
|
249
293
|
|
|
294
|
+
logoPath: string;
|
|
295
|
+
darkLogoPath: string | undefined;
|
|
296
|
+
brandPath: string | undefined;
|
|
297
|
+
darkBrandPath: string | undefined;
|
|
298
|
+
|
|
250
299
|
logoHeight: number;
|
|
251
300
|
logoWidth: number;
|
|
252
301
|
brandHeight: number;
|
|
253
302
|
brandWidth: number;
|
|
254
303
|
|
|
255
304
|
background: Color;
|
|
305
|
+
logo: Sharp;
|
|
256
306
|
brand: Sharp | undefined;
|
|
257
307
|
|
|
258
308
|
darkBackground: Color | undefined;
|
|
@@ -272,11 +322,12 @@ const requireAddon = ():
|
|
|
272
322
|
};
|
|
273
323
|
|
|
274
324
|
export const generate: CommandFunction<{
|
|
275
|
-
|
|
325
|
+
platforms: string[];
|
|
276
326
|
background: string;
|
|
327
|
+
logoWidth: number;
|
|
277
328
|
assetsOutput?: string;
|
|
329
|
+
html: string;
|
|
278
330
|
flavor: string;
|
|
279
|
-
platforms: string[];
|
|
280
331
|
|
|
281
332
|
licenseKey?: string;
|
|
282
333
|
brand?: string;
|
|
@@ -287,7 +338,7 @@ export const generate: CommandFunction<{
|
|
|
287
338
|
}> = async (
|
|
288
339
|
[argsLogo],
|
|
289
340
|
{ project: { android, ios } },
|
|
290
|
-
{
|
|
341
|
+
{ platforms, html, flavor, licenseKey, ...args },
|
|
291
342
|
) => {
|
|
292
343
|
const [nodeStringVersion = ""] = process.versions.node.split(".");
|
|
293
344
|
const nodeVersion = parseInt(nodeStringVersion, 10);
|
|
@@ -302,34 +353,38 @@ export const generate: CommandFunction<{
|
|
|
302
353
|
process.exit(1);
|
|
303
354
|
}
|
|
304
355
|
|
|
356
|
+
const logoPath = path.resolve(workingPath, argsLogo);
|
|
357
|
+
|
|
358
|
+
const darkLogoPath =
|
|
359
|
+
args.darkLogo != null
|
|
360
|
+
? path.resolve(workingPath, args.darkLogo)
|
|
361
|
+
: undefined;
|
|
362
|
+
|
|
363
|
+
const brandPath =
|
|
364
|
+
args.brand != null ? path.resolve(workingPath, args.brand) : undefined;
|
|
365
|
+
|
|
366
|
+
const darkBrandPath =
|
|
367
|
+
args.darkBrand != null
|
|
368
|
+
? path.resolve(workingPath, args.darkBrand)
|
|
369
|
+
: undefined;
|
|
370
|
+
|
|
305
371
|
const assetsOutputPath =
|
|
306
372
|
args.assetsOutput != null
|
|
307
373
|
? path.resolve(workingPath, args.assetsOutput)
|
|
308
374
|
: undefined;
|
|
309
375
|
|
|
376
|
+
const logo = sharp(logoPath);
|
|
377
|
+
const darkLogo = darkLogoPath != null ? sharp(darkLogoPath) : undefined;
|
|
378
|
+
const brand = brandPath != null ? sharp(brandPath) : undefined;
|
|
379
|
+
const darkBrand = darkBrandPath != null ? sharp(darkBrandPath) : undefined;
|
|
380
|
+
|
|
310
381
|
const background = parseColor(args.background);
|
|
311
|
-
const logo = sharp(path.resolve(workingPath, argsLogo));
|
|
312
382
|
const logoWidth = args.logoWidth - (args.logoWidth % 2);
|
|
313
383
|
const brandWidth = args.brandWidth - (args.brandWidth % 2);
|
|
314
384
|
|
|
315
|
-
const brand =
|
|
316
|
-
args.brand != null
|
|
317
|
-
? sharp(path.resolve(workingPath, args.brand))
|
|
318
|
-
: undefined;
|
|
319
|
-
|
|
320
385
|
const darkBackground =
|
|
321
386
|
args.darkBackground != null ? parseColor(args.darkBackground) : undefined;
|
|
322
387
|
|
|
323
|
-
const darkLogo =
|
|
324
|
-
args.darkLogo != null
|
|
325
|
-
? sharp(path.resolve(workingPath, args.darkLogo))
|
|
326
|
-
: undefined;
|
|
327
|
-
|
|
328
|
-
const darkBrand =
|
|
329
|
-
args.darkBrand != null
|
|
330
|
-
? sharp(path.resolve(workingPath, args.darkBrand))
|
|
331
|
-
: undefined;
|
|
332
|
-
|
|
333
388
|
const executeAddon =
|
|
334
389
|
brand != null ||
|
|
335
390
|
darkBackground != null ||
|
|
@@ -409,6 +464,10 @@ export const generate: CommandFunction<{
|
|
|
409
464
|
? getIOSProjectPath(ios)
|
|
410
465
|
: undefined;
|
|
411
466
|
|
|
467
|
+
const htmlTemplatePath = platforms.includes("web")
|
|
468
|
+
? getHtmlTemplatePath(html)
|
|
469
|
+
: undefined;
|
|
470
|
+
|
|
412
471
|
if (androidResPath != null) {
|
|
413
472
|
log.title("🤖", "Android");
|
|
414
473
|
|
|
@@ -419,13 +478,19 @@ export const generate: CommandFunction<{
|
|
|
419
478
|
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
420
479
|
|
|
421
480
|
if (fs.existsSync(colorsXmlPath)) {
|
|
422
|
-
const {
|
|
423
|
-
|
|
424
|
-
const
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
481
|
+
const { root, formatOptions } = readXml(colorsXmlPath);
|
|
482
|
+
const nextColor = parseHtml(colorsXmlEntry);
|
|
483
|
+
const prevColor = root.querySelector(
|
|
484
|
+
'color[name="bootsplash_background"]',
|
|
485
|
+
);
|
|
486
|
+
|
|
487
|
+
if (prevColor != null) {
|
|
488
|
+
prevColor.replaceWith(nextColor);
|
|
489
|
+
} else {
|
|
490
|
+
root.querySelector("resources")?.appendChild(nextColor);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
writeXml(colorsXmlPath, root.toString(), formatOptions);
|
|
429
494
|
} else {
|
|
430
495
|
writeXml(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`);
|
|
431
496
|
}
|
|
@@ -493,18 +558,16 @@ export const generate: CommandFunction<{
|
|
|
493
558
|
"BootSplash.storyboard",
|
|
494
559
|
);
|
|
495
560
|
|
|
496
|
-
|
|
561
|
+
writeXml(
|
|
497
562
|
storyboardPath,
|
|
498
563
|
getStoryboard({
|
|
499
564
|
logoHeight,
|
|
500
565
|
logoWidth,
|
|
501
566
|
background: background.rgb,
|
|
502
567
|
}),
|
|
503
|
-
|
|
568
|
+
{ whiteSpaceAtEndOfSelfclosingTag: false },
|
|
504
569
|
);
|
|
505
570
|
|
|
506
|
-
logWrite(storyboardPath);
|
|
507
|
-
|
|
508
571
|
const imageSetPath = path.resolve(
|
|
509
572
|
iosProjectPath,
|
|
510
573
|
"Images.xcassets",
|
|
@@ -560,6 +623,70 @@ export const generate: CommandFunction<{
|
|
|
560
623
|
);
|
|
561
624
|
}
|
|
562
625
|
|
|
626
|
+
if (htmlTemplatePath != null) {
|
|
627
|
+
log.title("🌐", "Web");
|
|
628
|
+
|
|
629
|
+
const { root, formatOptions } = readHtml(htmlTemplatePath);
|
|
630
|
+
const { format } = await logo.metadata();
|
|
631
|
+
const prevStyle = root.querySelector("#bootsplash-style");
|
|
632
|
+
|
|
633
|
+
const base64 = (
|
|
634
|
+
format === "svg"
|
|
635
|
+
? fs.readFileSync(logoPath)
|
|
636
|
+
: await logo
|
|
637
|
+
.clone()
|
|
638
|
+
.resize(Math.round(logoWidth * 2))
|
|
639
|
+
.png({ quality: 100 })
|
|
640
|
+
.toBuffer()
|
|
641
|
+
).toString("base64");
|
|
642
|
+
|
|
643
|
+
const dataURI = `data:image/${format ? "svg+xml" : "png"};base64,${base64}`;
|
|
644
|
+
|
|
645
|
+
const nextStyle = parseHtml(dedent`
|
|
646
|
+
<style id="bootsplash-style">
|
|
647
|
+
#bootsplash {
|
|
648
|
+
position: absolute;
|
|
649
|
+
top: 0;
|
|
650
|
+
bottom: 0;
|
|
651
|
+
left: 0;
|
|
652
|
+
right: 0;
|
|
653
|
+
overflow: hidden;
|
|
654
|
+
display: flex;
|
|
655
|
+
justify-content: center;
|
|
656
|
+
align-items: center;
|
|
657
|
+
background-color: ${background.hex};
|
|
658
|
+
}
|
|
659
|
+
#bootsplash-logo {
|
|
660
|
+
content: url("${dataURI}");
|
|
661
|
+
width: ${logoWidth}px;
|
|
662
|
+
height: ${logoHeight}px;
|
|
663
|
+
}
|
|
664
|
+
</style>
|
|
665
|
+
`);
|
|
666
|
+
|
|
667
|
+
if (prevStyle != null) {
|
|
668
|
+
prevStyle.replaceWith(nextStyle);
|
|
669
|
+
} else {
|
|
670
|
+
root.querySelector("head")?.appendChild(nextStyle);
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const prevDiv = root.querySelector("#bootsplash");
|
|
674
|
+
|
|
675
|
+
const nextDiv = parseHtml(dedent`
|
|
676
|
+
<div id="bootsplash">
|
|
677
|
+
<div id="bootsplash-logo"></div>
|
|
678
|
+
</div>
|
|
679
|
+
`);
|
|
680
|
+
|
|
681
|
+
if (prevDiv != null) {
|
|
682
|
+
prevDiv.replaceWith(nextDiv);
|
|
683
|
+
} else {
|
|
684
|
+
root.querySelector("body")?.appendChild(nextDiv);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
writeHtml(htmlTemplatePath, root.toString(), formatOptions);
|
|
688
|
+
}
|
|
689
|
+
|
|
563
690
|
if (assetsOutputPath != null) {
|
|
564
691
|
log.title("📄", "Assets");
|
|
565
692
|
|
|
@@ -606,6 +733,7 @@ export const generate: CommandFunction<{
|
|
|
606
733
|
|
|
607
734
|
androidResPath,
|
|
608
735
|
iosProjectPath,
|
|
736
|
+
htmlTemplatePath,
|
|
609
737
|
assetsOutputPath,
|
|
610
738
|
|
|
611
739
|
logoHeight,
|
|
@@ -613,7 +741,13 @@ export const generate: CommandFunction<{
|
|
|
613
741
|
brandHeight,
|
|
614
742
|
brandWidth,
|
|
615
743
|
|
|
744
|
+
logoPath,
|
|
745
|
+
darkLogoPath,
|
|
746
|
+
brandPath,
|
|
747
|
+
darkBrandPath,
|
|
748
|
+
|
|
616
749
|
background,
|
|
750
|
+
logo,
|
|
617
751
|
brand,
|
|
618
752
|
|
|
619
753
|
darkBackground,
|