diff --git a/README.md b/README.md index 6a9d0b2..791f408 100644 --- a/README.md +++ b/README.md @@ -5,10 +5,6 @@ Make your expo apps start faster by loading fonts at build time `expo-font` load fonts at runtime. This increases the startup time -### iOS ⚠️ - -Currently it only works on Android. PRs for adding iOS support are welcome - ### Installation ⚙️ ```bash @@ -20,7 +16,12 @@ Add to your plugins on `app.json` ```json { "name": "my app", - "plugins": ["with-expo-fonts"] + "plugins": [[ + "with-expo-fonts", + { + path: "./assets/fonts", + }, + ]] } ``` diff --git a/build/index.d.ts b/build/index.d.ts index 93ebf45..a62736f 100644 --- a/build/index.d.ts +++ b/build/index.d.ts @@ -1,2 +1,5 @@ -export { default } from "./withExpoFonts"; +import { ConfigPlugin } from "@expo/config-plugins"; +import { PluginConfigType } from "./pluginConfigType"; +declare const _default: ConfigPlugin; +export default _default; //# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/build/index.d.ts.map b/build/index.d.ts.map index 89aed8c..0f7d92c 100644 --- a/build/index.d.ts.map +++ b/build/index.d.ts.map @@ -1 +1 @@ -{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC"} \ No newline at end of file +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,sBAAsB,CAAC;AAKzE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;;AAWtD,wBAAyE"} \ No newline at end of file diff --git a/build/index.js b/build/index.js index c27ad5d..6012171 100644 --- a/build/index.js +++ b/build/index.js @@ -1,9 +1,15 @@ "use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); -exports.default = void 0; -var withExpoFonts_1 = require("./withExpoFonts"); -Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(withExpoFonts_1).default; } }); +const config_plugins_1 = require("@expo/config-plugins"); +const withAndroidExpoFonts_1 = require("./withAndroidExpoFonts"); +const withInfoPlistExpoFonts_1 = require("./withInfoPlistExpoFonts"); +const withXcodeProjectExpoFonts_1 = require("./withXcodeProjectExpoFonts"); +const withExpoFonts = (config, props) => { + config = (0, withAndroidExpoFonts_1.withAndroidExpoFonts)(config, props); + config = (0, withInfoPlistExpoFonts_1.withInfoPlistExpoFonts)(config, props); + config = (0, withXcodeProjectExpoFonts_1.withXcodeProjectExpoFonts)(config, props); + return config; +}; +const pak = require("../package.json"); +exports.default = (0, config_plugins_1.createRunOncePlugin)(withExpoFonts, pak.name, pak.version); //# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/build/index.js.map b/build/index.js.map index de2795a..4464602 100644 --- a/build/index.js.map +++ b/build/index.js.map @@ -1 +1 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;AAAA,iDAA0C;AAAjC,yHAAA,OAAO,OAAA","sourcesContent":["export { default } from \"./withExpoFonts\";\n"]} \ No newline at end of file +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;AAAA,yDAAyE;AAEzE,iEAA8D;AAC9D,qEAAkE;AAClE,2EAAwE;AAGxE,MAAM,aAAa,GAAmC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;IACtE,MAAM,GAAG,IAAA,2CAAoB,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC7C,MAAM,GAAG,IAAA,+CAAsB,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC/C,MAAM,GAAG,IAAA,qDAAyB,EAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAElD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AACvC,kBAAe,IAAA,oCAAmB,EAAC,aAAa,EAAE,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC","sourcesContent":["import { ConfigPlugin, createRunOncePlugin } from \"@expo/config-plugins\";\n\nimport { withAndroidExpoFonts } from \"./withAndroidExpoFonts\";\nimport { withInfoPlistExpoFonts } from \"./withInfoPlistExpoFonts\";\nimport { withXcodeProjectExpoFonts } from \"./withXcodeProjectExpoFonts\";\nimport { PluginConfigType } from \"./pluginConfigType\";\n\nconst withExpoFonts: ConfigPlugin = (config, props) => {\n config = withAndroidExpoFonts(config, props);\n config = withInfoPlistExpoFonts(config, props);\n config = withXcodeProjectExpoFonts(config, props);\n\n return config;\n};\n\nconst pak = require(\"../package.json\");\nexport default createRunOncePlugin(withExpoFonts, pak.name, pak.version);\n"]} \ No newline at end of file diff --git a/build/pluginConfigType.d.ts b/build/pluginConfigType.d.ts new file mode 100644 index 0000000..0dc7be7 --- /dev/null +++ b/build/pluginConfigType.d.ts @@ -0,0 +1,4 @@ +export interface PluginConfigType { + path: string; +} +//# sourceMappingURL=pluginConfigType.d.ts.map \ No newline at end of file diff --git a/build/pluginConfigType.d.ts.map b/build/pluginConfigType.d.ts.map new file mode 100644 index 0000000..9eba097 --- /dev/null +++ b/build/pluginConfigType.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"pluginConfigType.d.ts","sourceRoot":"","sources":["../src/pluginConfigType.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;CACd"} \ No newline at end of file diff --git a/build/pluginConfigType.js b/build/pluginConfigType.js new file mode 100644 index 0000000..16ddd87 --- /dev/null +++ b/build/pluginConfigType.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=pluginConfigType.js.map \ No newline at end of file diff --git a/build/pluginConfigType.js.map b/build/pluginConfigType.js.map new file mode 100644 index 0000000..1b60ffe --- /dev/null +++ b/build/pluginConfigType.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pluginConfigType.js","sourceRoot":"","sources":["../src/pluginConfigType.ts"],"names":[],"mappings":"","sourcesContent":["export interface PluginConfigType {\n path: string;\n}\n"]} \ No newline at end of file diff --git a/build/withAndroidExpoFonts.d.ts b/build/withAndroidExpoFonts.d.ts new file mode 100644 index 0000000..fde41ca --- /dev/null +++ b/build/withAndroidExpoFonts.d.ts @@ -0,0 +1,4 @@ +import { ConfigPlugin } from "@expo/config-plugins"; +import { PluginConfigType } from "./pluginConfigType"; +export declare const withAndroidExpoFonts: ConfigPlugin; +//# sourceMappingURL=withAndroidExpoFonts.d.ts.map \ No newline at end of file diff --git a/build/withAndroidExpoFonts.d.ts.map b/build/withAndroidExpoFonts.d.ts.map new file mode 100644 index 0000000..7db2fb4 --- /dev/null +++ b/build/withAndroidExpoFonts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withAndroidExpoFonts.d.ts","sourceRoot":"","sources":["../src/withAndroidExpoFonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAIpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,eAAO,MAAM,oBAAoB,EAAE,YAAY,CAAC,gBAAgB,CAyB/D,CAAC"} \ No newline at end of file diff --git a/build/withAndroidExpoFonts.js b/build/withAndroidExpoFonts.js new file mode 100644 index 0000000..6d947d9 --- /dev/null +++ b/build/withAndroidExpoFonts.js @@ -0,0 +1,25 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withAndroidExpoFonts = void 0; +const config_plugins_1 = require("@expo/config-plugins"); +const fs_1 = require("fs"); +const path_1 = require("path"); +const ANDROID_FONTS_PATHS = "android/app/src/main/assets/fonts"; +const withAndroidExpoFonts = (config, props) => { + return (0, config_plugins_1.withDangerousMod)(config, [ + "android", + (config) => { + const projectAndroidFontsPath = (0, path_1.resolve)(config.modRequest.projectRoot, ANDROID_FONTS_PATHS); + if (!(0, fs_1.existsSync)(projectAndroidFontsPath)) { + (0, fs_1.mkdirSync)(projectAndroidFontsPath, { recursive: true }); + } + const fontsFiles = (0, fs_1.readdirSync)(props.path); + fontsFiles.forEach((fontFile) => { + (0, fs_1.copyFileSync)(`${props.path}/${fontFile}`, `${projectAndroidFontsPath}/${fontFile}`); + }); + return config; + }, + ]); +}; +exports.withAndroidExpoFonts = withAndroidExpoFonts; +//# sourceMappingURL=withAndroidExpoFonts.js.map \ No newline at end of file diff --git a/build/withAndroidExpoFonts.js.map b/build/withAndroidExpoFonts.js.map new file mode 100644 index 0000000..9e67df8 --- /dev/null +++ b/build/withAndroidExpoFonts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"withAndroidExpoFonts.js","sourceRoot":"","sources":["../src/withAndroidExpoFonts.ts"],"names":[],"mappings":";;;AACA,yDAAwD;AACxD,2BAAsE;AACtE,+BAA+B;AAG/B,MAAM,mBAAmB,GAAG,mCAAmC,CAAC;AAEzD,MAAM,oBAAoB,GAAmC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;IACpF,OAAO,IAAA,iCAAgB,EAAC,MAAM,EAAE;QAC9B,SAAS;QACT,CAAC,MAAM,EAAE,EAAE;YACT,MAAM,uBAAuB,GAAG,IAAA,cAAO,EACrC,MAAM,CAAC,UAAU,CAAC,WAAW,EAC7B,mBAAmB,CACpB,CAAC;YAEF,IAAI,CAAC,IAAA,eAAU,EAAC,uBAAuB,CAAC,EAAE;gBACxC,IAAA,cAAS,EAAC,uBAAuB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;aACzD;YAED,MAAM,UAAU,GAAG,IAAA,gBAAW,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAE3C,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;gBAC9B,IAAA,iBAAY,EACV,GAAG,KAAK,CAAC,IAAI,IAAI,QAAQ,EAAE,EAC3B,GAAG,uBAAuB,IAAI,QAAQ,EAAE,CACzC,CAAC;YACJ,CAAC,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC;QAChB,CAAC;KACF,CAAC,CAAC;AACL,CAAC,CAAC;AAzBW,QAAA,oBAAoB,wBAyB/B","sourcesContent":["import { ConfigPlugin } from \"@expo/config-plugins\";\nimport { withDangerousMod } from \"@expo/config-plugins\";\nimport { copyFileSync, existsSync, mkdirSync, readdirSync } from \"fs\";\nimport { resolve } from \"path\";\nimport { PluginConfigType } from \"./pluginConfigType\";\n\nconst ANDROID_FONTS_PATHS = \"android/app/src/main/assets/fonts\";\n\nexport const withAndroidExpoFonts: ConfigPlugin = (config, props) => {\n return withDangerousMod(config, [\n \"android\",\n (config) => {\n const projectAndroidFontsPath = resolve(\n config.modRequest.projectRoot,\n ANDROID_FONTS_PATHS\n );\n\n if (!existsSync(projectAndroidFontsPath)) {\n mkdirSync(projectAndroidFontsPath, { recursive: true });\n }\n\n const fontsFiles = readdirSync(props.path);\n\n fontsFiles.forEach((fontFile) => {\n copyFileSync(\n `${props.path}/${fontFile}`,\n `${projectAndroidFontsPath}/${fontFile}`\n );\n });\n\n return config;\n },\n ]);\n};"]} \ No newline at end of file diff --git a/build/withInfoPlistExpoFonts.d.ts b/build/withInfoPlistExpoFonts.d.ts new file mode 100644 index 0000000..328fe2a --- /dev/null +++ b/build/withInfoPlistExpoFonts.d.ts @@ -0,0 +1,4 @@ +import { ConfigPlugin } from "expo/config-plugins"; +import { PluginConfigType } from "./pluginConfigType"; +export declare const withInfoPlistExpoFonts: ConfigPlugin; +//# sourceMappingURL=withInfoPlistExpoFonts.d.ts.map \ No newline at end of file diff --git a/build/withInfoPlistExpoFonts.d.ts.map b/build/withInfoPlistExpoFonts.d.ts.map new file mode 100644 index 0000000..67ca5b8 --- /dev/null +++ b/build/withInfoPlistExpoFonts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withInfoPlistExpoFonts.d.ts","sourceRoot":"","sources":["../src/withInfoPlistExpoFonts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAiB,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAWtD,eAAO,MAAM,sBAAsB,EAAE,YAAY,CAAC,gBAAgB,CA4BjE,CAAC"} \ No newline at end of file diff --git a/build/withInfoPlistExpoFonts.js b/build/withInfoPlistExpoFonts.js new file mode 100644 index 0000000..46dc791 --- /dev/null +++ b/build/withInfoPlistExpoFonts.js @@ -0,0 +1,33 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withInfoPlistExpoFonts = void 0; +const config_plugins_1 = require("expo/config-plugins"); +const fs_1 = require("fs"); +function ensureKey(arr, key) { + if (!arr.find((mode) => mode === key)) { + arr.push(key); + } + return arr; +} +const withInfoPlistExpoFonts = (config, props) => { + if (!props.path) + return config; + return (0, config_plugins_1.withInfoPlist)(config, (config) => { + if (!Array.isArray(config.modResults.UIAppFonts)) { + config.modResults.UIAppFonts = []; + } + const fontsFiles = (0, fs_1.readdirSync)(props.path); + fontsFiles.forEach((fontFile) => { + if (fontFile.endsWith(".ttf") || fontFile.endsWith(".otf")) { + config.modResults.UIAppFonts = ensureKey(config.modResults.UIAppFonts, fontFile); + } + }); + // Prevent empty array + if (!config.modResults.UIAppFonts.length) { + delete config.modResults.UIAppFonts; + } + return config; + }); +}; +exports.withInfoPlistExpoFonts = withInfoPlistExpoFonts; +//# sourceMappingURL=withInfoPlistExpoFonts.js.map \ No newline at end of file diff --git a/build/withInfoPlistExpoFonts.js.map b/build/withInfoPlistExpoFonts.js.map new file mode 100644 index 0000000..773633f --- /dev/null +++ b/build/withInfoPlistExpoFonts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"withInfoPlistExpoFonts.js","sourceRoot":"","sources":["../src/withInfoPlistExpoFonts.ts"],"names":[],"mappings":";;;AAAA,wDAAkE;AAGlE,2BAAiC;AAEjC,SAAS,SAAS,CAAC,GAAa,EAAE,GAAW;IAC3C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE;QACrC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;KACf;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAEM,MAAM,sBAAsB,GAAmC,CACpE,MAAM,EACN,KAAK,EACL,EAAE;IACF,IAAI,CAAC,KAAK,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC/B,OAAO,IAAA,8BAAa,EAAC,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;YAChD,MAAM,CAAC,UAAU,CAAC,UAAU,GAAG,EAAE,CAAC;SACnC;QAED,MAAM,UAAU,GAAG,IAAA,gBAAW,EAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAE3C,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;YAC9B,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;gBAC1D,MAAM,CAAC,UAAU,CAAC,UAAU,GAAG,SAAS,CACtC,MAAM,CAAC,UAAU,CAAC,UAAsB,EACxC,QAAQ,CACT,CAAC;aACH;QACH,CAAC,CAAC,CAAC;QAEH,sBAAsB;QACtB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE;YACxC,OAAO,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;SACrC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC;AA5BW,QAAA,sBAAsB,0BA4BjC","sourcesContent":["import { ConfigPlugin, withInfoPlist } from \"expo/config-plugins\";\nimport { PluginConfigType } from \"./pluginConfigType\";\n\nimport { readdirSync } from \"fs\";\n\nfunction ensureKey(arr: string[], key: string) {\n if (!arr.find((mode) => mode === key)) {\n arr.push(key);\n }\n return arr;\n}\n\nexport const withInfoPlistExpoFonts: ConfigPlugin = (\n config,\n props\n) => {\n if (!props.path) return config;\n return withInfoPlist(config, (config) => {\n if (!Array.isArray(config.modResults.UIAppFonts)) {\n config.modResults.UIAppFonts = [];\n }\n\n const fontsFiles = readdirSync(props.path);\n\n fontsFiles.forEach((fontFile) => {\n if (fontFile.endsWith(\".ttf\") || fontFile.endsWith(\".otf\")) {\n config.modResults.UIAppFonts = ensureKey(\n config.modResults.UIAppFonts as string[],\n fontFile\n );\n }\n });\n\n // Prevent empty array\n if (!config.modResults.UIAppFonts.length) {\n delete config.modResults.UIAppFonts;\n }\n\n return config;\n });\n};\n"]} \ No newline at end of file diff --git a/build/withXcodeProjectExpoFonts.d.ts b/build/withXcodeProjectExpoFonts.d.ts new file mode 100644 index 0000000..4f414ce --- /dev/null +++ b/build/withXcodeProjectExpoFonts.d.ts @@ -0,0 +1,4 @@ +import { ConfigPlugin } from "@expo/config-plugins"; +import { PluginConfigType } from "./pluginConfigType"; +export declare const withXcodeProjectExpoFonts: ConfigPlugin; +//# sourceMappingURL=withXcodeProjectExpoFonts.d.ts.map \ No newline at end of file diff --git a/build/withXcodeProjectExpoFonts.d.ts.map b/build/withXcodeProjectExpoFonts.d.ts.map new file mode 100644 index 0000000..46bf6e9 --- /dev/null +++ b/build/withXcodeProjectExpoFonts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"withXcodeProjectExpoFonts.d.ts","sourceRoot":"","sources":["../src/withXcodeProjectExpoFonts.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAGb,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAItD,eAAO,MAAM,yBAAyB,EAAE,YAAY,CAAC,gBAAgB,CA2EpE,CAAC"} \ No newline at end of file diff --git a/build/withXcodeProjectExpoFonts.js b/build/withXcodeProjectExpoFonts.js new file mode 100644 index 0000000..db01a36 --- /dev/null +++ b/build/withXcodeProjectExpoFonts.js @@ -0,0 +1,75 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.withXcodeProjectExpoFonts = void 0; +const config_plugins_1 = require("@expo/config-plugins"); +const fs_1 = require("fs"); +const path_1 = require("path"); +// @ts-ignore +const pbxFile_1 = __importDefault(require("xcode/lib/pbxFile")); +const withXcodeProjectExpoFonts = (config, props) => { + return (0, config_plugins_1.withXcodeProject)(config, async (config) => { + const groupPath = `.${props.path}`; + const group = config_plugins_1.IOSConfig.XcodeUtils.ensureGroupRecursively(config.modResults, groupPath); + const project = config.modResults; + const opt = {}; + // Unlink old assets + const groupId = Object.keys(project.hash.project.objects["PBXGroup"]).find((id) => { + const _group = project.hash.project.objects["PBXGroup"][id]; + return _group.name === group.name; + }); + if (!project.hash.project.objects["PBXVariantGroup"]) { + project.hash.project.objects["PBXVariantGroup"] = {}; + } + const variantGroupId = Object.keys(project.hash.project.objects["PBXVariantGroup"]).find((id) => { + const _group = project.hash.project.objects["PBXVariantGroup"][id]; + return _group.name === group.name; + }); + const children = [...(group.children || [])]; + for (const child of children) { + const file = new pbxFile_1.default((0, path_1.join)(group.name, child.comment), opt); + file.target = opt ? opt.target : undefined; + project.removeFromPbxBuildFileSection(file); // PBXBuildFile + project.removeFromPbxFileReferenceSection(file); // PBXFileReference + if (group) { + if (groupId) { + project.removeFromPbxGroup(file, groupId); //Group other than Resources (i.e. 'splash') + } + else if (variantGroupId) { + project.removeFromPbxVariantGroup(file, variantGroupId); // PBXVariantGroup + } + } + project.removeFromPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase + } + // Link new assets + await iterateFontsAsync(props, async (fontFile) => { + if (!group?.children.some(({ comment }) => comment === fontFile)) { + // Only write the file if it doesn't already exist. + config.modResults = config_plugins_1.IOSConfig.XcodeUtils.addResourceFileToGroup({ + filepath: (0, path_1.join)(groupPath, fontFile), + groupName: groupPath, + project: config.modResults, + isBuildFile: true, + verbose: true, + }); + } + else { + console.log("Skipping duplicate: ", fontFile); + } + }); + return config; + }); +}; +exports.withXcodeProjectExpoFonts = withXcodeProjectExpoFonts; +async function iterateFontsAsync(props, callback) { + const fontsFiles = (0, fs_1.readdirSync)(props.path); + for (let index = 0; index < fontsFiles.length; index++) { + const fontFile = fontsFiles[index]; + if (fontFile.endsWith(".ttf") || fontFile.endsWith(".otf")) { + await callback(fontFile, index); + } + } +} +//# sourceMappingURL=withXcodeProjectExpoFonts.js.map \ No newline at end of file diff --git a/build/withXcodeProjectExpoFonts.js.map b/build/withXcodeProjectExpoFonts.js.map new file mode 100644 index 0000000..d2c6799 --- /dev/null +++ b/build/withXcodeProjectExpoFonts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"withXcodeProjectExpoFonts.js","sourceRoot":"","sources":["../src/withXcodeProjectExpoFonts.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n ConfigPlugin,\n IOSConfig,\n withXcodeProject,\n} from \"@expo/config-plugins\";\nimport { readdirSync } from \"fs\";\nimport { join } from \"path\";\nimport { PluginConfigType } from \"./pluginConfigType\";\n// @ts-ignore\nimport pbxFile from \"xcode/lib/pbxFile\";\n\nexport const withXcodeProjectExpoFonts: ConfigPlugin = (\n config,\n props\n) => {\n return withXcodeProject(config, async (config) => {\n const groupPath = `.${props.path}`;\n const group = IOSConfig.XcodeUtils.ensureGroupRecursively(\n config.modResults,\n groupPath\n );\n const project = config.modResults;\n const opt: any = {};\n\n // Unlink old assets\n\n const groupId = Object.keys(project.hash.project.objects[\"PBXGroup\"]).find(\n (id) => {\n const _group = project.hash.project.objects[\"PBXGroup\"][id];\n return _group.name === group.name;\n }\n );\n if (!project.hash.project.objects[\"PBXVariantGroup\"]) {\n project.hash.project.objects[\"PBXVariantGroup\"] = {};\n }\n const variantGroupId = Object.keys(\n project.hash.project.objects[\"PBXVariantGroup\"]\n ).find((id) => {\n const _group = project.hash.project.objects[\"PBXVariantGroup\"][id];\n return _group.name === group.name;\n });\n\n const children = [...(group.children || [])];\n\n for (const child of children as {\n comment: string;\n value: string;\n }[]) {\n const file = new pbxFile(join(group.name, child.comment), opt);\n file.target = opt ? opt.target : undefined;\n\n project.removeFromPbxBuildFileSection(file); // PBXBuildFile\n project.removeFromPbxFileReferenceSection(file); // PBXFileReference\n if (group) {\n if (groupId) {\n project.removeFromPbxGroup(file, groupId); //Group other than Resources (i.e. 'splash')\n } else if (variantGroupId) {\n project.removeFromPbxVariantGroup(file, variantGroupId); // PBXVariantGroup\n }\n }\n project.removeFromPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase\n }\n\n // Link new assets\n\n await iterateFontsAsync(props, async (fontFile) => {\n if (\n !group?.children.some(\n ({ comment }: { comment: string }) => comment === fontFile\n )\n ) {\n // Only write the file if it doesn't already exist.\n config.modResults = IOSConfig.XcodeUtils.addResourceFileToGroup({\n filepath: join(groupPath, fontFile),\n groupName: groupPath,\n project: config.modResults,\n isBuildFile: true,\n verbose: true,\n });\n } else {\n console.log(\"Skipping duplicate: \", fontFile);\n }\n });\n\n return config;\n });\n};\n\nasync function iterateFontsAsync(\n props: PluginConfigType,\n callback: (fontFile: string, index: number) => Promise\n) {\n const fontsFiles = readdirSync(props.path);\n\n for (let index = 0; index < fontsFiles.length; index++) {\n const fontFile = fontsFiles[index];\n if (fontFile.endsWith(\".ttf\") || fontFile.endsWith(\".otf\")) {\n await callback(fontFile, index);\n }\n }\n}\n"]} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index e4d0121..08be057 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "with-expo-fonts", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "with-expo-fonts", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "devDependencies": { "@commitlint/cli": "^17.4.4", diff --git a/src/index.ts b/src/index.ts index 3052886..f184547 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1 +1,17 @@ -export { default } from "./withExpoFonts"; +import { ConfigPlugin, createRunOncePlugin } from "@expo/config-plugins"; + +import { withAndroidExpoFonts } from "./withAndroidExpoFonts"; +import { withInfoPlistExpoFonts } from "./withInfoPlistExpoFonts"; +import { withXcodeProjectExpoFonts } from "./withXcodeProjectExpoFonts"; +import { PluginConfigType } from "./pluginConfigType"; + +const withExpoFonts: ConfigPlugin = (config, props) => { + config = withAndroidExpoFonts(config, props); + config = withInfoPlistExpoFonts(config, props); + config = withXcodeProjectExpoFonts(config, props); + + return config; +}; + +const pak = require("../package.json"); +export default createRunOncePlugin(withExpoFonts, pak.name, pak.version); diff --git a/src/pluginConfigType.ts b/src/pluginConfigType.ts new file mode 100644 index 0000000..6525aa4 --- /dev/null +++ b/src/pluginConfigType.ts @@ -0,0 +1,3 @@ +export interface PluginConfigType { + path: string; +} diff --git a/src/withAndroidExpoFonts.ts b/src/withAndroidExpoFonts.ts new file mode 100644 index 0000000..0ef386f --- /dev/null +++ b/src/withAndroidExpoFonts.ts @@ -0,0 +1,34 @@ +import { ConfigPlugin } from "@expo/config-plugins"; +import { withDangerousMod } from "@expo/config-plugins"; +import { copyFileSync, existsSync, mkdirSync, readdirSync } from "fs"; +import { resolve } from "path"; +import { PluginConfigType } from "./pluginConfigType"; + +const ANDROID_FONTS_PATHS = "android/app/src/main/assets/fonts"; + +export const withAndroidExpoFonts: ConfigPlugin = (config, props) => { + return withDangerousMod(config, [ + "android", + (config) => { + const projectAndroidFontsPath = resolve( + config.modRequest.projectRoot, + ANDROID_FONTS_PATHS + ); + + if (!existsSync(projectAndroidFontsPath)) { + mkdirSync(projectAndroidFontsPath, { recursive: true }); + } + + const fontsFiles = readdirSync(props.path); + + fontsFiles.forEach((fontFile) => { + copyFileSync( + `${props.path}/${fontFile}`, + `${projectAndroidFontsPath}/${fontFile}` + ); + }); + + return config; + }, + ]); +}; \ No newline at end of file diff --git a/src/withExpoFonts.ts b/src/withExpoFonts.ts deleted file mode 100644 index 99cce2b..0000000 --- a/src/withExpoFonts.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { ConfigPlugin } from "@expo/config-plugins"; -import { withDangerousMod } from "@expo/config-plugins"; -import { copyFileSync, existsSync, mkdirSync, readdirSync } from "node:fs"; -import { resolve } from "node:path"; - -const ANDROID_FONTS_PATHS = "android/app/src/main/assets/fonts"; -const PROJECT_FONTS_PATH = "assets/fonts"; - -const withExpoFonts: ConfigPlugin = (config) => { - return withDangerousMod(config, [ - "android", - (config) => { - const projectAndroidFontsPath = resolve( - config.modRequest.projectRoot, - ANDROID_FONTS_PATHS, - ); - - if (!existsSync(projectAndroidFontsPath)) { - mkdirSync(projectAndroidFontsPath, { recursive: true }); - } - - const fontsFiles = readdirSync(PROJECT_FONTS_PATH); - - fontsFiles.forEach((fontFile) => { - copyFileSync( - `${PROJECT_FONTS_PATH}/${fontFile}`, - `${projectAndroidFontsPath}/${fontFile}`, - ); - }); - - return config; - }, - ]); -}; - -export default withExpoFonts; diff --git a/src/withInfoPlistExpoFonts.ts b/src/withInfoPlistExpoFonts.ts new file mode 100644 index 0000000..b6f7aec --- /dev/null +++ b/src/withInfoPlistExpoFonts.ts @@ -0,0 +1,41 @@ +import { ConfigPlugin, withInfoPlist } from "expo/config-plugins"; +import { PluginConfigType } from "./pluginConfigType"; + +import { readdirSync } from "fs"; + +function ensureKey(arr: string[], key: string) { + if (!arr.find((mode) => mode === key)) { + arr.push(key); + } + return arr; +} + +export const withInfoPlistExpoFonts: ConfigPlugin = ( + config, + props +) => { + if (!props.path) return config; + return withInfoPlist(config, (config) => { + if (!Array.isArray(config.modResults.UIAppFonts)) { + config.modResults.UIAppFonts = []; + } + + const fontsFiles = readdirSync(props.path); + + fontsFiles.forEach((fontFile) => { + if (fontFile.endsWith(".ttf") || fontFile.endsWith(".otf")) { + config.modResults.UIAppFonts = ensureKey( + config.modResults.UIAppFonts as string[], + fontFile + ); + } + }); + + // Prevent empty array + if (!config.modResults.UIAppFonts.length) { + delete config.modResults.UIAppFonts; + } + + return config; + }); +}; diff --git a/src/withXcodeProjectExpoFonts.ts b/src/withXcodeProjectExpoFonts.ts new file mode 100644 index 0000000..0be1ae8 --- /dev/null +++ b/src/withXcodeProjectExpoFonts.ts @@ -0,0 +1,101 @@ +import { + ConfigPlugin, + IOSConfig, + withXcodeProject, +} from "@expo/config-plugins"; +import { readdirSync } from "fs"; +import { join } from "path"; +import { PluginConfigType } from "./pluginConfigType"; +// @ts-ignore +import pbxFile from "xcode/lib/pbxFile"; + +export const withXcodeProjectExpoFonts: ConfigPlugin = ( + config, + props +) => { + return withXcodeProject(config, async (config) => { + const groupPath = `.${props.path}`; + const group = IOSConfig.XcodeUtils.ensureGroupRecursively( + config.modResults, + groupPath + ); + const project = config.modResults; + const opt: any = {}; + + // Unlink old assets + + const groupId = Object.keys(project.hash.project.objects["PBXGroup"]).find( + (id) => { + const _group = project.hash.project.objects["PBXGroup"][id]; + return _group.name === group.name; + } + ); + if (!project.hash.project.objects["PBXVariantGroup"]) { + project.hash.project.objects["PBXVariantGroup"] = {}; + } + const variantGroupId = Object.keys( + project.hash.project.objects["PBXVariantGroup"] + ).find((id) => { + const _group = project.hash.project.objects["PBXVariantGroup"][id]; + return _group.name === group.name; + }); + + const children = [...(group.children || [])]; + + for (const child of children as { + comment: string; + value: string; + }[]) { + const file = new pbxFile(join(group.name, child.comment), opt); + file.target = opt ? opt.target : undefined; + + project.removeFromPbxBuildFileSection(file); // PBXBuildFile + project.removeFromPbxFileReferenceSection(file); // PBXFileReference + if (group) { + if (groupId) { + project.removeFromPbxGroup(file, groupId); //Group other than Resources (i.e. 'splash') + } else if (variantGroupId) { + project.removeFromPbxVariantGroup(file, variantGroupId); // PBXVariantGroup + } + } + project.removeFromPbxResourcesBuildPhase(file); // PBXResourcesBuildPhase + } + + // Link new assets + + await iterateFontsAsync(props, async (fontFile) => { + if ( + !group?.children.some( + ({ comment }: { comment: string }) => comment === fontFile + ) + ) { + // Only write the file if it doesn't already exist. + config.modResults = IOSConfig.XcodeUtils.addResourceFileToGroup({ + filepath: join(groupPath, fontFile), + groupName: groupPath, + project: config.modResults, + isBuildFile: true, + verbose: true, + }); + } else { + console.log("Skipping duplicate: ", fontFile); + } + }); + + return config; + }); +}; + +async function iterateFontsAsync( + props: PluginConfigType, + callback: (fontFile: string, index: number) => Promise +) { + const fontsFiles = readdirSync(props.path); + + for (let index = 0; index < fontsFiles.length; index++) { + const fontFile = fontsFiles[index]; + if (fontFile.endsWith(".ttf") || fontFile.endsWith(".otf")) { + await callback(fontFile, index); + } + } +}