react-native-bootsplash 6.0.0-beta.7 → 6.0.0-beta.9

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
@@ -9,6 +9,7 @@ import {
9
9
  AndroidProjectConfig,
10
10
  IOSProjectConfig,
11
11
  } from "@react-native-community/cli-types";
12
+ import childProcess from "child_process";
12
13
  import crypto from "crypto";
13
14
  import detectIndent from "detect-indent";
14
15
  import fs from "fs-extra";
@@ -21,6 +22,7 @@ import * as cssPlugin from "prettier/plugins/postcss";
21
22
  import * as prettier from "prettier/standalone";
22
23
  import sharp, { Sharp } from "sharp";
23
24
  import { dedent } from "ts-dedent";
25
+ import util from "util";
24
26
  import formatXml, { XMLFormatterOptions } from "xml-formatter";
25
27
  import { Manifest } from ".";
26
28
 
@@ -40,6 +42,11 @@ type Color = {
40
42
  rgb: RGBColor;
41
43
  };
42
44
 
45
+ const promisifiedExec = util.promisify(childProcess.exec);
46
+
47
+ const exec = (cmd: string) =>
48
+ promisifiedExec(cmd).then(({ stdout, stderr }) => stdout || stderr);
49
+
43
50
  export const log = {
44
51
  error: (text: string) => {
45
52
  console.log(pc.red(`❌ ${text}`));
@@ -458,10 +465,12 @@ const getIOSOutputPath = ({
458
465
  return iosOutputPath;
459
466
  };
460
467
 
461
- const getHtmlTemplatePath = ({
468
+ const getHtmlTemplatePath = async ({
469
+ isExpo,
462
470
  html,
463
471
  platforms,
464
472
  }: {
473
+ isExpo: boolean;
465
474
  html: string;
466
475
  platforms: Platforms;
467
476
  }) => {
@@ -469,6 +478,24 @@ const getHtmlTemplatePath = ({
469
478
  return;
470
479
  }
471
480
 
481
+ if (isExpo) {
482
+ const htmlTemplatePath = path.resolve(workingPath, html);
483
+
484
+ const htmlTemplateRelativePath = path.relative(
485
+ workingPath,
486
+ htmlTemplatePath,
487
+ );
488
+
489
+ if (
490
+ htmlTemplateRelativePath === "public/index.html" &&
491
+ !hfs.exists(htmlTemplatePath)
492
+ ) {
493
+ const cmd = `npx expo customize ${htmlTemplateRelativePath}`;
494
+ console.log(pc.dim(`Running ${cmd}`));
495
+ await exec(cmd);
496
+ }
497
+ }
498
+
472
499
  const htmlTemplatePath = path.resolve(workingPath, html);
473
500
 
474
501
  if (!hfs.exists(htmlTemplatePath)) {
@@ -687,7 +714,8 @@ export const generate = async ({
687
714
  platforms,
688
715
  });
689
716
 
690
- const htmlTemplatePath = getHtmlTemplatePath({
717
+ const htmlTemplatePath = await getHtmlTemplatePath({
718
+ isExpo,
691
719
  html,
692
720
  platforms,
693
721
  });
@@ -752,6 +780,29 @@ export const generate = async ({
752
780
  );
753
781
 
754
782
  if (!isExpo) {
783
+ const manifestXmlPath = path.resolve(
784
+ androidOutputPath,
785
+ "..",
786
+ "AndroidManifest.xml",
787
+ );
788
+
789
+ const manifestXml = readXmlLike(manifestXmlPath);
790
+ const activities = manifestXml.root.querySelectorAll("activity");
791
+
792
+ for (const activity of activities) {
793
+ if (activity.getAttribute("android:name") === ".MainActivity") {
794
+ activity.setAttribute("android:theme", "@style/BootTheme");
795
+ }
796
+ }
797
+
798
+ await writeXmlLike(manifestXmlPath, manifestXml.root.toString(), {
799
+ ...manifestXml.formatOptions,
800
+ formatter: "prettier",
801
+ htmlWhitespaceSensitivity: "ignore",
802
+ selfClosingTags: true,
803
+ singleAttributePerLine: true,
804
+ });
805
+
755
806
  const valuesPath = path.resolve(androidOutputPath, "values");
756
807
  hfs.ensureDir(valuesPath);
757
808
 
@@ -759,21 +810,21 @@ export const generate = async ({
759
810
  const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`;
760
811
 
761
812
  if (hfs.exists(colorsXmlPath)) {
762
- const { root, formatOptions } = readXmlLike(colorsXmlPath);
813
+ const colorsXml = readXmlLike(colorsXmlPath);
763
814
  const nextColor = parseHtml(colorsXmlEntry);
764
815
 
765
- const prevColor = root.querySelector(
816
+ const prevColor = colorsXml.root.querySelector(
766
817
  'color[name="bootsplash_background"]',
767
818
  );
768
819
 
769
820
  if (prevColor != null) {
770
821
  prevColor.replaceWith(nextColor);
771
822
  } else {
772
- root.querySelector("resources")?.appendChild(nextColor);
823
+ colorsXml.root.querySelector("resources")?.appendChild(nextColor);
773
824
  }
774
825
 
775
- await writeXmlLike(colorsXmlPath, root.toString(), {
776
- ...formatOptions,
826
+ await writeXmlLike(colorsXmlPath, colorsXml.root.toString(), {
827
+ ...colorsXml.formatOptions,
777
828
  formatter: "xmlFormatter",
778
829
  });
779
830
  } else {
@@ -784,88 +835,61 @@ export const generate = async ({
784
835
  );
785
836
  }
786
837
 
787
- {
788
- const manifestXmlPath = path.resolve(
789
- androidOutputPath,
790
- "..",
791
- "AndroidManifest.xml",
792
- );
838
+ const stylesXmlPath = path.resolve(valuesPath, "styles.xml");
839
+ const stylesXml = readXmlLike(stylesXmlPath);
840
+
841
+ const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]');
842
+ const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
843
+
844
+ const extraItems = parseHtml(
845
+ prevStyle?.text
846
+ .split("\n")
847
+ .map((line) => line.trim())
848
+ .join("") ?? "",
849
+ )
850
+ .childNodes.filter((node) => {
851
+ if (!(node instanceof HTMLElement)) {
852
+ return true;
853
+ }
793
854
 
794
- const { root, formatOptions } = readXmlLike(manifestXmlPath);
795
- const activities = root.querySelectorAll("activity");
855
+ const name = node.getAttribute("name");
796
856
 
797
- for (const activity of activities) {
798
- if (activity.getAttribute("android:name") === ".MainActivity") {
799
- activity.setAttribute("android:theme", "@style/BootTheme");
800
- }
801
- }
857
+ return (
858
+ name !== "bootSplashBackground" &&
859
+ name !== "bootSplashLogo" &&
860
+ name !== "bootSplashBrand" &&
861
+ name !== "postBootSplashTheme"
862
+ );
863
+ })
864
+ .map((node) => node.toString());
802
865
 
803
- await writeXmlLike(manifestXmlPath, root.toString(), {
804
- ...formatOptions,
805
- formatter: "prettier",
806
- htmlWhitespaceSensitivity: "ignore",
807
- selfClosingTags: true,
808
- singleAttributePerLine: true,
809
- });
810
- }
866
+ const styleItems: string[] = [
867
+ ...(extraItems.length > 0 ? [...extraItems, ""] : []),
811
868
 
812
- {
813
- const stylesXmlPath = path.resolve(valuesPath, "styles.xml");
814
- const { root, formatOptions } = readXmlLike(stylesXmlPath);
815
-
816
- const prevStyle = root.querySelector('style[name="BootTheme"]');
817
- const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash";
818
-
819
- const extraItems = parseHtml(
820
- prevStyle?.text
821
- .split("\n")
822
- .map((line) => line.trim())
823
- .join("") ?? "",
824
- )
825
- .childNodes.filter((node) => {
826
- if (!(node instanceof HTMLElement)) {
827
- return true;
828
- }
829
-
830
- const name = node.getAttribute("name");
831
-
832
- return (
833
- name !== "bootSplashBackground" &&
834
- name !== "bootSplashLogo" &&
835
- name !== "bootSplashBrand" &&
836
- name !== "postBootSplashTheme"
837
- );
838
- })
839
- .map((node) => node.toString());
840
-
841
- const styleItems: string[] = [
842
- ...(extraItems.length > 0 ? [...extraItems, ""] : []),
843
-
844
- '<item name="bootSplashBackground">@color/bootsplash_background</item>',
845
- '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>',
846
-
847
- ...(brand != null && brandPath != null
848
- ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>']
849
- : []),
850
-
851
- '<item name="postBootSplashTheme">@style/AppTheme</item>',
852
- ];
853
-
854
- const nextStyle = parseHtml(dedent`
855
- <style name="BootTheme" parent="${parent}">
856
- ${styleItems.join("\n")}
857
- </style>
858
- `);
859
-
860
- prevStyle?.remove(); // remove the existing style
861
- root.querySelector("resources")?.appendChild(nextStyle);
862
-
863
- await writeXmlLike(stylesXmlPath, root.toString(), {
864
- ...formatOptions,
865
- formatter: "prettier",
866
- htmlWhitespaceSensitivity: "ignore",
867
- });
868
- }
869
+ '<item name="bootSplashBackground">@color/bootsplash_background</item>',
870
+ '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>',
871
+
872
+ ...(brand != null && brandPath != null
873
+ ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>']
874
+ : []),
875
+
876
+ '<item name="postBootSplashTheme">@style/AppTheme</item>',
877
+ ];
878
+
879
+ const nextStyle = parseHtml(dedent`
880
+ <style name="BootTheme" parent="${parent}">
881
+ ${styleItems.join("\n")}
882
+ </style>
883
+ `);
884
+
885
+ prevStyle?.remove(); // remove the existing style
886
+ stylesXml.root.querySelector("resources")?.appendChild(nextStyle);
887
+
888
+ await writeXmlLike(stylesXmlPath, stylesXml.root.toString(), {
889
+ ...stylesXml.formatOptions,
890
+ formatter: "prettier",
891
+ htmlWhitespaceSensitivity: "ignore",
892
+ });
869
893
  }
870
894
  }
871
895
 
@@ -1006,18 +1030,19 @@ export const generate = async ({
1006
1030
 
1007
1031
  const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot);
1008
1032
  const projectName = path.basename(iosOutputPath);
1033
+ const groupName = path.parse(xcodeProjectPath).name;
1009
1034
 
1010
1035
  Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
1011
- filepath: path.join(projectName, "BootSplash.storyboard"),
1012
- groupName: path.parse(xcodeProjectPath).name,
1013
1036
  project,
1037
+ filepath: path.join(projectName, "BootSplash.storyboard"),
1038
+ groupName,
1014
1039
  isBuildFile: true,
1015
1040
  });
1016
1041
 
1017
1042
  Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({
1018
- filepath: path.join(projectName, "Colors.xcassets"),
1019
- groupName: path.parse(xcodeProjectPath).name,
1020
1043
  project,
1044
+ filepath: path.join(projectName, "Colors.xcassets"),
1045
+ groupName,
1021
1046
  isBuildFile: true,
1022
1047
  });
1023
1048
 
@@ -1029,9 +1054,9 @@ export const generate = async ({
1029
1054
  if (htmlTemplatePath != null) {
1030
1055
  log.title("🌐", "Web");
1031
1056
 
1032
- const { root, formatOptions } = readXmlLike(htmlTemplatePath);
1057
+ const htmlTemplate = readXmlLike(htmlTemplatePath);
1033
1058
  const { format } = await logo.metadata();
1034
- const prevStyle = root.querySelector("#bootsplash-style");
1059
+ const prevStyle = htmlTemplate.root.querySelector("#bootsplash-style");
1035
1060
 
1036
1061
  const base64 = (
1037
1062
  format === "svg"
@@ -1070,10 +1095,10 @@ export const generate = async ({
1070
1095
  if (prevStyle != null) {
1071
1096
  prevStyle.replaceWith(nextStyle);
1072
1097
  } else {
1073
- root.querySelector("head")?.appendChild(nextStyle);
1098
+ htmlTemplate.root.querySelector("head")?.appendChild(nextStyle);
1074
1099
  }
1075
1100
 
1076
- const prevDiv = root.querySelector("#bootsplash");
1101
+ const prevDiv = htmlTemplate.root.querySelector("#bootsplash");
1077
1102
 
1078
1103
  const nextDiv = parseHtml(dedent`
1079
1104
  <div id="bootsplash">
@@ -1084,11 +1109,11 @@ export const generate = async ({
1084
1109
  if (prevDiv != null) {
1085
1110
  prevDiv.replaceWith(nextDiv);
1086
1111
  } else {
1087
- root.querySelector("body")?.appendChild(nextDiv);
1112
+ htmlTemplate.root.querySelector("body")?.appendChild(nextDiv);
1088
1113
  }
1089
1114
 
1090
- await writeXmlLike(htmlTemplatePath, root.toString(), {
1091
- ...formatOptions,
1115
+ await writeXmlLike(htmlTemplatePath, htmlTemplate.root.toString(), {
1116
+ ...htmlTemplate.formatOptions,
1092
1117
  formatter: "prettier",
1093
1118
  useCssPlugin: true,
1094
1119
  });