@prosopo/procaptcha-bundle 4.1.33 → 4.1.35
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/.turbo/turbo-build$colon$cjs.log +4 -4
- package/.turbo/turbo-build$colon$tsc.log +27 -27
- package/.turbo/turbo-build.log +5 -5
- package/CHANGELOG.md +42 -0
- package/dist/cjs/util/language.cjs +10 -2
- package/dist/cjs/util/widgetFactory.cjs +7 -3
- package/dist/util/language.d.ts +1 -0
- package/dist/util/language.d.ts.map +1 -1
- package/dist/util/language.js +10 -2
- package/dist/util/language.js.map +1 -1
- package/dist/util/widgetFactory.d.ts +1 -1
- package/dist/util/widgetFactory.d.ts.map +1 -1
- package/dist/util/widgetFactory.js +7 -3
- package/dist/util/widgetFactory.js.map +1 -1
- package/package.json +5 -5
- package/src/util/language.ts +19 -2
- package/src/util/widgetFactory.ts +18 -3
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.config.ts +24 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/procaptcha-bundle@4.1.
|
|
2
|
+
> @prosopo/procaptcha-bundle@4.1.35 build:cjs
|
|
3
3
|
> NODE_ENV=${NODE_ENV:-development}; vite build --config vite.cjs.config.ts --mode $NODE_ENV
|
|
4
4
|
|
|
5
5
|
ViteCommonJSConfig: .
|
|
@@ -64,11 +64,11 @@ Build end
|
|
|
64
64
|
rendering chunks...
|
|
65
65
|
[2mdist/cjs/[22m[36mutil/timeout.cjs [39m[1m[2m0.61 kB[22m[1m[22m
|
|
66
66
|
[2mdist/cjs/[22m[36mutil/widgetThemeResolver.cjs [39m[1m[2m0.62 kB[22m[1m[22m
|
|
67
|
-
[2mdist/cjs/[22m[36mutil/language.cjs [39m[1m[2m0.67 kB[22m[1m[22m
|
|
68
67
|
[2mdist/cjs/[22m[36mutil/config.cjs [39m[1m[2m0.76 kB[22m[1m[22m
|
|
69
68
|
[2mdist/cjs/[22m[36mutil/captcha/components/bundleCaptcha.cjs [39m[1m[2m0.83 kB[22m[1m[22m
|
|
69
|
+
[2mdist/cjs/[22m[36mutil/language.cjs [39m[1m[2m0.89 kB[22m[1m[22m
|
|
70
70
|
[2mdist/cjs/[22m[36mutil/configCreator.cjs [39m[1m[2m0.93 kB[22m[1m[22m
|
|
71
71
|
[2mdist/cjs/[22m[36mutil/captcha/captchaRenderer.cjs [39m[1m[2m2.21 kB[22m[1m[22m
|
|
72
|
-
[2mdist/cjs/[22m[36mutil/widgetFactory.cjs [39m[1m[
|
|
72
|
+
[2mdist/cjs/[22m[36mutil/widgetFactory.cjs [39m[1m[2m3.08 kB[22m[1m[22m
|
|
73
73
|
[2mdist/cjs/[22m[36mindex.cjs [39m[1m[2m5.79 kB[22m[1m[22m
|
|
74
|
-
[32m✓ built in
|
|
74
|
+
[32m✓ built in 147ms[39m
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/procaptcha-bundle@4.1.
|
|
2
|
+
> @prosopo/procaptcha-bundle@4.1.35 build:tsc
|
|
3
3
|
> tsc --build --verbose
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
4:35:58 PM - Projects in this build:
|
|
6
6
|
* ../../dev/config/tsconfig.json
|
|
7
7
|
* ../util/tsconfig.json
|
|
8
8
|
* ../logger/tsconfig.json
|
|
@@ -28,53 +28,53 @@
|
|
|
28
28
|
* ../procaptcha-frictionless/tsconfig.json
|
|
29
29
|
* tsconfig.json
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
4:35:58 PM - Project '../../dev/config/tsconfig.json' is up to date because newest input '../../dev/config/src/index.ts' is older than output '../../dev/config/tsconfig.tsbuildinfo'
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
4:35:58 PM - Project '../util/tsconfig.json' is up to date because newest input '../util/src/url.ts' is older than output '../util/tsconfig.tsbuildinfo'
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
4:35:58 PM - Project '../logger/tsconfig.json' is up to date because newest input '../logger/src/index.ts' is older than output '../logger/tsconfig.tsbuildinfo'
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
4:35:58 PM - Project '../dotenv/tsconfig.json' is up to date because newest input '../dotenv/src/env.ts' is older than output '../dotenv/tsconfig.tsbuildinfo'
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
4:35:58 PM - Project '../locale/tsconfig.json' is up to date because newest input '../locale/src/translationKey.ts' is older than output '../locale/tsconfig.tsbuildinfo'
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
4:35:58 PM - Project '../util-crypto/tsconfig.json' is up to date because newest input '../util-crypto/src/types.ts' is older than output '../util-crypto/tsconfig.tsbuildinfo'
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
4:35:58 PM - Project '../types/tsconfig.json' is up to date because newest input '../types/src/keyring/keyring/types.ts' is older than output '../types/tsconfig.tsbuildinfo'
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
4:35:58 PM - Project '../detector/tsconfig.json' is up to date because newest input '../detector/src/index.js' is older than output '../detector/tsconfig.tsbuildinfo'
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
4:35:58 PM - Project '../api/tsconfig.json' is up to date because newest input '../api/src/index.ts' is older than output '../api/tsconfig.tsbuildinfo'
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
4:35:58 PM - Project '../common/tsconfig.json' is up to date because newest input '../common/src/index.ts' is older than output '../common/tsconfig.tsbuildinfo'
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
4:35:58 PM - Project '../fingerprintjs/tsconfig.json' is up to date because newest input '../fingerprintjs/src/utils/browser.ts' is older than output '../fingerprintjs/tsconfig.tsbuildinfo'
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
4:35:58 PM - Project '../fingerprint/tsconfig.json' is up to date because newest input '../fingerprint/src/index.ts' is older than output '../fingerprint/tsconfig.tsbuildinfo'
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
4:35:58 PM - Project '../load-balancer/tsconfig.json' is up to date because newest input '../load-balancer/src/balancer.ts' is older than output '../load-balancer/tsconfig.tsbuildinfo'
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
4:35:58 PM - Project '../widget-skeleton/tsconfig.json' is up to date because newest input '../widget-skeleton/src/webComponent/createWidget.ts' is older than output '../widget-skeleton/tsconfig.tsbuildinfo'
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
4:35:58 PM - Project '../keyring/tsconfig.json' is up to date because newest input '../keyring/src/index.ts' is older than output '../keyring/tsconfig.tsbuildinfo'
|
|
60
60
|
|
|
61
|
-
|
|
61
|
+
4:35:58 PM - Project '../account/tsconfig.json' is up to date because newest input '../account/src/custom.d.ts' is older than output '../account/tsconfig.tsbuildinfo'
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
4:35:58 PM - Project '../procaptcha-common/tsconfig.json' is up to date because newest input '../procaptcha-common/src/reactComponents/Honeypot.tsx' is older than output '../procaptcha-common/tsconfig.tsbuildinfo'
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
4:35:58 PM - Project '../procaptcha-pow/tsconfig.json' is up to date because newest input '../procaptcha-pow/src/index.ts' is older than output '../procaptcha-pow/tsconfig.tsbuildinfo'
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
4:35:58 PM - Project '../procaptcha-puzzle/tsconfig.json' is up to date because newest input '../procaptcha-puzzle/src/index.ts' is older than output '../procaptcha-puzzle/tsconfig.tsbuildinfo'
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
4:35:58 PM - Project '../datasets/tsconfig.json' is up to date because newest input '../datasets/src/tests/mocks/data/captchas.ts' is older than output '../datasets/tsconfig.tsbuildinfo'
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
4:35:58 PM - Project '../procaptcha/tsconfig.json' is up to date because newest input '../procaptcha/src/modules/Manager.ts' is older than output '../procaptcha/tsconfig.tsbuildinfo'
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
4:35:58 PM - Project '../procaptcha-react/tsconfig.json' is up to date because newest input '../procaptcha-react/src/index.ts' is older than output '../procaptcha-react/tsconfig.tsbuildinfo'
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
4:35:58 PM - Project '../procaptcha-frictionless/tsconfig.json' is up to date because newest input '../procaptcha-frictionless/src/tests/customDetectBotSimd.test.ts' is older than output '../procaptcha-frictionless/tsconfig.tsbuildinfo'
|
|
76
76
|
|
|
77
|
-
|
|
77
|
+
4:35:58 PM - Project 'tsconfig.json' is out of date because output file 'tsconfig.tsbuildinfo' does not exist
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
4:35:58 PM - Building project '/home/runner/work/captcha/captcha/packages/procaptcha-bundle/tsconfig.json'...
|
|
80
80
|
|
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @prosopo/procaptcha-bundle@4.1.
|
|
2
|
+
> @prosopo/procaptcha-bundle@4.1.35 build
|
|
3
3
|
> npm run build:cross-env -- --mode ${NODE_ENV:-development}
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @prosopo/procaptcha-bundle@4.1.
|
|
6
|
+
> @prosopo/procaptcha-bundle@4.1.35 build:cross-env
|
|
7
7
|
> vite build --config vite.esm.config.ts --mode production
|
|
8
8
|
|
|
9
9
|
ViteEsmConfig: .
|
|
@@ -67,11 +67,11 @@ Build end
|
|
|
67
67
|
rendering chunks...
|
|
68
68
|
[2mdist/[22m[36mutil/timeout.js [39m[1m[2m0.50 kB[22m[1m[22m
|
|
69
69
|
[2mdist/[22m[36mutil/widgetThemeResolver.js [39m[1m[2m0.51 kB[22m[1m[22m
|
|
70
|
-
[2mdist/[22m[36mutil/language.js [39m[1m[2m0.57 kB[22m[1m[22m
|
|
71
70
|
[2mdist/[22m[36mutil/config.js [39m[1m[2m0.63 kB[22m[1m[22m
|
|
72
71
|
[2mdist/[22m[36mutil/captcha/components/bundleCaptcha.js [39m[1m[2m0.66 kB[22m[1m[22m
|
|
72
|
+
[2mdist/[22m[36mutil/language.js [39m[1m[2m0.77 kB[22m[1m[22m
|
|
73
73
|
[2mdist/[22m[36mutil/configCreator.js [39m[1m[2m0.86 kB[22m[1m[22m
|
|
74
74
|
[2mdist/[22m[36mutil/captcha/captchaRenderer.js [39m[1m[2m2.04 kB[22m[1m[22m
|
|
75
|
-
[2mdist/[22m[36mutil/widgetFactory.js [39m[1m[2m2.
|
|
75
|
+
[2mdist/[22m[36mutil/widgetFactory.js [39m[1m[2m2.90 kB[22m[1m[22m
|
|
76
76
|
[2mdist/[22m[36mindex.js [39m[1m[2m5.55 kB[22m[1m[22m
|
|
77
|
-
[32m✓ built in
|
|
77
|
+
[32m✓ built in 216ms[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,47 @@
|
|
|
1
1
|
# @prosopo/procaptcha-bundle
|
|
2
2
|
|
|
3
|
+
## 4.1.35
|
|
4
|
+
### Patch Changes
|
|
5
|
+
|
|
6
|
+
- 7272dee: perf(procaptcha-bundle): force `@prosopo/fingerprint` + `@prosopo/fingerprintjs` into a single shared chunk (~220ms main-thread win)
|
|
7
|
+
|
|
8
|
+
Chrome timeline traces on a heavy page (pimeyes.com) showed **two nearly-identical ~220ms main-thread tasks** dominated by `getContext` / `getParameter` / `getImageData` — Canvas + WebGL fingerprint sources running twice per widget session. Different obfuscated function graphs in each task (`vr → jl → mr` vs `ge → kn → U`) and different chunk URLs (`index-Bty406ZI.js` vs `index-Cewgc2Jv.js`), while `@prosopo/fingerprint/index.ts` deliberately memoises via a module-local `componentsCache` — proof that Vite was inlining `@prosopo/fingerprint` into multiple downstream chunks (the widget bundle for `account.createAccount` → `getFingerprint`, and `procaptcha-pow` for `Manager` → `getFingerprintProof`), giving each chunk its own module instance and its own private cache.
|
|
9
|
+
|
|
10
|
+
`manualChunks` now routes `packages/fingerprint/dist` + `packages/fingerprintjs/dist` into one shared chunk (per-build opaque name, same pattern as `honeypotChunkName` — no `fingerprint` in the emitted URL). One physical chunk = one module instance = one populated `componentsCache` = one execution of the expensive Canvas + WebGL sources per widget session. Both `getFingerprint` and `getFingerprintProof` now hit the cache on the second call within a session, which was the original design intent.
|
|
11
|
+
|
|
12
|
+
Measured on staging widget injected into pimeyes.com:
|
|
13
|
+
|
|
14
|
+
- Before: 2 × ~220ms main-thread long tasks, ~2000 `getContext` self-samples on main
|
|
15
|
+
- After: 0 `getContext` self-samples on main, fingerprint dropped out of the main-thread long-task list entirely
|
|
16
|
+
|
|
17
|
+
No API change. Opaque chunk name means the emitted URL doesn't leak what's inside (won't help static URL-blocklist scrapers).
|
|
18
|
+
- b500d56: fix(widget): enforce single language across widget, kill browser/config race
|
|
19
|
+
|
|
20
|
+
`WidgetFactory.getCaptchaRenderer()` booted the i18n singleton with the
|
|
21
|
+
browser-detected language before the site-owner `renderOptions.language` /
|
|
22
|
+
`data-language` had been resolved, and each widget then called
|
|
23
|
+
`i18n.changeLanguage(config.language)` from a post-mount effect. Any child
|
|
24
|
+
component that read `useTranslation()` between first render and the async
|
|
25
|
+
`changeLanguage` resolution rendered in the browser language, then re-rendered
|
|
26
|
+
in the site-owner language — the multi-language flash customers reported.
|
|
27
|
+
|
|
28
|
+
Resolve the site-owner language in `WidgetFactory.createWidget()` before the
|
|
29
|
+
lazy renderer load and thread it into `loadI18next(false, lng)`, so the
|
|
30
|
+
singleton boots (or reconciles via `changeLanguage` + await) with the correct
|
|
31
|
+
language before React mounts. Site-owner language wins; falls back to browser
|
|
32
|
+
detection only when no `language` / `data-language` is set.
|
|
33
|
+
- Updated dependencies [b500d56]
|
|
34
|
+
- @prosopo/locale@3.2.7
|
|
35
|
+
- @prosopo/procaptcha-frictionless@2.12.16
|
|
36
|
+
- @prosopo/types@4.9.9
|
|
37
|
+
- @prosopo/procaptcha-common@2.11.13
|
|
38
|
+
|
|
39
|
+
## 4.1.34
|
|
40
|
+
### Patch Changes
|
|
41
|
+
|
|
42
|
+
- Updated dependencies [d0f3a52]
|
|
43
|
+
- @prosopo/procaptcha-frictionless@2.12.15
|
|
44
|
+
|
|
3
45
|
## 4.1.33
|
|
4
46
|
### Patch Changes
|
|
5
47
|
|
|
@@ -2,10 +2,17 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const locale = require("@prosopo/locale");
|
|
4
4
|
const setLanguage = (renderOptions, element, config) => {
|
|
5
|
+
const resolved = resolveLanguage(renderOptions, element);
|
|
6
|
+
if (resolved) {
|
|
7
|
+
config.language = resolved;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const resolveLanguage = (renderOptions, element) => {
|
|
5
11
|
const languageAttribute = renderOptions?.language || element.getAttribute("data-language");
|
|
6
|
-
if (languageAttribute) {
|
|
7
|
-
|
|
12
|
+
if (!languageAttribute) {
|
|
13
|
+
return void 0;
|
|
8
14
|
}
|
|
15
|
+
return validateLanguage(languageAttribute);
|
|
9
16
|
};
|
|
10
17
|
const validateLanguage = (languageAttribute) => {
|
|
11
18
|
try {
|
|
@@ -15,4 +22,5 @@ const validateLanguage = (languageAttribute) => {
|
|
|
15
22
|
return locale.LanguageSchema.parse("en");
|
|
16
23
|
}
|
|
17
24
|
};
|
|
25
|
+
exports.resolveLanguage = resolveLanguage;
|
|
18
26
|
exports.setLanguage = setLanguage;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const locale = require("@prosopo/locale");
|
|
4
4
|
const procaptchaCommon = require("@prosopo/procaptcha-common");
|
|
5
5
|
const widgetSkeleton = require("@prosopo/widget-skeleton");
|
|
6
|
+
const language = require("./language.cjs");
|
|
6
7
|
class WidgetFactory {
|
|
7
8
|
constructor(widgetThemeResolver) {
|
|
8
9
|
this.widgetThemeResolver = widgetThemeResolver;
|
|
@@ -52,7 +53,8 @@ class WidgetFactory {
|
|
|
52
53
|
widgetInteractiveArea = widgetResult.widgetInteractiveArea;
|
|
53
54
|
widgetContainer = widgetResult.webComponent;
|
|
54
55
|
}
|
|
55
|
-
const
|
|
56
|
+
const language$1 = language.resolveLanguage(renderOptions, container);
|
|
57
|
+
const captchaRenderer = await this.getCaptchaRenderer(language$1);
|
|
56
58
|
const captchaRoot = captchaRenderer.renderCaptcha(
|
|
57
59
|
{
|
|
58
60
|
identifierPrefix: "procaptcha-",
|
|
@@ -70,9 +72,11 @@ class WidgetFactory {
|
|
|
70
72
|
);
|
|
71
73
|
return captchaRoot;
|
|
72
74
|
}
|
|
73
|
-
async getCaptchaRenderer() {
|
|
75
|
+
async getCaptchaRenderer(language2) {
|
|
74
76
|
if (this._i18n === null) {
|
|
75
|
-
this._i18n = await locale.loadI18next(false);
|
|
77
|
+
this._i18n = await locale.loadI18next(false, language2);
|
|
78
|
+
} else if (language2 && this._i18n.language !== language2) {
|
|
79
|
+
await this._i18n.changeLanguage(language2);
|
|
76
80
|
}
|
|
77
81
|
if (this.captchaRenderer === null) {
|
|
78
82
|
this.captchaRenderer = await this.createCaptchaRenderer();
|
package/dist/util/language.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { ProcaptchaClientConfigInput, ProcaptchaRenderOptions } from "@prosopo/types";
|
|
2
2
|
export declare const setLanguage: (renderOptions: ProcaptchaRenderOptions | undefined, element: Element, config: ProcaptchaClientConfigInput) => void;
|
|
3
|
+
export declare const resolveLanguage: (renderOptions: ProcaptchaRenderOptions | undefined, element: Element) => string | undefined;
|
|
3
4
|
//# sourceMappingURL=language.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../../src/util/language.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACX,2BAA2B,EAC3B,uBAAuB,EACvB,MAAM,gBAAgB,CAAC;AAcxB,eAAO,MAAM,WAAW,kBACR,uBAAuB,GAAG,SAAS,WACzC,OAAO,UACR,2BAA2B,
|
|
1
|
+
{"version":3,"file":"language.d.ts","sourceRoot":"","sources":["../../src/util/language.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EACX,2BAA2B,EAC3B,uBAAuB,EACvB,MAAM,gBAAgB,CAAC;AAcxB,eAAO,MAAM,WAAW,kBACR,uBAAuB,GAAG,SAAS,WACzC,OAAO,UACR,2BAA2B,SAOnC,CAAC;AAMF,eAAO,MAAM,eAAe,kBACZ,uBAAuB,GAAG,SAAS,WACzC,OAAO,KACd,MAAM,GAAG,SASX,CAAC"}
|
package/dist/util/language.js
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import { LanguageSchema } from "@prosopo/locale";
|
|
2
2
|
const setLanguage = (renderOptions, element, config) => {
|
|
3
|
+
const resolved = resolveLanguage(renderOptions, element);
|
|
4
|
+
if (resolved) {
|
|
5
|
+
config.language = resolved;
|
|
6
|
+
}
|
|
7
|
+
};
|
|
8
|
+
const resolveLanguage = (renderOptions, element) => {
|
|
3
9
|
const languageAttribute = renderOptions?.language || element.getAttribute("data-language");
|
|
4
|
-
if (languageAttribute) {
|
|
5
|
-
|
|
10
|
+
if (!languageAttribute) {
|
|
11
|
+
return void 0;
|
|
6
12
|
}
|
|
13
|
+
return validateLanguage(languageAttribute);
|
|
7
14
|
};
|
|
8
15
|
const validateLanguage = (languageAttribute) => {
|
|
9
16
|
try {
|
|
@@ -14,5 +21,6 @@ const validateLanguage = (languageAttribute) => {
|
|
|
14
21
|
}
|
|
15
22
|
};
|
|
16
23
|
export {
|
|
24
|
+
resolveLanguage,
|
|
17
25
|
setLanguage
|
|
18
26
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"language.js","sourceRoot":"","sources":["../../src/util/language.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAkB,MAAM,iBAAiB,CAAC;AAkBjE,MAAM,CAAC,MAAM,WAAW,GAAG,CAC1B,aAAkD,EAClD,OAAgB,EAChB,MAAmC,EAClC,EAAE;IACH,MAAM,iBAAiB,GACtB,aAAa,EAAE,QAAQ,IAAI,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;IAElE,IAAI,iBAAiB,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"language.js","sourceRoot":"","sources":["../../src/util/language.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,cAAc,EAAkB,MAAM,iBAAiB,CAAC;AAkBjE,MAAM,CAAC,MAAM,WAAW,GAAG,CAC1B,aAAkD,EAClD,OAAgB,EAChB,MAAmC,EAClC,EAAE;IACH,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAEzD,IAAI,QAAQ,EAAE,CAAC;QACd,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC5B,CAAC;AACF,CAAC,CAAC;AAMF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC9B,aAAkD,EAClD,OAAgB,EACK,EAAE;IACvB,MAAM,iBAAiB,GACtB,aAAa,EAAE,QAAQ,IAAI,OAAO,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;IAElE,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACxB,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,OAAO,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,MAAM,gBAAgB,GAAG,CAAC,iBAA4C,EAAE,EAAE;IACzE,IAAI,CAAC;QACJ,OAAO,cAAc,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,+BAA+B,iBAAiB,EAAE,CAAC,CAAC;QAClE,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;AACF,CAAC,CAAC"}
|
|
@@ -11,7 +11,7 @@ declare class WidgetFactory {
|
|
|
11
11
|
get i18n(): Ti18n;
|
|
12
12
|
createWidgets(containers: Element[], renderOptions: ProcaptchaRenderOptions, isWeb2?: boolean, invisible?: boolean): Promise<Root[]>;
|
|
13
13
|
createWidget(container: Element, renderOptions: ProcaptchaRenderOptions, callbacks: Callbacks, isWeb2?: boolean, invisible?: boolean): Promise<Root>;
|
|
14
|
-
protected getCaptchaRenderer(): Promise<CaptchaRenderer>;
|
|
14
|
+
protected getCaptchaRenderer(language?: string): Promise<CaptchaRenderer>;
|
|
15
15
|
protected createCaptchaRenderer(): Promise<CaptchaRenderer>;
|
|
16
16
|
}
|
|
17
17
|
export { WidgetFactory };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widgetFactory.d.ts","sourceRoot":"","sources":["../../src/util/widgetFactory.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAK7C,OAAO,KAAK,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAMzE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"widgetFactory.d.ts","sourceRoot":"","sources":["../../src/util/widgetFactory.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAK7C,OAAO,KAAK,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAMzE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAEpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,cAAM,aAAa;IAKjB,OAAO,CAAC,QAAQ,CAAC,mBAAmB;IAJrC,OAAO,CAAC,eAAe,CAAgC;IACvD,OAAO,CAAC,KAAK,CAAsB;gBAGjB,mBAAmB,EAAE,mBAAmB;IAG1D,IAAI,IAAI,IAAI,KAAK,CAKhB;IAEY,aAAa,CACzB,UAAU,EAAE,OAAO,EAAE,EACrB,aAAa,EAAE,uBAAuB,EACtC,MAAM,UAAO,EACb,SAAS,UAAQ,GACf,OAAO,CAAC,IAAI,EAAE,CAAC;IAgBL,YAAY,CACxB,SAAS,EAAE,OAAO,EAClB,aAAa,EAAE,uBAAuB,EACtC,SAAS,EAAE,SAAS,EACpB,MAAM,UAAO,EACb,SAAS,UAAQ,GACf,OAAO,CAAC,IAAI,CAAC;cA2DA,kBAAkB,CACjC,QAAQ,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,eAAe,CAAC;cAiBX,qBAAqB,IAAI,OAAO,CAAC,eAAe,CAAC;CAMjE;AAED,OAAO,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { loadI18next } from "@prosopo/locale";
|
|
2
2
|
import { getDefaultCallbacks, setUserCallbacks } from "@prosopo/procaptcha-common";
|
|
3
3
|
import { lightTheme, darkTheme, createWidgetSkeleton } from "@prosopo/widget-skeleton";
|
|
4
|
+
import { resolveLanguage } from "./language.js";
|
|
4
5
|
class WidgetFactory {
|
|
5
6
|
constructor(widgetThemeResolver) {
|
|
6
7
|
this.widgetThemeResolver = widgetThemeResolver;
|
|
@@ -50,7 +51,8 @@ class WidgetFactory {
|
|
|
50
51
|
widgetInteractiveArea = widgetResult.widgetInteractiveArea;
|
|
51
52
|
widgetContainer = widgetResult.webComponent;
|
|
52
53
|
}
|
|
53
|
-
const
|
|
54
|
+
const language = resolveLanguage(renderOptions, container);
|
|
55
|
+
const captchaRenderer = await this.getCaptchaRenderer(language);
|
|
54
56
|
const captchaRoot = captchaRenderer.renderCaptcha(
|
|
55
57
|
{
|
|
56
58
|
identifierPrefix: "procaptcha-",
|
|
@@ -68,9 +70,11 @@ class WidgetFactory {
|
|
|
68
70
|
);
|
|
69
71
|
return captchaRoot;
|
|
70
72
|
}
|
|
71
|
-
async getCaptchaRenderer() {
|
|
73
|
+
async getCaptchaRenderer(language) {
|
|
72
74
|
if (this._i18n === null) {
|
|
73
|
-
this._i18n = await loadI18next(false);
|
|
75
|
+
this._i18n = await loadI18next(false, language);
|
|
76
|
+
} else if (language && this._i18n.language !== language) {
|
|
77
|
+
await this._i18n.changeLanguage(language);
|
|
74
78
|
}
|
|
75
79
|
if (this.captchaRenderer === null) {
|
|
76
80
|
this.captchaRenderer = await this.createCaptchaRenderer();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"widgetFactory.js","sourceRoot":"","sources":["../../src/util/widgetFactory.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,OAAO,EACN,mBAAmB,EACnB,gBAAgB,GAChB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EACN,oBAAoB,EACpB,SAAS,EACT,UAAU,GACV,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"widgetFactory.js","sourceRoot":"","sources":["../../src/util/widgetFactory.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@prosopo/procaptcha-bundle",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.35",
|
|
4
4
|
"author": "PROSOPO LIMITED <info@prosopo.io>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"browserslist": ["> 0.5%, last 2 versions, not dead"],
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@prosopo/dotenv": "3.0.49",
|
|
43
|
-
"@prosopo/locale": "3.2.
|
|
44
|
-
"@prosopo/procaptcha-common": "2.11.
|
|
45
|
-
"@prosopo/procaptcha-frictionless": "2.12.
|
|
46
|
-
"@prosopo/types": "4.9.
|
|
43
|
+
"@prosopo/locale": "3.2.7",
|
|
44
|
+
"@prosopo/procaptcha-common": "2.11.13",
|
|
45
|
+
"@prosopo/procaptcha-frictionless": "2.12.16",
|
|
46
|
+
"@prosopo/types": "4.9.9",
|
|
47
47
|
"@prosopo/util": "3.3.4",
|
|
48
48
|
"@prosopo/widget-skeleton": "2.8.4",
|
|
49
49
|
"dotenv": "16.4.5",
|
package/src/util/language.ts
CHANGED
|
@@ -35,12 +35,29 @@ export const setLanguage = (
|
|
|
35
35
|
element: Element,
|
|
36
36
|
config: ProcaptchaClientConfigInput,
|
|
37
37
|
) => {
|
|
38
|
+
const resolved = resolveLanguage(renderOptions, element);
|
|
39
|
+
|
|
40
|
+
if (resolved) {
|
|
41
|
+
config.language = resolved;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Resolves the site-owner language before an i18n singleton has been created,
|
|
46
|
+
// so the widget can boot i18n with the correct language on first init instead
|
|
47
|
+
// of having to run a post-mount changeLanguage() effect. Returning `undefined`
|
|
48
|
+
// preserves the existing "fall back to browser detection" behaviour.
|
|
49
|
+
export const resolveLanguage = (
|
|
50
|
+
renderOptions: ProcaptchaRenderOptions | undefined,
|
|
51
|
+
element: Element,
|
|
52
|
+
): string | undefined => {
|
|
38
53
|
const languageAttribute =
|
|
39
54
|
renderOptions?.language || element.getAttribute("data-language");
|
|
40
55
|
|
|
41
|
-
if (languageAttribute) {
|
|
42
|
-
|
|
56
|
+
if (!languageAttribute) {
|
|
57
|
+
return undefined;
|
|
43
58
|
}
|
|
59
|
+
|
|
60
|
+
return validateLanguage(languageAttribute);
|
|
44
61
|
};
|
|
45
62
|
|
|
46
63
|
const validateLanguage = (languageAttribute: string | typeof Languages) => {
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from "@prosopo/widget-skeleton";
|
|
27
27
|
import type { Root } from "react-dom/client";
|
|
28
28
|
import type { CaptchaRenderer } from "./captcha/captchaRenderer.js";
|
|
29
|
+
import { resolveLanguage } from "./language.js";
|
|
29
30
|
import type { WidgetThemeResolver } from "./widgetThemeResolver.js";
|
|
30
31
|
|
|
31
32
|
class WidgetFactory {
|
|
@@ -99,9 +100,16 @@ class WidgetFactory {
|
|
|
99
100
|
widgetContainer = widgetResult.webComponent;
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
// Resolve the site-owner language BEFORE lazy-loading the renderer so
|
|
104
|
+
// i18n can boot (or reconcile) with the correct language on first init,
|
|
105
|
+
// rather than starting in the browser-detected language and swapping to
|
|
106
|
+
// the site-owner language via a post-mount effect (which caused mixed-
|
|
107
|
+
// language flashes visible to end users).
|
|
108
|
+
const language = resolveLanguage(renderOptions, container);
|
|
109
|
+
|
|
102
110
|
// all the captcha-rendering logic is lazy-loaded, to avoid react & zod delay the initial widget creation.
|
|
103
111
|
|
|
104
|
-
const captchaRenderer = await this.getCaptchaRenderer();
|
|
112
|
+
const captchaRenderer = await this.getCaptchaRenderer(language);
|
|
105
113
|
|
|
106
114
|
const captchaRoot = captchaRenderer.renderCaptcha(
|
|
107
115
|
{
|
|
@@ -122,9 +130,16 @@ class WidgetFactory {
|
|
|
122
130
|
return captchaRoot;
|
|
123
131
|
}
|
|
124
132
|
|
|
125
|
-
protected async getCaptchaRenderer(
|
|
133
|
+
protected async getCaptchaRenderer(
|
|
134
|
+
language?: string,
|
|
135
|
+
): Promise<CaptchaRenderer> {
|
|
126
136
|
if (this._i18n === null) {
|
|
127
|
-
this._i18n = await loadI18next(false);
|
|
137
|
+
this._i18n = await loadI18next(false, language);
|
|
138
|
+
} else if (language && this._i18n.language !== language) {
|
|
139
|
+
// A subsequent widget on the same page requested a different
|
|
140
|
+
// language than the cached singleton — reconcile before rendering
|
|
141
|
+
// so all widgets on the page share one consistent language state.
|
|
142
|
+
await this._i18n.changeLanguage(language);
|
|
128
143
|
}
|
|
129
144
|
|
|
130
145
|
if (this.captchaRenderer === null) {
|