@capgo/capacitor-inappbrowser 8.14.2 → 8.15.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/dist/docs.json CHANGED
@@ -999,9 +999,13 @@
999
999
  {
1000
1000
  "text": "0.1.0",
1001
1001
  "name": "since"
1002
+ },
1003
+ {
1004
+ "text": "\"https://capgo.app\"",
1005
+ "name": "example"
1002
1006
  }
1003
1007
  ],
1004
- "docs": "Target URL to load.",
1008
+ "docs": "Target URL to load.\n\nRemote `http://` and `https://` URLs are loaded as-is. Relative bundled paths\nsuch as `/index.html` are not supported; use `openWebView()` instead.",
1005
1009
  "complexTypes": [],
1006
1010
  "type": "string"
1007
1011
  },
@@ -1403,12 +1407,20 @@
1403
1407
  "text": "0.1.0",
1404
1408
  "name": "since"
1405
1409
  },
1410
+ {
1411
+ "text": "8.15.0 Relative bundled paths (`/index.html`, `assets/page.html`) are supported.",
1412
+ "name": "since"
1413
+ },
1406
1414
  {
1407
1415
  "text": "\"https://capgo.app\"",
1408
1416
  "name": "example"
1417
+ },
1418
+ {
1419
+ "text": "\"/index.html\"",
1420
+ "name": "example"
1409
1421
  }
1410
1422
  ],
1411
- "docs": "Target URL to load.",
1423
+ "docs": "Target URL to load.\n\nRemote `http://` and `https://` URLs are loaded as-is.\n\nTo open bundled web assets from the app bundle without running a local HTTP server,\npass a relative path such as `/index.html` or `assets/page.html`. The plugin resolves it to\nthe Capacitor local URL for the current platform (defaults: `capacitor://localhost/...` on iOS,\n`https://localhost/...` on Android; actual scheme and host follow the app's configured Capacitor\nlocal URL) and serves files from the packaged `public/` directory, or `www/` on iOS when `public/`\nis absent.",
1412
1424
  "complexTypes": [],
1413
1425
  "type": "string"
1414
1426
  },
@@ -2342,7 +2354,7 @@
2342
2354
  "name": "example"
2343
2355
  }
2344
2356
  ],
2345
- "docs": "If true, the webView will not take the full height and will have a 20px margin at the bottom.\nThis creates a safe margin area outside the browser view.",
2357
+ "docs": "If true, the webView is inset by the bottom system bar (navigation bar) so bottom-anchored\ncontent stays reachable. On Android 15+ the browser window is always edge-to-edge, so the\nbottom inset is applied there regardless of this option.",
2346
2358
  "complexTypes": [],
2347
2359
  "type": "boolean | undefined"
2348
2360
  },
@@ -2362,7 +2374,7 @@
2362
2374
  "name": "example"
2363
2375
  }
2364
2376
  ],
2365
- "docs": "If false, the webView will extend behind the status bar for true full-screen immersive content.\nWhen true (default), respects the safe area at the top of the screen.\nWorks independently of toolbarType - use for full-screen video players, games, or immersive web apps.",
2377
+ "docs": "If false, the webView will extend behind the status bar for true full-screen immersive content.\nWhen true (default), respects the safe area at the top of the screen.\nWorks independently of toolbarType - use for full-screen video players, games, or immersive web apps.\nOn Android, when a toolbar is visible the toolbar itself provides that safe area; with\n`toolbarType: 'blank'` on Android 15+ the status bar inset is applied to the webView instead.",
2366
2378
  "complexTypes": [],
2367
2379
  "type": "boolean | undefined"
2368
2380
  },
@@ -2378,7 +2390,7 @@
2378
2390
  "name": "example"
2379
2391
  }
2380
2392
  ],
2381
- "docs": "When true, applies the system status bar inset as the WebView top margin on Android.\nKeeps the legacy 0px margin by default for apps that handle padding themselves.",
2393
+ "docs": "When true, applies the system status bar inset to the top of the WebView on Android even when\nthe window is not edge-to-edge (before Android 15). Keeps the legacy 0px inset by default for\napps that handle padding themselves. On Android 15+ this is not needed: without a visible\ntoolbar the status bar inset already follows `enabledSafeTopMargin`.",
2382
2394
  "complexTypes": [],
