react-native-bootsplash 5.3.0 → 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/src/generate.ts CHANGED
@@ -1,11 +1,13 @@
1
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";
2
5
  import {
3
6
  AndroidProjectConfig,
4
- CommandFunction,
5
7
  IOSProjectConfig,
6
8
  } from "@react-native-community/cli-types";
7
9
  import detectIndent from "detect-indent";
8
- import fs from "fs-extra";
10
+ import fs from "fs";
9
11
  import { parse as parseHtml } from "node-html-parser";
10
12
  import path from "path";
11
13
  import pc from "picocolors";
@@ -103,6 +105,42 @@ const getStoryboard = ({
103
105
  `;
104
106
  };
105
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
+
106
144
  export const log = {
107
145
  error: (text: string) => console.log(pc.red(`❌ ${text}`)),
108
146
  text: (text: string) => console.log(text),
@@ -121,12 +159,12 @@ export const logWrite = (
121
159
  );
122
160
 
123
161
  export const writeJson = (file: string, json: object) => {
124
- fs.writeFileSync(file, JSON.stringify(json, null, 2) + "\n", "utf-8");
162
+ hfs.write(file, JSON.stringify(json, null, 2));
125
163
  logWrite(file);
126
164
  };
127
165
 
128
166
  export const readXml = (file: string) => {
129
- const xml = fs.readFileSync(file, "utf-8");
167
+ const xml = hfs.text(file);
130
168
  const { indent } = detectIndent(xml);
131
169
 
132
170
  const formatOptions: XMLFormatterOptions = {
@@ -150,12 +188,12 @@ export const writeXml = (
150
188
  ...options,
151
189
  });
152
190
 
153
- fs.writeFileSync(file, formatted + "\n", "utf-8");
191
+ hfs.write(file, formatted);
154
192
  logWrite(file);
155
193
  };
156
194
 
157
195
  export const readHtml = (file: string) => {
158
- const html = fs.readFileSync(file, "utf-8");
196
+ const html = hfs.text(file);
159
197
  const { type, amount } = detectIndent(html);
160
198
 
161
199
  const formatOptions: PrettierOptions = {
@@ -179,15 +217,16 @@ export const writeHtml = async (
179
217
  ...options,
180
218
  });
181
219
 
182
- fs.writeFileSync(file, formatted, "utf-8");
220
+ hfs.write(file, formatted);
183
221
  logWrite(file);
184
222
  };
185
223
 
186
224
  export const cleanIOSAssets = (dir: string, prefix: string) => {
187
- fs.readdirSync(dir, "utf-8")
225
+ hfs
226
+ .readDir(dir)
188
227
  .filter((file) => file.startsWith(prefix) && file.endsWith(".png"))
189
228
  .map((file) => path.join(dir, file))
190
- .forEach((file) => fs.rmSync(file, { force: true }));
229
+ .forEach((file) => hfs.rm(file));
191
230
  };
192
231
 
193
232
  export const getIOSAssetFileName = async ({
@@ -249,7 +288,7 @@ const getAndroidResPath = (
249
288
  "res",
250
289
  );
251
290
 
252
- if (!fs.existsSync(androidResPath)) {
291
+ if (!hfs.exists(androidResPath)) {
253
292
  log.warn(
254
293
  `No ${path.relative(
255
294
  workingPath,
@@ -283,7 +322,7 @@ const getIOSProjectPath = (ios: IOSProjectConfig): string | undefined => {
283
322
  .resolve(ios.sourceDir, ios.xcodeProject.name)
284
323
  .replace(/\.(xcodeproj|xcworkspace)$/, "");
285
324
 
286
- if (!fs.existsSync(iosProjectPath)) {
325
+ if (!hfs.exists(iosProjectPath)) {
287
326
  log.warn(
288
327
  `No ${path.relative(
289
328
  workingPath,
@@ -298,7 +337,7 @@ const getIOSProjectPath = (ios: IOSProjectConfig): string | undefined => {
298
337
  const getHtmlTemplatePath = (html: string): string | undefined => {
299
338
  const htmlTemplatePath = path.resolve(workingPath, html);
300
339
 
301
- if (!fs.existsSync(htmlTemplatePath)) {
340
+ if (!hfs.exists(htmlTemplatePath)) {
302
341
  log.warn(
303
342
  `No ${path.relative(
304
343
  workingPath,
@@ -347,7 +386,19 @@ const requireAddon = ():
347
386
  }
348
387
  };
349
388
 
350
- export const generate: CommandFunction<{
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;
351
402
  platforms: string[];
352
403
  background: string;
353
404
  logoWidth: number;
@@ -361,11 +412,7 @@ export const generate: CommandFunction<{
361
412
  darkBackground?: string;
362
413
  darkLogo?: string;
363
414
  darkBrand?: string;
364
- }> = async (
365
- [argsLogo],
366
- { project: { android, ios } },
367
- { platforms, html, flavor, licenseKey, ...args },
368
- ) => {
415
+ }) => {
369
416
  const [nodeStringVersion = ""] = process.versions.node.split(".");
370
417
  const nodeVersion = parseInt(nodeStringVersion, 10);
371
418
 
@@ -374,12 +421,7 @@ export const generate: CommandFunction<{
374
421
  process.exit(1);
375
422
  }
376
423
 
377
- if (argsLogo == null) {
378
- log.error("Missing required argument 'logo'");
379
- process.exit(1);
380
- }
381
-
382
- const logoPath = path.resolve(workingPath, argsLogo);
424
+ const logoPath = path.resolve(workingPath, args.logo);
383
425
 
384
426
  const darkLogoPath =
385
427
  args.darkLogo != null
@@ -498,12 +540,12 @@ export const generate: CommandFunction<{
498
540
  log.title("🤖", "Android");
499
541
 
500
542
  const valuesPath = path.resolve(androidResPath, "values");
501
- fs.ensureDirSync(valuesPath);
543
+ hfs.ensureDir(valuesPath);
502
544
 
503
545
  const colorsXmlPath = path.resolve(valuesPath, "colors.xml");
504
546
  const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
505
547
 
506
- if (fs.existsSync(colorsXmlPath)) {
548
+ if (hfs.exists(colorsXmlPath)) {
507
549
  const { root, formatOptions } = readXml(colorsXmlPath);
508
550
  const nextColor = parseHtml(colorsXmlEntry);
509
551
  const prevColor = root.querySelector(
@@ -534,7 +576,7 @@ export const generate: CommandFunction<{
534
576
  `drawable-${suffix}`,
535
577
  );
536
578
 
537
- fs.ensureDirSync(drawableDirPath);
579
+ hfs.ensureDir(drawableDirPath);
538
580
 
539
581
  // https://developer.android.com/develop/ui/views/launch/splash-screen#dimensions
540
582
  const canvasSize = 288 * ratio;
@@ -594,13 +636,37 @@ export const generate: CommandFunction<{
594
636
  { whiteSpaceAtEndOfSelfclosingTag: false },
595
637
  );
596
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
+
597
663
  const imageSetPath = path.resolve(
598
664
  iosProjectPath,
599
665
  "Images.xcassets",
600
666
  "BootSplashLogo.imageset",
601
667
  );
602
668
 
603
- fs.ensureDirSync(imageSetPath);
669
+ hfs.ensureDir(imageSetPath);
604
670
  cleanIOSAssets(imageSetPath, "bootsplash_logo");
605
671
 
606
672
  const logoFileName = await getIOSAssetFileName({
@@ -665,7 +731,7 @@ export const generate: CommandFunction<{
665
731
 
666
732
  const base64 = (
667
733
  format === "svg"
668
- ? fs.readFileSync(logoPath)
734
+ ? hfs.buffer(logoPath)
669
735
  : await logo
670
736
  .clone()
671
737
  .resize(Math.round(logoWidth * 2))
@@ -723,7 +789,7 @@ export const generate: CommandFunction<{
723
789
  if (assetsOutputPath != null) {
724
790
  log.title("📄", "Assets");
725
791
 
726
- fs.ensureDirSync(assetsOutputPath);
792
+ hfs.ensureDir(assetsOutputPath);
727
793
 
728
794
  writeJson(path.resolve(assetsOutputPath, "bootsplash_manifest.json"), {
729
795
  background: background.hex,