UNPKG

react-native-bootsplash

Version:

Display a bootsplash on your app starts. Hide it when you want.

274 lines (273 loc) 11.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generate = void 0; var Expo = _interopRequireWildcard(require("@expo/config-plugins")); var _plist = _interopRequireDefault(require("@expo/plist")); var _fastGlob = _interopRequireDefault(require("fast-glob")); var _fs = _interopRequireDefault(require("fs")); var _nodeHtmlParser = require("node-html-parser"); var _path = _interopRequireDefault(require("path")); var _picocolors = _interopRequireDefault(require("picocolors")); var _tsDedent = require("ts-dedent"); var _xmlFormatter = _interopRequireDefault(require("xml-formatter")); var _utils = require("./utils.js"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } const cwd = process.env.INIT_CWD ?? process.env.PWD ?? process.cwd(); (0, _utils.setLoggerMode)({ type: "cli", cwd }); const projectRoot = (() => { let directory = _path.default.resolve(cwd); const { root } = _path.default.parse(directory); const ends = new Set([root, _path.default.resolve(directory, root)]); while (directory) { const pkgPath = _path.default.join(directory, "package.json"); const stats = _fs.default.statSync(pkgPath, { throwIfNoEntry: false }); if (stats != null && stats.isFile()) { return _path.default.dirname(pkgPath); } if (ends.has(directory)) { break; } else { directory = _path.default.dirname(directory); } } })(); if (!projectRoot) { _utils.log.error("We couldn't find a package.json in your project."); process.exit(1); } const getAndroidOutputPath = ({ flavor }) => { const sourceDir = _path.default.join(projectRoot, "android"); if (!_fs.default.existsSync(sourceDir)) { return; } const appDir = _path.default.join(sourceDir, "app"); const androidOutputPath = _path.default.resolve(sourceDir, _fs.default.existsSync(appDir) ? "app" : "", "src", flavor, "res"); if (_utils.hfs.exists(androidOutputPath)) { return androidOutputPath; } _utils.log.warn(`No ${_path.default.relative(cwd, androidOutputPath)} directory found. Skipping Android assets generation…`); }; const getIOSOutputPath = () => { const podfile = _fastGlob.default.sync("**/Podfile", { cwd: projectRoot.replace(/^([a-zA-Z]+:|\.\/)/, ""), deep: 10, ignore: ["**/@(Pods|node_modules|Carthage|vendor|android)/**"] }).find(project => { return _path.default.dirname(project) === "ios"; }); if (!podfile) { return; } const sourceDir = _path.default.dirname(_path.default.join(projectRoot, podfile)); const xcodeProjectName = _fs.default.readdirSync(sourceDir).sort().reverse().find(fileName => { const ext = _path.default.extname(fileName); return ext === ".xcodeproj" || ext === ".xcworkspace"; }); if (xcodeProjectName == null) { _utils.log.warn("No Xcode project found. Skipping iOS assets generation…"); return; } const iosOutputPath = _path.default.resolve(sourceDir, xcodeProjectName).replace(/\.(xcodeproj|xcworkspace)$/, ""); if (_utils.hfs.exists(iosOutputPath)) { return iosOutputPath; } _utils.log.warn(`No ${_path.default.relative(cwd, iosOutputPath)} directory found. Skipping iOS assets generation…`); }; const getHtmlTemplatePath = ({ html }) => { const htmlTemplatePath = _path.default.resolve(cwd, html); if (_utils.hfs.exists(htmlTemplatePath)) { return htmlTemplatePath; } _utils.log.warn(`No ${_path.default.relative(cwd, htmlTemplatePath)} found. Skipping HTML + CSS generation…`); }; const getInfoPlistPath = ({ iosOutputPath, plist }) => { if (plist != null) { const infoPlistPath = _path.default.resolve(cwd, plist); if (!_utils.hfs.exists(infoPlistPath)) { return _utils.log.warn(`No ${_path.default.relative(cwd, infoPlistPath)} found`); } return infoPlistPath; } return _path.default.resolve(iosOutputPath, "Info.plist"); }; const generate = async ({ platforms, html, flavor, plist, ...rawProps }) => { const props = await (0, _utils.transformProps)(cwd, rawProps); const addon = (0, _utils.requireAddon)(props); const { background, brand } = props; const androidOutputPath = platforms.includes("android") ? getAndroidOutputPath({ flavor }) : undefined; const iosOutputPath = platforms.includes("ios") ? getIOSOutputPath() : undefined; const htmlTemplatePath = platforms.includes("web") ? getHtmlTemplatePath({ html }) : undefined; if (androidOutputPath != null) { await (0, _utils.writeAndroidAssets)({ androidOutputPath, props }); const manifestXmlPath = _path.default.resolve(androidOutputPath, "..", "AndroidManifest.xml"); if (_utils.hfs.exists(manifestXmlPath)) { const manifestXml = (0, _utils.readXmlLike)(manifestXmlPath); const activities = manifestXml.root.querySelectorAll("activity"); for (const activity of activities) { if (activity.getAttribute("android:name") === ".MainActivity") { activity.setAttribute("android:theme", "@style/BootTheme"); } } await (0, _utils.writeXmlLike)(manifestXmlPath, manifestXml.root.toString(), { ...manifestXml.formatOptions, formatter: "prettier", htmlWhitespaceSensitivity: "ignore", selfClosingTags: true, singleAttributePerLine: true }); } else { _utils.log.warn("No AndroidManifest.xml found"); } const valuesPath = _path.default.resolve(androidOutputPath, "values"); _utils.hfs.ensureDir(valuesPath); const colorsXmlPath = _path.default.resolve(valuesPath, "colors.xml"); const colorsXmlEntry = `<color name="bootsplash_background">${background.hex}</color>`; if (_utils.hfs.exists(colorsXmlPath)) { const colorsXml = (0, _utils.readXmlLike)(colorsXmlPath); const nextColor = (0, _nodeHtmlParser.parse)(colorsXmlEntry); const prevColor = colorsXml.root.querySelector('color[name="bootsplash_background"]'); if (prevColor != null) { prevColor.replaceWith(nextColor); } else { colorsXml.root.querySelector("resources")?.appendChild(nextColor); } await (0, _utils.writeXmlLike)(colorsXmlPath, colorsXml.root.toString(), { ...colorsXml.formatOptions, formatter: "xmlFormatter" }); } else { await (0, _utils.writeXmlLike)(colorsXmlPath, `<resources>${colorsXmlEntry}</resources>`, { formatter: "xmlFormatter" }); } const stylesXmlPath = _path.default.resolve(valuesPath, "styles.xml"); if (_utils.hfs.exists(stylesXmlPath)) { const stylesXml = (0, _utils.readXmlLike)(stylesXmlPath); const prevStyle = stylesXml.root.querySelector('style[name="BootTheme"]'); const parent = prevStyle?.getAttribute("parent") ?? "Theme.BootSplash"; const extraItems = (0, _nodeHtmlParser.parse)(prevStyle?.text.split("\n").map(line => line.trim()).join("") ?? "").childNodes.filter(node => { if (!(node instanceof _nodeHtmlParser.HTMLElement)) { return true; } const name = node.getAttribute("name"); return name !== "bootSplashBackground" && name !== "bootSplashLogo" && name !== "bootSplashBrand" && name !== "postBootSplashTheme"; }).map(node => node.toString()); const styleItems = [...(extraItems.length > 0 ? [...extraItems, ""] : []), '<item name="bootSplashBackground">@color/bootsplash_background</item>', '<item name="bootSplashLogo">@drawable/bootsplash_logo</item>', ...(brand != null ? ['<item name="bootSplashBrand">@drawable/bootsplash_brand</item>'] : []), '<item name="postBootSplashTheme">@style/AppTheme</item>']; const nextStyle = (0, _nodeHtmlParser.parse)((0, _tsDedent.dedent)` <style name="BootTheme" parent="${parent}"> ${styleItems.join("\n")} </style> `); prevStyle?.remove(); // remove the existing style stylesXml.root.querySelector("resources")?.appendChild(nextStyle); await (0, _utils.writeXmlLike)(stylesXmlPath, stylesXml.root.toString(), { ...stylesXml.formatOptions, formatter: "prettier", htmlWhitespaceSensitivity: "ignore" }); } else { _utils.log.warn("No styles.xml found"); } } if (iosOutputPath != null) { await (0, _utils.writeIOSAssets)({ iosOutputPath, props }); const pbxprojectPath = Expo.IOSConfig.Paths.getPBXProjectPath(projectRoot); const xcodeProjectPath = Expo.IOSConfig.Paths.getXcodeProjectPath(projectRoot); const project = Expo.IOSConfig.XcodeUtils.getPbxproj(projectRoot); const projectName = _path.default.basename(iosOutputPath); const groupName = _path.default.parse(xcodeProjectPath).name; Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({ project, filepath: _path.default.join(projectName, "BootSplash.storyboard"), groupName, isBuildFile: true }); Expo.IOSConfig.XcodeUtils.addResourceFileToGroup({ project, filepath: _path.default.join(projectName, "Colors.xcassets"), groupName, isBuildFile: true }); _utils.hfs.write(pbxprojectPath, project.writeSync()); _utils.log.write(pbxprojectPath); const infoPlistPath = getInfoPlistPath({ iosOutputPath, plist }); if (infoPlistPath != null) { const infoPlist = _plist.default.parse(_utils.hfs.text(infoPlistPath)); infoPlist["UILaunchStoryboardName"] = "BootSplash"; const formatted = (0, _xmlFormatter.default)(_plist.default.build(infoPlist), { collapseContent: true, forceSelfClosingEmptyTag: false, indentation: "\t", lineSeparator: "\n", whiteSpaceAtEndOfSelfclosingTag: false }).replace(/<string\/>/gm, "<string></string>").replace(/^\t/gm, ""); _utils.hfs.write(infoPlistPath, formatted); _utils.log.write(infoPlistPath); } } if (htmlTemplatePath != null) { await (0, _utils.writeWebAssets)({ htmlTemplatePath, props }); } await (0, _utils.writeGenericAssets)({ props }); if (addon != null) { await addon.execute({ props, androidOutputPath, iosOutputPath, htmlTemplatePath }); } else { console.log(` ${_picocolors.default.blue("┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓")} ${_picocolors.default.blue("┃")} 🔑 ${_picocolors.default.bold("Get a license key for brand image / dark mode support")} ${_picocolors.default.blue("┃")} ${_picocolors.default.blue("┃")} ${_picocolors.default.underline("https://zoontek.gumroad.com/l/bootsplash-generator")} ${_picocolors.default.blue("┃")} ${_picocolors.default.blue("┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛")}`); } console.log(`\n💖 Thanks for using ${_picocolors.default.underline("react-native-bootsplash")}`); }; exports.generate = generate; //# sourceMappingURL=generate.js.map