2383
2395
  "type": "boolean | undefined"
2384
2396
  },
@@ -0,0 +1,40 @@
1
+ export type BundledAssetPlatform = 'ios' | 'android';
2
+ export interface BundledAssetLocalConfig {
3
+ scheme: string;
4
+ host: string;
5
+ }
6
+ export interface BundledAssetResolution {
7
+ url: string;
8
+ }
9
+ /** Default Capacitor local URL settings used when no runtime config is available. */
10
+ export declare const BUNDLED_ASSET_DEFAULTS: Record<BundledAssetPlatform, BundledAssetLocalConfig>;
11
+ /** Returns true when the input looks like an absolute URL (including protocol-relative URLs). */
12
+ export declare function isAbsoluteUrl(url: string): boolean;
13
+ /** Returns true when any path segment is `..`. */
14
+ export declare function containsPathTraversal(path: string): boolean;
15
+ /**
16
+ * Normalizes a relative bundled asset path to a leading-slash form.
17
+ * Returns null when the path contains traversal segments.
18
+ */
19
+ export declare function normalizeBundledPath(path: string): string | null;
20
+ /** Parses a Capacitor local URL into scheme and host components. */
21
+ export declare function parseBundledLocalConfig(localUrl?: string | null): BundledAssetLocalConfig | null;
22
+ /** Returns the scheme WebView navigation should use for bundled assets on a platform. */
23
+ export declare function handlerSchemeForPlatform(platform: BundledAssetPlatform, localConfig: BundledAssetLocalConfig): string;
24
+ /**
25
+ * Returns true when the URL targets the configured Capacitor local host/scheme
26
+ * (including the platform handler scheme rewrite).
27
+ */
28
+ export declare function isBundledLocalUrl(url: string, platform: BundledAssetPlatform, localConfig?: BundledAssetLocalConfig | null): boolean;
29
+ /** Returns true when the input is a non-empty relative bundled asset path. */
30
+ export declare function isRelativeBundledPath(url: string): boolean;
31
+ /**
32
+ * Resolves a bundled asset URL for the given platform.
33
+ * Relative paths become platform-local URLs; bundled local URLs may be rewritten to the handler scheme.
34
+ */
35
+ export declare function resolveBundledAssetUrl(url: string, platform: BundledAssetPlatform, localConfig?: BundledAssetLocalConfig | null): BundledAssetResolution | null;
36
+ /**
37
+ * Resolves relative bundled paths for legacy native plugins that do not perform native resolution.
38
+ * Throws when the path is invalid.
39
+ */
40
+ export declare function resolveLegacyNativeWebViewUrl(url: string, platform: BundledAssetPlatform, localConfig?: BundledAssetLocalConfig | null): string;
@@ -0,0 +1,157 @@
1
+ /** Default Capacitor local URL settings used when no runtime config is available. */
2
+ export const BUNDLED_ASSET_DEFAULTS = {
3
+ ios: { scheme: 'capacitor', host: 'localhost' },
4
+ android: { scheme: 'https', host: 'localhost' },
5
+ };
6
+ const ABSOLUTE_URL_PATTERN = /^[a-zA-Z][a-zA-Z\d+\-.]*:/;
7
+ const RESERVED_WEB_SCHEMES = ['http', 'https'];
8
+ /** Returns true when the input looks like an absolute URL (including protocol-relative URLs). */
9
+ export function isAbsoluteUrl(url) {
10
+ return ABSOLUTE_URL_PATTERN.test(url) || url.startsWith('//');
11
+ }
12
+ /** Returns true when any path segment is `..`. */
13
+ export function containsPathTraversal(path) {
14
+ return path.split('/').includes('..');
15
+ }
16
+ /**
17
+ * Normalizes a relative bundled asset path to a leading-slash form.
18
+ * Returns null when the path contains traversal segments.
19
+ */
20
+ export function normalizeBundledPath(path) {
21
+ const trimmed = path.trim();
22
+ if (!trimmed || trimmed === '/') {
23
+ return '/';
24
+ }
25
+ if (containsPathTraversal(trimmed)) {
26
+ return null;
27
+ }
28
+ return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;
29
+ }
30
+ /** Parses a Capacitor local URL into scheme and host components. */
31
+ export function parseBundledLocalConfig(localUrl) {
32
+ if (!localUrl) {
33
+ return null;
34
+ }
35
+ try {
36
+ const parsed = new URL(localUrl.endsWith('/') ? localUrl : `${localUrl}/`);
37
+ if (!parsed.protocol || !parsed.hostname) {
38
+ return null;
39
+ }
40
+ return {
41
+ scheme: parsed.protocol.replace(/:$/, '').toLowerCase(),
42
+ host: parsed.hostname.toLowerCase(),
43
+ };
44
+ }
45
+ catch (_a) {
46
+ return null;
47
+ }
48
+ }
49
+ /** Returns the scheme WebView navigation should use for bundled assets on a platform. */
50
+ export function handlerSchemeForPlatform(platform, localConfig) {
51
+ if (platform === 'ios' && RESERVED_WEB_SCHEMES.includes(localConfig.scheme)) {
52
+ return BUNDLED_ASSET_DEFAULTS.ios.scheme;
53
+ }
54
+ if (platform === 'android') {
55
+ if (localConfig.scheme === 'http' || localConfig.scheme === 'https') {
56
+ return localConfig.scheme;
57
+ }
58
+ return BUNDLED_ASSET_DEFAULTS.android.scheme;
59
+ }
60
+ return localConfig.scheme;
61
+ }
62
+ /**
63
+ * Returns true when the URL targets the configured Capacitor local host/scheme
64
+ * (including the platform handler scheme rewrite).
65
+ */
66
+ export function isBundledLocalUrl(url, platform, localConfig) {
67
+ if (!isAbsoluteUrl(url)) {
68
+ return false;
69
+ }
70
+ try {
71
+ const parsed = new URL(url);
72
+ const scheme = parsed.protocol.replace(/:$/, '').toLowerCase();
73
+ const host = parsed.hostname.toLowerCase();
74
+ const config = localConfig !== null && localConfig !== void 0 ? localConfig : BUNDLED_ASSET_DEFAULTS[platform];
75
+ if (host !== config.host) {
76
+ return false;
77
+ }
78
+ if (parsed.port !== '') {
79
+ return false;
80
+ }
81
+ if (scheme === config.scheme || scheme === handlerSchemeForPlatform(platform, config)) {
82
+ return true;
83
+ }
84
+ return RESERVED_WEB_SCHEMES.includes(scheme) && RESERVED_WEB_SCHEMES.includes(config.scheme);
85
+ }
86
+ catch (_a) {
87
+ return false;
88
+ }
89
+ }
90
+ /** Returns true when the input is a non-empty relative bundled asset path. */
91
+ export function isRelativeBundledPath(url) {
92
+ const trimmed = url.trim();
93
+ if (!trimmed) {
94
+ return false;
95
+ }
96
+ return !isAbsoluteUrl(trimmed);
97
+ }
98
+ function rewriteBundledLocalUrl(url, localConfig, navigationScheme) {
99
+ try {
100
+ const parsed = new URL(url);
101
+ const host = parsed.hostname.toLowerCase();
102
+ const scheme = parsed.protocol.replace(/:$/, '').toLowerCase();
103
+ if (host !== localConfig.host || scheme === navigationScheme) {
104
+ return null;
105
+ }
106
+ const pathname = parsed.pathname || '/';
107
+ const search = parsed.search;
108
+ const hash = parsed.hash;
109
+ const userinfo = parsed.username.length > 0 ? `${parsed.username}${parsed.password.length > 0 ? `:${parsed.password}` : ''}@` : '';
110
+ return `${navigationScheme}://${userinfo}${host}${pathname}${search}${hash}`;
111
+ }
112
+ catch (_a) {
113
+ return null;
114
+ }
115
+ }
116
+ /**
117
+ * Resolves a bundled asset URL for the given platform.
118
+ * Relative paths become platform-local URLs; bundled local URLs may be rewritten to the handler scheme.
119
+ */
120
+ export function resolveBundledAssetUrl(url, platform, localConfig) {
121
+ const trimmed = url.trim();
122
+ const config = localConfig !== null && localConfig !== void 0 ? localConfig : BUNDLED_ASSET_DEFAULTS[platform];
123
+ const navigationScheme = handlerSchemeForPlatform(platform, config);
124
+ if (isRelativeBundledPath(trimmed)) {
125
+ const path = normalizeBundledPath(trimmed);
126
+ if (path === null) {
127
+ return null;
128
+ }
129
+ return {
130
+ url: `${navigationScheme}://${config.host}${path}`,
131
+ };
132
+ }
133
+ if (isBundledLocalUrl(trimmed, platform, config)) {
134
+ const rewritten = rewriteBundledLocalUrl(trimmed, config, navigationScheme);
135
+ return {
136
+ url: rewritten !== null && rewritten !== void 0 ? rewritten : trimmed,
137
+ };
138
+ }
139
+ return {
140
+ url: trimmed,
141
+ };
142
+ }
143
+ /**
144
+ * Resolves relative bundled paths for legacy native plugins that do not perform native resolution.
145
+ * Throws when the path is invalid.
146
+ */
147
+ export function resolveLegacyNativeWebViewUrl(url, platform, localConfig) {
148
+ if (!isRelativeBundledPath(url)) {
149
+ return url;
150
+ }
151
+ const resolution = resolveBundledAssetUrl(url, platform, localConfig);
152
+ if (resolution === null) {
153
+ throw new Error('Invalid bundled asset path');
154
+ }
155
+ return resolution.url;
156
+ }
157
+ //# sourceMappingURL=bundled-asset-support.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bundled-asset-support.js","sourceRoot":"","sources":["../../src/bundled-asset-support.ts"],"names":[],"mappings":"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","sourcesContent":["export type BundledAssetPlatform = 'ios' | 'android';\n\nexport interface BundledAssetLocalConfig {\n scheme: string;\n host: string;\n}\n\nexport interface BundledAssetResolution {\n url: string;\n}\n\n/** Default Capacitor local URL settings used when no runtime config is available. */\nexport const BUNDLED_ASSET_DEFAULTS: Record<BundledAssetPlatform, BundledAssetLocalConfig> = {\n ios: { scheme: 'capacitor', host: 'localhost' },\n android: { scheme: 'https', host: 'localhost' },\n};\n\nconst ABSOLUTE_URL_PATTERN = /^[a-zA-Z][a-zA-Z\\d+\\-.]*:/;\nconst RESERVED_WEB_SCHEMES = ['http', 'https'];\n\n/** Returns true when the input looks like an absolute URL (including protocol-relative URLs). */\nexport function isAbsoluteUrl(url: string): boolean {\n return ABSOLUTE_URL_PATTERN.test(url) || url.startsWith('//');\n}\n\n/** Returns true when any path segment is `..`. */\nexport function containsPathTraversal(path: string): boolean {\n return path.split('/').includes('..');\n}\n\n/**\n * Normalizes a relative bundled asset path to a leading-slash form.\n * Returns null when the path contains traversal segments.\n */\nexport function normalizeBundledPath(path: string): string | null {\n const trimmed = path.trim();\n if (!trimmed || trimmed === '/') {\n return '/';\n }\n\n if (containsPathTraversal(trimmed)) {\n return null;\n }\n\n return trimmed.startsWith('/') ? trimmed : `/${trimmed}`;\n}\n\n/** Parses a Capacitor local URL into scheme and host components. */\nexport function parseBundledLocalConfig(localUrl?: string | null): BundledAssetLocalConfig | null {\n if (!localUrl) {\n return null;\n }\n\n try {\n const parsed = new URL(localUrl.endsWith('/') ? localUrl : `${localUrl}/`);\n if (!parsed.protocol || !parsed.hostname) {\n return null;\n }\n\n return {\n scheme: parsed.protocol.replace(/:$/, '').toLowerCase(),\n host: parsed.hostname.toLowerCase(),\n };\n } catch {\n return null;\n }\n}\n\n/** Returns the scheme WebView navigation should use for bundled assets on a platform. */\nexport function handlerSchemeForPlatform(platform: BundledAssetPlatform, localConfig: BundledAssetLocalConfig): string {\n if (platform === 'ios' && RESERVED_WEB_SCHEMES.includes(localConfig.scheme)) {\n return BUNDLED_ASSET_DEFAULTS.ios.scheme;\n }\n\n if (platform === 'android') {\n if (localConfig.scheme === 'http' || localConfig.scheme === 'https') {\n return localConfig.scheme;\n }\n return BUNDLED_ASSET_DEFAULTS.android.scheme;\n }\n\n return localConfig.scheme;\n}\n\n/**\n * Returns true when the URL targets the configured Capacitor local host/scheme\n * (including the platform handler scheme rewrite).\n */\nexport function isBundledLocalUrl(\n url: string,\n platform: BundledAssetPlatform,\n localConfig?: BundledAssetLocalConfig | null,\n): boolean {\n if (!isAbsoluteUrl(url)) {\n return false;\n }\n\n try {\n const parsed = new URL(url);\n const scheme = parsed.protocol.replace(/:$/, '').toLowerCase();\n const host = parsed.hostname.toLowerCase();\n const config = localConfig ?? BUNDLED_ASSET_DEFAULTS[platform];\n\n if (host !== config.host) {\n return false;\n }\n\n if (parsed.port !== '') {\n return false;\n }\n\n if (scheme === config.scheme || scheme === handlerSchemeForPlatform(platform, config)) {\n return true;\n }\n\n return RESERVED_WEB_SCHEMES.includes(scheme) && RESERVED_WEB_SCHEMES.includes(config.scheme);\n } catch {\n return false;\n }\n}\n\n/** Returns true when the input is a non-empty relative bundled asset path. */\nexport function isRelativeBundledPath(url: string): boolean {\n const trimmed = url.trim();\n if (!trimmed) {\n return false;\n }\n\n return !isAbsoluteUrl(trimmed);\n}\n\nfunction rewriteBundledLocalUrl(\n url: string,\n localConfig: BundledAssetLocalConfig,\n navigationScheme: string,\n): string | null {\n try {\n const parsed = new URL(url);\n const host = parsed.hostname.toLowerCase();\n const scheme = parsed.protocol.replace(/:$/, '').toLowerCase();\n\n if (host !== localConfig.host || scheme === navigationScheme) {\n return null;\n }\n\n const pathname = parsed.pathname || '/';\n const search = parsed.search;\n const hash = parsed.hash;\n const userinfo =\n parsed.username.length > 0 ? `${parsed.username}${parsed.password.length > 0 ? `:${parsed.password}` : ''}@` : '';\n return `${navigationScheme}://${userinfo}${host}${pathname}${search}${hash}`;\n } catch {\n return null;\n }\n}\n\n/**\n * Resolves a bundled asset URL for the given platform.\n * Relative paths become platform-local URLs; bundled local URLs may be rewritten to the handler scheme.\n */\nexport function resolveBundledAssetUrl(\n url: string,\n platform: BundledAssetPlatform,\n localConfig?: BundledAssetLocalConfig | null,\n): BundledAssetResolution | null {\n const trimmed = url.trim();\n const config = localConfig ?? BUNDLED_ASSET_DEFAULTS[platform];\n const navigationScheme = handlerSchemeForPlatform(platform, config);\n\n if (isRelativeBundledPath(trimmed)) {\n const path = normalizeBundledPath(trimmed);\n if (path === null) {\n return null;\n }\n return {\n url: `${navigationScheme}://${config.host}${path}`,\n };\n }\n\n if (isBundledLocalUrl(trimmed, platform, config)) {\n const rewritten = rewriteBundledLocalUrl(trimmed, config, navigationScheme);\n return {\n url: rewritten ?? trimmed,\n };\n }\n\n return {\n url: trimmed,\n };\n}\n\n/**\n * Resolves relative bundled paths for legacy native plugins that do not perform native resolution.\n * Throws when the path is invalid.\n */\nexport function resolveLegacyNativeWebViewUrl(\n url: string,\n platform: BundledAssetPlatform,\n localConfig?: BundledAssetLocalConfig | null,\n): string {\n if (!isRelativeBundledPath(url)) {\n return url;\n }\n\n const resolution = resolveBundledAssetUrl(url, platform, localConfig);\n if (resolution === null) {\n throw new Error('Invalid bundled asset path');\n }\n\n return resolution.url;\n}\n"]}
@@ -419,7 +419,12 @@ export type ProxyHandler = (request: ProxyRequest) => ProxyHandlerResult | Promi
419
419
  export interface OpenOptions {
420
420
  /**
421
421
  * Target URL to load.
422
+ *
423
+ * Remote `http://` and `https://` URLs are loaded as-is. Relative bundled paths
424
+ * such as `/index.html` are not supported; use `openWebView()` instead.
425
+ *
422
426
  * @since 0.1.0
427
+ * @example "https://capgo.app"
423
428
  */
424
429
  url: string;
425
430
  /**
@@ -595,8 +600,20 @@ export interface CloseWebviewOptions {
595
600
  export interface OpenWebViewOptions {
596
601
  /**
597
602
  * Target URL to load.
603
+ *
604
+ * Remote `http://` and `https://` URLs are loaded as-is.
605
+ *
606
+ * To open bundled web assets from the app bundle without running a local HTTP server,
607
+ * pass a relative path such as `/index.html` or `assets/page.html`. The plugin resolves it to
608
+ * the Capacitor local URL for the current platform (defaults: `capacitor://localhost/...` on iOS,
609
+ * `https://localhost/...` on Android; actual scheme and host follow the app's configured Capacitor
610
+ * local URL) and serves files from the packaged `public/` directory, or `www/` on iOS when `public/`
611
+ * is absent.
612
+ *
598
613
  * @since 0.1.0
614
+ * @since 8.15.0 Relative bundled paths (`/index.html`, `assets/page.html`) are supported.
599
615
  * @example "https://capgo.app"
616
+ * @example "/index.html"
600
617
  */
601
618
  url: string;
602
619
  /**
@@ -1200,8 +1217,9 @@ export interface OpenWebViewOptions {
1200
1217
  */
1201
1218
  authorizedAppLinks?: string[];
1202
1219
  /**
1203
- * If true, the webView will not take the full height and will have a 20px margin at the bottom.
1204
- * This creates a safe margin area outside the browser view.
1220
+ * If true, the webView is inset by the bottom system bar (navigation bar) so bottom-anchored
1221
+ * content stays reachable. On Android 15+ the browser window is always edge-to-edge, so the
1222
+ * bottom inset is applied there regardless of this option.
1205
1223
  * @since 7.13.0
1206
1224
  * @default false
1207
1225
  * @example
@@ -1212,6 +1230,8 @@ export interface OpenWebViewOptions {
1212
1230
  * If false, the webView will extend behind the status bar for true full-screen immersive content.
1213
1231
  * When true (default), respects the safe area at the top of the screen.
1214
1232
  * Works independently of toolbarType - use for full-screen video players, games, or immersive web apps.
1233
+ * On Android, when a toolbar is visible the toolbar itself provides that safe area; with
1234
+ * `toolbarType: 'blank'` on Android 15+ the status bar inset is applied to the webView instead.
1215
1235
  * @since 8.2.0
1216
1236
  * @default true
1217
1237
  * @example
@@ -1219,8 +1239,10 @@ export interface OpenWebViewOptions {
1219
1239
  */
1220
1240
  enabledSafeTopMargin?: boolean;
1221
1241
  /**
1222
- * When true, applies the system status bar inset as the WebView top margin on Android.
1223
- * Keeps the legacy 0px margin by default for apps that handle padding themselves.
1242
+ * When true, applies the system status bar inset to the top of the WebView on Android even when
1243
+ * the window is not edge-to-edge (before Android 15). Keeps the legacy 0px inset by default for
1244
+ * apps that handle padding themselves. On Android 15+ this is not needed: without a visible
1245
+ * toolbar the status bar inset already follows `enabledSafeTopMargin`.
1224
1246
  * @default false
1225
1247
  * @example
1226
1248
  * useTopInset: true