@vanenshi/expo-plugins 0.1.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amir Shekari
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,143 @@
1
+ # @vanenshi/expo-plugins
2
+
3
+ A small collection of [Expo config plugins](https://docs.expo.dev/config-plugins/introduction/).
4
+
5
+ ## Install
6
+
7
+ ```sh
8
+ npx expo install @vanenshi/expo-plugins
9
+ ```
10
+
11
+ ---
12
+
13
+ ## `withDisplayName`
14
+
15
+ **Goal:** Give each build variant (dev / beta / prod) its own home-screen
16
+ display name on both iOS and Android — without touching the internal root `name`
17
+ (which drives bundle structure and forces slow clean rebuilds when changed).
18
+
19
+ **Underneath:**
20
+ - **iOS** — sets `CFBundleDisplayName` in `Info.plist` via `withInfoPlist`.
21
+ - **Android** — sets `app_name` in `strings.xml` via `withStringsXml`.
22
+
23
+ ```ts
24
+ // app.config.ts
25
+ export default {
26
+ name: "MyApp", // internal project name — unchanged
27
+ plugins: [
28
+ ["@vanenshi/expo-plugins/display-name", { displayName: "MyApp (Beta)" }],
29
+ ],
30
+ };
31
+ ```
32
+
33
+ ### Options
34
+
35
+ | Option | Type | Description |
36
+ | ------------- | -------- | -------------------------------------------------- |
37
+ | `displayName` | `string` | Name shown to users on the home screen (required). |
38
+
39
+ ---
40
+
41
+ ## `withExpoGoogleFonts`
42
+
43
+ **Goal:** Embed `@expo-google-fonts/*` faces into the native projects without
44
+ manually listing every font path in your app config. The plugin reads the
45
+ weight/style folder layout from your installed packages, resolves the `.ttf`
46
+ file paths, and delegates to `expo-font` — so you only declare _which_ font
47
+ families and weights you want.
48
+
49
+ **Underneath:**
50
+ - **Discovery** — walks `@expo-google-fonts/<name>` package folders, parses
51
+ folder names like `400Regular` / `700Bold_Italic`, and collects `.ttf` paths.
52
+ - **Delegation** — passes the resolved font manifest to `expo-font/app.plugin`
53
+ (`withFonts`), which handles embedding into both Android assets and iOS
54
+ `Info.plist`.
55
+
56
+ ```sh
57
+ npx expo install expo-font @expo-google-fonts/roboto @expo-google-fonts/inter
58
+ ```
59
+
60
+ ```json
61
+ {
62
+ "plugins": [
63
+ [
64
+ "@vanenshi/expo-plugins/google-fonts",
65
+ {
66
+ "fonts": [
67
+ { "packageName": "roboto", "weights": [400, 500, 700], "importItalic": true },
68
+ { "packageName": "inter", "weights": [400, 600] }
69
+ ]
70
+ }
71
+ ]
72
+ ]
73
+ }
74
+ ```
75
+
76
+ No separate `["expo-font", ...]` entry is needed.
77
+
78
+ > Need the raw `expo-font` options (e.g. to merge with local fonts)? Import
79
+ > `buildExpoGoogleFontsOptions(input)` and pass the result to
80
+ > `["expo-font", options]` yourself.
81
+
82
+ ### Options
83
+
84
+ | Option | Type | Default | Description |
85
+ | --------------- | ------------------ | --------------- | ------------------------------------------------------ |
86
+ | `fonts` | `GoogleFontSpec[]` | — | Fonts to embed (see below). |
87
+ | `projectRoot` | `string` | `process.cwd()` | Where to resolve `@expo-google-fonts/*` packages from. |
88
+ | `warnOnMissing` | `boolean` | `true` | Warn when a package, weight, or `.ttf` is missing. |
89
+
90
+ `GoogleFontSpec`: `{ packageName, fontFamily?, weights?, importItalic? }` —
91
+ `weights` defaults to `[400]`, `fontFamily` defaults to the package's metadata
92
+ family name.
93
+
94
+ ---
95
+
96
+ ## Development
97
+
98
+ This package uses [`expo-module-scripts`](https://github.com/expo/expo/tree/main/packages/expo-module-scripts) and follows [`expo/config-plugins`](https://github.com/expo/config-plugins) conventions.
99
+
100
+ ```sh
101
+ pnpm install
102
+ pnpm run build # compile src/ → build/
103
+ pnpm run lint
104
+ pnpm test
105
+ ```
106
+
107
+ ### Example app
108
+
109
+ `apps/app` is a minimal Expo app wiring both plugins, used to verify plugins
110
+ work end-to-end via `expo prebuild`:
111
+
112
+ ```sh
113
+ cd apps/app
114
+ npm install
115
+ npx expo prebuild --clean
116
+ grep "Example (Beta)" android/app/src/main/res/values/strings.xml
117
+ grep "CFBundleDisplayName" ios/*/Info.plist
118
+ ```
119
+
120
+ See [`apps/app/README.md`](apps/app/README.md) for details.
121
+
122
+ ### Publishing
123
+
124
+ CI publishes to npm on every **GitHub Release** ([`.github/workflows/publish.yml`](.github/workflows/publish.yml)).
125
+ Add an `NPM_TOKEN` repo secret (npm Automation token), then:
126
+
127
+ ```sh
128
+ pnpm version <patch|minor|major>
129
+ git push --follow-tags
130
+ # create a GitHub Release from the new tag — CI builds, tests, and publishes
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Architecture decisions
136
+
137
+ See [`docs/adr/`](docs/adr/) for the recorded decisions behind this package's design:
138
+ package structure ([ADR-0001](docs/adr/0001-single-package.md)),
139
+ toolchain ([ADR-0002](docs/adr/0002-expo-module-scripts.md)),
140
+ logging ([ADR-0003](docs/adr/0003-warning-aggregator-logger.md)),
141
+ font discovery ([ADR-0004](docs/adr/0004-google-fonts-auto-discovery.md)),
142
+ folder-per-plugin layout ([ADR-0005](docs/adr/0005-folder-per-plugin-layout.md)),
143
+ and cross-platform display name ([ADR-0006](docs/adr/0006-cross-platform-display-name.md)).
@@ -0,0 +1,11 @@
1
+ import { ConfigPlugin } from "expo/config-plugins";
2
+ export interface DisplayNameProps {
3
+ /**
4
+ * Display name shown to users on the home screen. Applied to
5
+ * `CFBundleDisplayName` (iOS) and `app_name` in `strings.xml` (Android).
6
+ * When omitted the plugin is a no-op.
7
+ */
8
+ displayName?: string;
9
+ }
10
+ declare const _default: ConfigPlugin<void | DisplayNameProps>;
11
+ export default _default;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const config_plugins_1 = require("expo/config-plugins");
4
+ const logger_1 = require("../utils/logger");
5
+ const logger = (0, logger_1.createLogger)("@vanenshi/expo-plugins/display-name");
6
+ const pkg = require("../../package.json");
7
+ /**
8
+ * Sets a custom display name on both iOS and Android without touching the root
9
+ * `name` (which drives bundle structure and internal module naming). Lets you
10
+ * give each build variant (dev, beta, prod) its own user-facing name while
11
+ * keeping internal naming consistent.
12
+ *
13
+ * Underneath:
14
+ * - iOS: sets `CFBundleDisplayName` in `Info.plist` via `withInfoPlist`.
15
+ * - Android: sets `app_name` in `strings.xml` via `withStringsXml`.
16
+ *
17
+ * @example
18
+ * // app.config.ts
19
+ * plugins: [["@vanenshi/expo-plugins/display-name", { displayName: "My App (Beta)" }]]
20
+ */
21
+ const withDisplayName = (config, props) => {
22
+ const displayName = props?.displayName;
23
+ if (!displayName)
24
+ return config;
25
+ // Android
26
+ config = (0, config_plugins_1.withStringsXml)(config, (modConfig) => {
27
+ if (modConfig.name) {
28
+ logger.warnAndroid(`displayName is set — ignoring abstract "name": ${modConfig.name}`);
29
+ }
30
+ const strings = modConfig.modResults.resources.string ?? [];
31
+ const entry = strings.find((item) => item.$.name === "app_name");
32
+ if (entry) {
33
+ entry._ = displayName;
34
+ }
35
+ else {
36
+ strings.push({ $: { name: "app_name" }, _: displayName });
37
+ modConfig.modResults.resources.string = strings;
38
+ }
39
+ return modConfig;
40
+ });
41
+ // iOS
42
+ config = (0, config_plugins_1.withInfoPlist)(config, (modConfig) => {
43
+ if (modConfig.name) {
44
+ logger.warnIOS(`displayName is set — ignoring abstract "name": ${modConfig.name}`);
45
+ }
46
+ modConfig.modResults.CFBundleDisplayName = displayName;
47
+ return modConfig;
48
+ });
49
+ return config;
50
+ };
51
+ exports.default = (0, config_plugins_1.createRunOncePlugin)(withDisplayName, "@vanenshi/expo-plugins/display-name", pkg.version);
@@ -0,0 +1,34 @@
1
+ type FontStyle = "normal" | "italic";
2
+ export interface FontFace {
3
+ path: string;
4
+ absPath: string;
5
+ weight: number;
6
+ style: FontStyle;
7
+ }
8
+ export interface DiscoveredPackage {
9
+ fontFamily: string;
10
+ faces: Map<string, FontFace>;
11
+ }
12
+ export declare const TTF_REQUIRE_RE: RegExp;
13
+ export declare const FOLDER_TO_WEIGHT: Record<string, number>;
14
+ export declare function parseFolder(folder: string): {
15
+ weight: number;
16
+ style: FontStyle;
17
+ } | null;
18
+ /**
19
+ * Parses an already-resolved `@expo-google-fonts/*` package directory.
20
+ * Pure: no `require.resolve`, no network. Suitable for unit testing with a
21
+ * committed fixture directory.
22
+ */
23
+ export declare function parsePackage(pkgDir: string, packageName: string): DiscoveredPackage | null;
24
+ /**
25
+ * Resolves the `@expo-google-fonts/<packageName>` package directory via
26
+ * `require.resolve`. This is the only side-effectful seam; keep it thin.
27
+ */
28
+ export declare function resolvePackageDir(packageName: string, projectRoot: string): string | null;
29
+ /**
30
+ * Discovers a Google Fonts package: resolves it then parses its contents.
31
+ * Emits a warning and returns null when the package is missing or malformed.
32
+ */
33
+ export declare function discoverPackage(packageName: string, projectRoot: string, warnOnMissing: boolean): DiscoveredPackage | null;
34
+ export {};
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.FOLDER_TO_WEIGHT = exports.TTF_REQUIRE_RE = void 0;
7
+ exports.parseFolder = parseFolder;
8
+ exports.parsePackage = parsePackage;
9
+ exports.resolvePackageDir = resolvePackageDir;
10
+ exports.discoverPackage = discoverPackage;
11
+ const node_fs_1 = __importDefault(require("node:fs"));
12
+ const node_path_1 = __importDefault(require("node:path"));
13
+ const logger_1 = require("../utils/logger");
14
+ const logger = (0, logger_1.createLogger)("@vanenshi/expo-plugins/google-fonts");
15
+ exports.TTF_REQUIRE_RE = /require\(['"]\.\/([^'"]+\.ttf)['"]\)/g;
16
+ exports.FOLDER_TO_WEIGHT = {
17
+ "100Thin": 100,
18
+ "200ExtraLight": 200,
19
+ "300Light": 300,
20
+ "400Regular": 400,
21
+ "500Medium": 500,
22
+ "600SemiBold": 600,
23
+ "700Bold": 700,
24
+ "800ExtraBold": 800,
25
+ "900Black": 900,
26
+ };
27
+ function parseFolder(folder) {
28
+ const italic = folder.endsWith("_Italic");
29
+ const base = italic ? folder.slice(0, -"_Italic".length) : folder;
30
+ if (!(base in exports.FOLDER_TO_WEIGHT))
31
+ return null;
32
+ const weight = exports.FOLDER_TO_WEIGHT[base] ?? 400;
33
+ return { weight, style: italic ? "italic" : "normal" };
34
+ }
35
+ /**
36
+ * Parses an already-resolved `@expo-google-fonts/*` package directory.
37
+ * Pure: no `require.resolve`, no network. Suitable for unit testing with a
38
+ * committed fixture directory.
39
+ */
40
+ function parsePackage(pkgDir, packageName) {
41
+ const metadataPath = node_path_1.default.join(pkgDir, "metadata.json");
42
+ const indexPath = node_path_1.default.join(pkgDir, "index.js");
43
+ if (!node_fs_1.default.existsSync(metadataPath) || !node_fs_1.default.existsSync(indexPath)) {
44
+ logger.warn(`@expo-google-fonts/${packageName} is missing metadata.json or index.js.`);
45
+ return null;
46
+ }
47
+ const { family } = JSON.parse(node_fs_1.default.readFileSync(metadataPath, "utf8"));
48
+ const faces = new Map();
49
+ for (const match of node_fs_1.default
50
+ .readFileSync(indexPath, "utf8")
51
+ .matchAll(exports.TTF_REQUIRE_RE)) {
52
+ const relPath = match[1];
53
+ const parsed = parseFolder(node_path_1.default.dirname(relPath));
54
+ if (!parsed)
55
+ continue;
56
+ faces.set(`${parsed.weight}:${parsed.style}`, {
57
+ ...parsed,
58
+ path: `./node_modules/@expo-google-fonts/${packageName}/${relPath}`,
59
+ absPath: node_path_1.default.join(pkgDir, relPath),
60
+ });
61
+ }
62
+ return { fontFamily: family, faces };
63
+ }
64
+ /**
65
+ * Resolves the `@expo-google-fonts/<packageName>` package directory via
66
+ * `require.resolve`. This is the only side-effectful seam; keep it thin.
67
+ */
68
+ function resolvePackageDir(packageName, projectRoot) {
69
+ try {
70
+ return node_path_1.default.dirname(require.resolve(`@expo-google-fonts/${packageName}/package.json`, {
71
+ paths: [projectRoot],
72
+ }));
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ }
78
+ /**
79
+ * Discovers a Google Fonts package: resolves it then parses its contents.
80
+ * Emits a warning and returns null when the package is missing or malformed.
81
+ */
82
+ function discoverPackage(packageName, projectRoot, warnOnMissing) {
83
+ const pkgDir = resolvePackageDir(packageName, projectRoot);
84
+ if (!pkgDir) {
85
+ if (warnOnMissing) {
86
+ logger.warn(`@expo-google-fonts/${packageName} is not installed — run: npx expo install @expo-google-fonts/${packageName}`);
87
+ }
88
+ return null;
89
+ }
90
+ return parsePackage(pkgDir, packageName);
91
+ }
@@ -0,0 +1,43 @@
1
+ import { ConfigPlugin } from "expo/config-plugins";
2
+ export interface GoogleFontSpec {
3
+ packageName: string;
4
+ /** `fontFamily` style prop value — defaults to `metadata.json` family (e.g. `"Roboto"`). */
5
+ fontFamily?: string;
6
+ weights?: number[];
7
+ importItalic?: boolean;
8
+ }
9
+ export interface BuildExpoFontPluginOptionsInput {
10
+ fonts: GoogleFontSpec[];
11
+ projectRoot?: string;
12
+ warnOnMissing?: boolean;
13
+ }
14
+ interface ExpoFontPluginOptions {
15
+ android: {
16
+ fonts: {
17
+ fontFamily: string;
18
+ fontDefinitions: {
19
+ path: string;
20
+ weight: number;
21
+ style?: "italic";
22
+ }[];
23
+ }[];
24
+ };
25
+ ios: {
26
+ fonts: string[];
27
+ };
28
+ }
29
+ /**
30
+ * Builds the `expo-font` plugin options from installed `@expo-google-fonts/*`
31
+ * packages — Android uses `fontFamily` + weight/style, iOS embeds the resolved
32
+ * file paths. Use this directly only if you want to pass the options to
33
+ * `expo-font` yourself; most projects should use the {@link withExpoGoogleFonts}
34
+ * config plugin instead.
35
+ */
36
+ export declare function buildExpoGoogleFontsOptions({ fonts, projectRoot, warnOnMissing, }: BuildExpoFontPluginOptionsInput): ExpoFontPluginOptions;
37
+ export interface ExpoGoogleFontsProps {
38
+ fonts?: GoogleFontSpec[];
39
+ projectRoot?: string;
40
+ warnOnMissing?: boolean;
41
+ }
42
+ declare const _default: ConfigPlugin<ExpoGoogleFontsProps>;
43
+ export default _default;
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildExpoGoogleFontsOptions = buildExpoGoogleFontsOptions;
7
+ const config_plugins_1 = require("expo/config-plugins");
8
+ const node_fs_1 = __importDefault(require("node:fs"));
9
+ const discovery_1 = require("./discovery");
10
+ const logger_1 = require("../utils/logger");
11
+ const logger = (0, logger_1.createLogger)("@vanenshi/expo-plugins/google-fonts");
12
+ const pkg = require("../../package.json");
13
+ /**
14
+ * Builds the `expo-font` plugin options from installed `@expo-google-fonts/*`
15
+ * packages — Android uses `fontFamily` + weight/style, iOS embeds the resolved
16
+ * file paths. Use this directly only if you want to pass the options to
17
+ * `expo-font` yourself; most projects should use the {@link withExpoGoogleFonts}
18
+ * config plugin instead.
19
+ */
20
+ function buildExpoGoogleFontsOptions({ fonts, projectRoot = process.cwd(), warnOnMissing = true, }) {
21
+ const androidFonts = [];
22
+ const iosFonts = [];
23
+ for (const spec of fonts) {
24
+ const pkg = (0, discovery_1.discoverPackage)(spec.packageName, projectRoot, warnOnMissing);
25
+ if (!pkg)
26
+ continue;
27
+ const fontFamily = spec.fontFamily ?? pkg.fontFamily;
28
+ const weights = spec.weights ?? [400];
29
+ const wanted = weights.map((weight) => ({
30
+ weight,
31
+ style: "normal",
32
+ }));
33
+ if (spec.importItalic) {
34
+ wanted.push(...weights.map((weight) => ({ weight, style: "italic" })));
35
+ }
36
+ const fontDefinitions = [];
37
+ for (const { weight, style } of wanted) {
38
+ const face = pkg.faces.get(`${weight}:${style}`);
39
+ if (!face) {
40
+ if (warnOnMissing) {
41
+ logger.warn(`${fontFamily} weight ${weight}${style === "italic" ? " italic" : ""} not found in @expo-google-fonts/${spec.packageName}.`);
42
+ }
43
+ continue;
44
+ }
45
+ if (!node_fs_1.default.existsSync(face.absPath)) {
46
+ if (warnOnMissing) {
47
+ logger.warn(`${fontFamily} file missing: ${face.absPath}`);
48
+ }
49
+ continue;
50
+ }
51
+ fontDefinitions.push({
52
+ path: face.path,
53
+ weight: face.weight,
54
+ ...(face.style === "italic" ? { style: "italic" } : {}),
55
+ });
56
+ }
57
+ if (fontDefinitions.length === 0) {
58
+ if (warnOnMissing) {
59
+ logger.warn(`No faces embedded for ${fontFamily} (@expo-google-fonts/${spec.packageName}).`);
60
+ }
61
+ continue;
62
+ }
63
+ androidFonts.push({ fontFamily, fontDefinitions });
64
+ iosFonts.push(...fontDefinitions.map((def) => def.path));
65
+ }
66
+ return { android: { fonts: androidFonts }, ios: { fonts: iosFonts } };
67
+ }
68
+ /**
69
+ * Config plugin that embeds `@expo-google-fonts/*` faces into the native
70
+ * projects. Resolves the requested weights/styles and delegates to `expo-font`,
71
+ * so you don't need a separate `["expo-font", ...]` entry.
72
+ *
73
+ * @example
74
+ * // app.config.ts
75
+ * plugins: [
76
+ * [
77
+ * "@vanenshi/expo-plugins/google-fonts",
78
+ * { fonts: [{ packageName: "roboto", weights: [400, 700], importItalic: true }] },
79
+ * ],
80
+ * ]
81
+ */
82
+ const withExpoGoogleFonts = (config, props) => {
83
+ if (!props?.fonts?.length)
84
+ return config;
85
+ const options = buildExpoGoogleFontsOptions(props);
86
+ const withFonts = require("expo-font/app.plugin").default;
87
+ return withFonts(config, options);
88
+ };
89
+ exports.default = (0, config_plugins_1.createRunOncePlugin)(withExpoGoogleFonts, "@vanenshi/expo-plugins/google-fonts", pkg.version);
@@ -0,0 +1,4 @@
1
+ export { default as withDisplayName } from "./display-name";
2
+ export type { DisplayNameProps } from "./display-name";
3
+ export { default as withExpoGoogleFonts, buildExpoGoogleFontsOptions, } from "./google-fonts";
4
+ export type { GoogleFontSpec, BuildExpoFontPluginOptionsInput, ExpoGoogleFontsProps, } from "./google-fonts";
package/build/index.js ADDED
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.buildExpoGoogleFontsOptions = exports.withExpoGoogleFonts = exports.withDisplayName = void 0;
7
+ var display_name_1 = require("./display-name");
8
+ Object.defineProperty(exports, "withDisplayName", { enumerable: true, get: function () { return __importDefault(display_name_1).default; } });
9
+ var google_fonts_1 = require("./google-fonts");
10
+ Object.defineProperty(exports, "withExpoGoogleFonts", { enumerable: true, get: function () { return __importDefault(google_fonts_1).default; } });
11
+ Object.defineProperty(exports, "buildExpoGoogleFontsOptions", { enumerable: true, get: function () { return google_fonts_1.buildExpoGoogleFontsOptions; } });
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Scoped logger for Expo config plugins.
3
+ */
4
+ export declare function createLogger(scope: string): {
5
+ warnAndroid(text: string): void;
6
+ warnIOS(text: string): void;
7
+ warn(text: string): void;
8
+ };
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createLogger = createLogger;
4
+ const warned = new Set();
5
+ const bold = (text) => `\x1b[1m${text}\x1b[22m`;
6
+ const yellow = (text) => `\x1b[33m${text}\x1b[39m`;
7
+ /**
8
+ * Scoped logger for Expo config plugins.
9
+ */
10
+ function createLogger(scope) {
11
+ return {
12
+ warnAndroid(text) {
13
+ const warning = formatWarning({
14
+ platform: "android",
15
+ scope,
16
+ warning: text,
17
+ });
18
+ if (warned.has(warning))
19
+ return;
20
+ warned.add(warning);
21
+ console.warn(warning);
22
+ },
23
+ warnIOS(text) {
24
+ const warning = formatWarning({
25
+ platform: "ios",
26
+ scope,
27
+ warning: text,
28
+ });
29
+ if (warned.has(warning))
30
+ return;
31
+ warned.add(warning);
32
+ console.warn(warning);
33
+ },
34
+ warn(text) {
35
+ const warning = formatWarning({ warning: text });
36
+ if (warned.has(warning))
37
+ return;
38
+ warned.add(warning);
39
+ console.warn(formatWarning({ warning: text }));
40
+ },
41
+ };
42
+ }
43
+ /**
44
+ * » @expo-google-fonts/inter is not installed — run: npx expo install @expo-google-fonts/inter
45
+ * » @vanenshi/expo-plugins/display-name[android]: displayName is set — ignoring abstract "name": example-internal
46
+ * » @vanenshi/expo-plugins/display-name[ios]: displayName is set — ignoring abstract "name": example-internal
47
+ */
48
+ function formatWarning({ platform, scope, warning, }) {
49
+ let prefix = "» ";
50
+ if (scope && platform) {
51
+ prefix += bold(`${scope}[${bold(platform)}]: `);
52
+ }
53
+ else if (scope) {
54
+ prefix += bold(`${scope}: `);
55
+ }
56
+ else if (platform) {
57
+ prefix += bold(`${platform}: `);
58
+ }
59
+ return yellow(`${prefix}${warning}`);
60
+ }
@@ -0,0 +1,2 @@
1
+ // Entry stub for "@vanenshi/expo-plugins/display-name"
2
+ module.exports = require("./build/display-name").default;
@@ -0,0 +1,3 @@
1
+ // Plugin entry so `app.json` can reference
2
+ // "@vanenshi/expo-plugins/google-fonts".
3
+ module.exports = require("./build/google-fonts").default;
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@vanenshi/expo-plugins",
3
+ "version": "0.1.1",
4
+ "description": "A small collection of Expo config plugins.",
5
+ "license": "MIT",
6
+ "main": "build/index.js",
7
+ "types": "build/index.d.ts",
8
+ "sideEffects": false,
9
+ "files": [
10
+ "build",
11
+ "display-name.js",
12
+ "google-fonts.js"
13
+ ],
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "https://github.com/vanenshi/expo-plugins.git"
17
+ },
18
+ "keywords": [
19
+ "react",
20
+ "react-native",
21
+ "expo",
22
+ "config-plugin",
23
+ "expo-plugins"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "devDependencies": {
29
+ "@expo/config-types": "^56.0.0",
30
+ "eslint": "^9.39.4",
31
+ "expo-module-scripts": "^56.0.3",
32
+ "jest": "^29.7.0"
33
+ },
34
+ "peerDependencies": {
35
+ "expo": "*",
36
+ "expo-font": "*"
37
+ },
38
+ "peerDependenciesMeta": {
39
+ "expo-font": {
40
+ "optional": true
41
+ }
42
+ },
43
+ "scripts": {
44
+ "build": "pnpm clean && expo-module build",
45
+ "clean": "expo-module clean && pnpm clean:example",
46
+ "clean:example": "rm -rf example/node_modules/@vanenshi",
47
+ "lint": "expo-module lint",
48
+ "test": "expo-module test",
49
+ "expo-module": "expo-module"
50
+ }
51
+ }