react-native-bootsplash 5.2.2 → 5.4.0
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 +5 -15
- package/dist/commonjs/addon/index.js +29 -29
- package/dist/commonjs/addon/index.js.map +1 -1
- package/dist/commonjs/generate.js +100 -33
- package/dist/commonjs/generate.js.map +1 -1
- package/dist/module/addon/index.js +29 -29
- package/dist/module/addon/index.js.map +1 -1
- package/dist/module/generate.js +96 -32
- package/dist/module/generate.js.map +1 -1
- package/dist/typescript/addon/index.d.ts.map +1 -1
- package/dist/typescript/generate.d.ts +31 -9
- package/dist/typescript/generate.d.ts.map +1 -1
- package/package.json +6 -7
- package/react-native.config.js +2 -2
- package/src/generate.ts +133 -34
package/src/generate.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import murmurhash from "@emotion/hash";
|
|
2
|
+
import { IOSConfig } from "@expo/config-plugins";
|
|
3
|
+
import plist from "@expo/plist";
|
|
4
|
+
import { findProjectRoot } from "@react-native-community/cli-tools";
|
|
1
5
|
import {
|
|
2
6
|
AndroidProjectConfig,
|
|
3
|
-
CommandFunction,
|
|
4
7
|
IOSProjectConfig,
|
|
5
8
|
} from "@react-native-community/cli-types";
|
|
6
9
|
import detectIndent from "detect-indent";
|
|
7
|
-
import fs from "fs
|
|
10
|
+
import fs from "fs";
|
|
8
11
|
import { parse as parseHtml } from "node-html-parser";
|
|
9
12
|
import path from "path";
|
|
10
13
|
import pc from "picocolors";
|
|
@@ -102,6 +105,42 @@ const getStoryboard = ({
|
|
|
102
105
|
`;
|
|
103
106
|
};
|
|
104
107
|
|
|
108
|
+
export const addFileToXcodeProject = (filePath: string) => {
|
|
109
|
+
const projectRoot = findProjectRoot(workingPath);
|
|
110
|
+
|
|
111
|
+
const pbxprojectPath = IOSConfig.Paths.getPBXProjectPath(projectRoot);
|
|
112
|
+
const project = IOSConfig.XcodeUtils.getPbxproj(projectRoot);
|
|
113
|
+
const xcodeProjectPath = IOSConfig.Paths.getXcodeProjectPath(projectRoot);
|
|
114
|
+
|
|
115
|
+
IOSConfig.XcodeUtils.addResourceFileToGroup({
|
|
116
|
+
filepath: filePath,
|
|
117
|
+
groupName: path.parse(xcodeProjectPath).name,
|
|
118
|
+
project,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
hfs.write(pbxprojectPath, project.writeSync());
|
|
122
|
+
logWrite(pbxprojectPath);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
// Freely inspired by https://github.com/humanwhocodes/humanfs
|
|
126
|
+
export const hfs = {
|
|
127
|
+
buffer: (path: string) => fs.readFileSync(path),
|
|
128
|
+
exists: (path: string) => fs.existsSync(path),
|
|
129
|
+
json: (path: string) => JSON.parse(fs.readFileSync(path, "utf-8")) as unknown,
|
|
130
|
+
readDir: (path: string) => fs.readdirSync(path, "utf-8"),
|
|
131
|
+
realPath: (path: string) => fs.realpathSync(path, "utf-8"),
|
|
132
|
+
rm: (path: string) => fs.rmSync(path, { force: true }),
|
|
133
|
+
text: (path: string) => fs.readFileSync(path, "utf-8"),
|
|
134
|
+
|
|
135
|
+
ensureDir: (dir: string) => {
|
|
136
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
137
|
+
},
|
|
138
|
+
write: (file: string, data: string) => {
|
|
139
|
+
const trimmed = data.trim();
|
|
140
|
+
fs.writeFileSync(file, trimmed === "" ? trimmed : trimmed + "\n", "utf-8");
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
|
|
105
144
|
export const log = {
|
|
106
145
|
error: (text: string) => console.log(pc.red(`❌ ${text}`)),
|
|
107
146
|
text: (text: string) => console.log(text),
|
|
@@ -120,12 +159,12 @@ export const logWrite = (
|
|
|
120
159
|
);
|
|
121
160
|
|
|
122
161
|
export const writeJson = (file: string, json: object) => {
|
|
123
|
-
|
|
162
|
+
hfs.write(file, JSON.stringify(json, null, 2));
|
|
124
163
|
logWrite(file);
|
|
125
164
|
};
|
|
126
165
|
|
|
127
166
|
export const readXml = (file: string) => {
|
|
128
|
-
const xml =
|
|
167
|
+
const xml = hfs.text(file);
|
|
129
168
|
const { indent } = detectIndent(xml);
|
|
130
169
|
|
|
131
170
|
const formatOptions: XMLFormatterOptions = {
|
|
@@ -149,12 +188,12 @@ export const writeXml = (
|
|
|
149
188
|
...options,
|
|
150
189
|
});
|
|
151
190
|
|
|
152
|
-
|
|
191
|
+
hfs.write(file, formatted);
|
|
153
192
|
logWrite(file);
|
|
154
193
|
};
|
|
155
194
|
|
|
156
195
|
export const readHtml = (file: string) => {
|
|
157
|
-
const html =
|
|
196
|
+
const html = hfs.text(file);
|
|
158
197
|
const { type, amount } = detectIndent(html);
|
|
159
198
|
|
|
160
199
|
const formatOptions: PrettierOptions = {
|
|
@@ -178,10 +217,37 @@ export const writeHtml = async (
|
|
|
178
217
|
...options,
|
|
179
218
|
});
|
|
180
219
|
|
|
181
|
-
|
|
220
|
+
hfs.write(file, formatted);
|
|
182
221
|
logWrite(file);
|
|
183
222
|
};
|
|
184
223
|
|
|
224
|
+
export const cleanIOSAssets = (dir: string, prefix: string) => {
|
|
225
|
+
hfs
|
|
226
|
+
.readDir(dir)
|
|
227
|
+
.filter((file) => file.startsWith(prefix) && file.endsWith(".png"))
|
|
228
|
+
.map((file) => path.join(dir, file))
|
|
229
|
+
.forEach((file) => hfs.rm(file));
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
export const getIOSAssetFileName = async ({
|
|
233
|
+
name,
|
|
234
|
+
image,
|
|
235
|
+
width,
|
|
236
|
+
}: {
|
|
237
|
+
name: string;
|
|
238
|
+
image: Sharp;
|
|
239
|
+
width: number;
|
|
240
|
+
}) => {
|
|
241
|
+
const buffer = await image
|
|
242
|
+
.clone()
|
|
243
|
+
.resize(width)
|
|
244
|
+
.png({ quality: 100 })
|
|
245
|
+
.toBuffer();
|
|
246
|
+
|
|
247
|
+
const hash = murmurhash(buffer.toString("base64"));
|
|
248
|
+
return `${name}-${hash}`;
|
|
249
|
+
};
|
|
250
|
+
|
|
185
251
|
const ensureSupportedFormat = async (
|
|
186
252
|
name: string,
|
|
187
253
|
image: Sharp | undefined,
|
|
@@ -222,7 +288,7 @@ const getAndroidResPath = (
|
|
|
222
288
|
"res",
|
|
223
289
|
);
|
|
224
290
|
|
|
225
|
-
if (!
|
|
291
|
+
if (!hfs.exists(androidResPath)) {
|
|
226
292
|
log.warn(
|
|
227
293
|
`No ${path.relative(
|
|
228
294
|
workingPath,
|
|
@@ -256,7 +322,7 @@ const getIOSProjectPath = (ios: IOSProjectConfig): string | undefined => {
|
|
|
256
322
|
.resolve(ios.sourceDir, ios.xcodeProject.name)
|
|
257
323
|
.replace(/\.(xcodeproj|xcworkspace)$/, "");
|
|
258
324
|
|
|
259
|
-
if (!
|
|
325
|
+
if (!hfs.exists(iosProjectPath)) {
|
|
260
326
|
log.warn(
|
|
261
327
|
`No ${path.relative(
|
|
262
328
|
workingPath,
|
|
@@ -271,7 +337,7 @@ const getIOSProjectPath = (ios: IOSProjectConfig): string | undefined => {
|
|
|
271
337
|
const getHtmlTemplatePath = (html: string): string | undefined => {
|
|
272
338
|
const htmlTemplatePath = path.resolve(workingPath, html);
|
|
273
339
|
|
|
274
|
-
if (!
|
|
340
|
+
if (!hfs.exists(htmlTemplatePath)) {
|
|
275
341
|
log.warn(
|
|
276
342
|
`No ${path.relative(
|
|
277
343
|
workingPath,
|
|
@@ -314,14 +380,25 @@ const requireAddon = ():
|
|
|
314
380
|
| { execute: (config: AddonConfig) => Promise<void> }
|
|
315
381
|
| undefined => {
|
|
316
382
|
try {
|
|
317
|
-
// eslint-disable-
|
|
318
|
-
return require("./addon");
|
|
383
|
+
return require("./addon"); // eslint-disable-line
|
|
319
384
|
} catch {
|
|
320
385
|
return;
|
|
321
386
|
}
|
|
322
387
|
};
|
|
323
388
|
|
|
324
|
-
export const generate
|
|
389
|
+
export const generate = async ({
|
|
390
|
+
android,
|
|
391
|
+
ios,
|
|
392
|
+
platforms,
|
|
393
|
+
html,
|
|
394
|
+
flavor,
|
|
395
|
+
licenseKey,
|
|
396
|
+
...args
|
|
397
|
+
}: {
|
|
398
|
+
android?: AndroidProjectConfig;
|
|
399
|
+
ios?: IOSProjectConfig;
|
|
400
|
+
|
|
401
|
+
logo: string;
|
|
325
402
|
platforms: string[];
|
|
326
403
|
background: string;
|
|
327
404
|
logoWidth: number;
|
|
@@ -335,11 +412,7 @@ export const generate: CommandFunction<{
|
|
|
335
412
|
darkBackground?: string;
|
|
336
413
|
darkLogo?: string;
|
|
337
414
|
darkBrand?: string;
|
|
338
|
-
}
|
|
339
|
-
[argsLogo],
|
|
340
|
-
{ project: { android, ios } },
|
|
341
|
-
{ platforms, html, flavor, licenseKey, ...args },
|
|
342
|
-
) => {
|
|
415
|
+
}) => {
|
|
343
416
|
const [nodeStringVersion = ""] = process.versions.node.split(".");
|
|
344
417
|
const nodeVersion = parseInt(nodeStringVersion, 10);
|
|
345
418
|
|
|
@@ -348,12 +421,7 @@ export const generate: CommandFunction<{
|
|
|
348
421
|
process.exit(1);
|
|
349
422
|
}
|
|
350
423
|
|
|
351
|
-
|
|
352
|
-
log.error("Missing required argument 'logo'");
|
|
353
|
-
process.exit(1);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
const logoPath = path.resolve(workingPath, argsLogo);
|
|
424
|
+
const logoPath = path.resolve(workingPath, args.logo);
|
|
357
425
|
|
|
358
426
|
const darkLogoPath =
|
|
359
427
|
args.darkLogo != null
|
|
@@ -472,12 +540,12 @@ export const generate: CommandFunction<{
|
|
|
472
540
|
log.title("🤖", "Android");
|
|
473
541
|
|
|
474
542
|
const valuesPath = path.resolve(androidResPath, "values");
|
|
475
|
-
|
|
543
|
+
hfs.ensureDir(valuesPath);
|
|
476
544
|
|
|
477
545
|
const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
|
|
478
546
|
const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
|
|
479
547
|
|
|
480
|
-
if (
|
|
548
|
+
if (hfs.exists(colorsXmlPath)) {
|
|
481
549
|
const { root, formatOptions } = readXml(colorsXmlPath);
|
|
482
550
|
const nextColor = parseHtml(colorsXmlEntry);
|
|
483
551
|
const prevColor = root.querySelector(
|
|
@@ -508,7 +576,7 @@ export const generate: CommandFunction<{
|
|
|
508
576
|
`drawable-${suffix}`,
|
|
509
577
|
);
|
|
510
578
|
|
|
511
|
-
|
|
579
|
+
hfs.ensureDir(drawableDirPath);
|
|
512
580
|
|
|
513
581
|
// https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
|
|
514
582
|
const canvasSize = 288 * ratio;
|
|
@@ -568,29 +636,60 @@ export const generate: CommandFunction<{
|
|
|
568
636
|
{ whiteSpaceAtEndOfSelfclosingTag: false },
|
|
569
637
|
);
|
|
570
638
|
|
|
639
|
+
addFileToXcodeProject(storyboardPath);
|
|
640
|
+
|
|
641
|
+
const infoPlistPath = path.join(iosProjectPath, "Info.plist");
|
|
642
|
+
|
|
643
|
+
const infoPlist = plist.parse(hfs.text(infoPlistPath)) as Record<
|
|
644
|
+
string,
|
|
645
|
+
unknown
|
|
646
|
+
>;
|
|
647
|
+
|
|
648
|
+
infoPlist["UILaunchStoryboardName"] = "BootSplash.storyboard";
|
|
649
|
+
|
|
650
|
+
const formatted = formatXml(plist.build(infoPlist), {
|
|
651
|
+
collapseContent: true,
|
|
652
|
+
forceSelfClosingEmptyTag: false,
|
|
653
|
+
indentation: "\t",
|
|
654
|
+
lineSeparator: "\n",
|
|
655
|
+
whiteSpaceAtEndOfSelfclosingTag: false,
|
|
656
|
+
})
|
|
657
|
+
.replace(/<string\/>/gm, "<string></string>")
|
|
658
|
+
.replace(/^\t/gm, "");
|
|
659
|
+
|
|
660
|
+
hfs.write(infoPlistPath, formatted);
|
|
661
|
+
logWrite(infoPlistPath);
|
|
662
|
+
|
|
571
663
|
const imageSetPath = path.resolve(
|
|
572
664
|
iosProjectPath,
|
|
573
665
|
"Images.xcassets",
|
|
574
666
|
"BootSplashLogo.imageset",
|
|
575
667
|
);
|
|
576
668
|
|
|
577
|
-
|
|
669
|
+
hfs.ensureDir(imageSetPath);
|
|
670
|
+
cleanIOSAssets(imageSetPath, "bootsplash_logo");
|
|
671
|
+
|
|
672
|
+
const logoFileName = await getIOSAssetFileName({
|
|
673
|
+
name: "bootsplash_logo",
|
|
674
|
+
image: logo,
|
|
675
|
+
width: logoWidth,
|
|
676
|
+
});
|
|
578
677
|
|
|
579
678
|
writeJson(path.resolve(imageSetPath, "Contents.json"), {
|
|
580
679
|
images: [
|
|
581
680
|
{
|
|
582
681
|
idiom: "universal",
|
|
583
|
-
filename:
|
|
682
|
+
filename: `${logoFileName}.png`,
|
|
584
683
|
scale: "1x",
|
|
585
684
|
},
|
|
586
685
|
{
|
|
587
686
|
idiom: "universal",
|
|
588
|
-
filename:
|
|
687
|
+
filename: `${logoFileName}@2x.png`,
|
|
589
688
|
scale: "2x",
|
|
590
689
|
},
|
|
591
690
|
{
|
|
592
691
|
idiom: "universal",
|
|
593
|
-
filename:
|
|
692
|
+
filename: `${logoFileName}@3x.png`,
|
|
594
693
|
scale: "3x",
|
|
595
694
|
},
|
|
596
695
|
],
|
|
@@ -608,7 +707,7 @@ export const generate: CommandFunction<{
|
|
|
608
707
|
].map(({ ratio, suffix }) => {
|
|
609
708
|
const filePath = path.resolve(
|
|
610
709
|
imageSetPath,
|
|
611
|
-
|
|
710
|
+
`${logoFileName}${suffix}.png`,
|
|
612
711
|
);
|
|
613
712
|
|
|
614
713
|
return logo
|
|
@@ -632,7 +731,7 @@ export const generate: CommandFunction<{
|
|
|
632
731
|
|
|
633
732
|
const base64 = (
|
|
634
733
|
format === "svg"
|
|
635
|
-
?
|
|
734
|
+
? hfs.buffer(logoPath)
|
|
636
735
|
: await logo
|
|
637
736
|
.clone()
|
|
638
737
|
.resize(Math.round(logoWidth * 2))
|
|
@@ -690,7 +789,7 @@ export const generate: CommandFunction<{
|
|
|
690
789
|
if (assetsOutputPath != null) {
|
|
691
790
|
log.title("📄", "Assets");
|
|
692
791
|
|
|
693
|
-
|
|
792
|
+
hfs.ensureDir(assetsOutputPath);
|
|
694
793
|
|
|
695
794
|
writeJson(path.resolve(assetsOutputPath, "bootsplash_manifest.json"), {
|
|
696
795
|
background: background.hex,
|