=> {
273 | return new Promise((resolve, reject) => {
274 | if (this.state.rendered) {
275 | const response = this._getResponseRecaptcha();
276 | return resolve(response);
277 | }
278 | reject(new Error('This recaptcha instance did not render yet.'));
279 | });
280 | };
281 |
282 | render = () => {
283 | const container = (
284 | (this.container = e)}
289 | />
290 | );
291 |
292 | return this.props.children
293 | ? this.props.children({
294 | renderExplicitly: this.renderExplicitly,
295 | reset: this.reset,
296 | execute: this.execute,
297 | getResponse: this.getResponse,
298 | recaptchaComponent: container
299 | })
300 | : container;
301 | };
302 | }
303 |
304 | export default Reaptcha;
305 |
--------------------------------------------------------------------------------
/lib/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reaptcha",
3 | "version": "1.12.1",
4 | "description": "Google reCAPTCHA for React",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/sarneeh/reaptcha"
8 | },
9 | "license": "MIT",
10 | "author": "Jakub Sarnowski ",
11 | "files": [
12 | "dist",
13 | "index.d.ts"
14 | ],
15 | "source": "./index.tsx",
16 | "main": "dist/index.js",
17 | "module": "dist/index.esm.js",
18 | "unpkg": "dist/index.umd.js",
19 | "typings": "./index.d.ts",
20 | "scripts": {
21 | "dev": "npm run build -- -w",
22 | "build": "rimraf dist && microbundle --jsx React.createElement"
23 | },
24 | "peerDependencies": {
25 | "react": "^16 || ^17 || ^18"
26 | },
27 | "devDependencies": {
28 | "microbundle": "^0.14.2",
29 | "rimraf": "^3.0.2"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/lib/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.common.json",
3 | "compilerOptions": {
4 | "noEmit": true
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/lib/utils/injectScript.test.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable no-global-assign */
2 |
3 | import test from 'ava';
4 | import sinon from 'sinon';
5 | import jsdom from 'jsdom-global';
6 |
7 | import injectScript from './injectScript';
8 |
9 | jsdom();
10 |
11 | test.serial('should inject script', t => {
12 | const scriptObj = {} as HTMLScriptElement;
13 |
14 | const appendChildSpy = sinon.spy();
15 | const createElementStub = sinon
16 | .stub()
17 | .withArgs('script')
18 | .returns(scriptObj);
19 |
20 | sinon.stub(document, 'createElement').get(() => createElementStub);
21 | sinon.stub(document.head, 'appendChild').get(() => appendChildSpy);
22 |
23 | injectScript('src');
24 |
25 | t.true(scriptObj.async);
26 | t.true(scriptObj.async);
27 | t.is(scriptObj.src, 'src');
28 | t.true(appendChildSpy.calledOnceWith(scriptObj));
29 | });
30 |
31 | test.serial('should not throw when document head not present', t => {
32 | const createElementStub = sinon
33 | .stub()
34 | .withArgs('script')
35 | .returns({});
36 |
37 | sinon.stub(document, 'createElement').get(() => createElementStub);
38 | sinon.stub(document, 'head').get(() => null);
39 |
40 | t.notThrows(() => injectScript('src'));
41 | });
42 |
--------------------------------------------------------------------------------
/lib/utils/injectScript.ts:
--------------------------------------------------------------------------------
1 | export default (scriptSrc: string): void => {
2 | const script = document.createElement('script');
3 |
4 | script.async = true;
5 | script.defer = true;
6 | script.src = scriptSrc;
7 |
8 | if (document.head) {
9 | document.head.appendChild(script);
10 | }
11 | };
12 |
--------------------------------------------------------------------------------
/lib/utils/isAnyScriptPresent.test.ts:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import sinon from 'sinon';
3 | import jsdom from 'jsdom-global';
4 |
5 | import isAnyScriptPresent from './isAnyScriptPresent';
6 |
7 | jsdom();
8 |
9 | sinon
10 | .stub(document, 'scripts')
11 | .get(() => [
12 | { src: 'https://first.url?render=explicit' },
13 | { src: 'https://second.url?hl=en' },
14 | { src: 'https://third.url?hl=en' }
15 | ]);
16 |
17 | test('should return true', t => {
18 | t.true(isAnyScriptPresent(/https:\/\/second.url.*/));
19 | });
20 |
21 | test('should return false', t => {
22 | t.false(isAnyScriptPresent(/https:\/\/unknown.url.*/));
23 | });
24 |
--------------------------------------------------------------------------------
/lib/utils/isAnyScriptPresent.ts:
--------------------------------------------------------------------------------
1 | export default (regex: RegExp): boolean =>
2 | Array.from(document.scripts).reduce(
3 | (isPresent, script) => (isPresent ? isPresent : regex.test(script.src)),
4 | false
5 | );
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "reaptcha-monorepo",
3 | "private": true,
4 | "workspaces": [
5 | "lib",
6 | "example"
7 | ],
8 | "scripts": {
9 | "lint": "eslint .",
10 | "test": "ava --serial 'lib/**/*.test.{ts,tsx}'",
11 | "test:coverage": "c8 --reporter lcovonly --clean --100 npm test",
12 | "dev": "turbo run dev --parallel --no-cache",
13 | "build": "NODE_ENV=production turbo run build",
14 | "version": "changeset version",
15 | "publish": "npm run build && changeset publish"
16 | },
17 | "devDependencies": {
18 | "@changesets/cli": "^2.21.0",
19 | "@commitlint/cli": "^8.3.5",
20 | "@commitlint/config-conventional": "^8.3.4",
21 | "@types/enzyme": "^3.10.11",
22 | "@types/jsdom-global": "^3.0.2",
23 | "@types/node": "^17.0.21",
24 | "@types/react": "^18.0.12",
25 | "@types/react-dom": "^18.0.5",
26 | "@types/sinon": "^10.0.11",
27 | "@typescript-eslint/eslint-plugin": "^5.13.0",
28 | "@typescript-eslint/parser": "^5.13.0",
29 | "@wojtekmaj/enzyme-adapter-react-17": "^0.6.7",
30 | "ava": "^4.0.1",
31 | "c8": "^7.10.0",
32 | "cz-conventional-changelog": "^3.1.0",
33 | "enzyme": "^3.11.0",
34 | "eslint": "^8.10.0",
35 | "eslint-plugin-react": "^7.29.2",
36 | "husky": "^4.2.3",
37 | "jsdom": "^16.2.0",
38 | "jsdom-global": "^3.0.2",
39 | "prettier": "^1.19.1",
40 | "pretty-quick": "^2.0.1",
41 | "sinon": "^9.0.0",
42 | "ts-node": "^10.7.0",
43 | "turbo": "^1.1.4",
44 | "typescript": "~4.5.0"
45 | },
46 | "husky": {
47 | "hooks": {
48 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
49 | "pre-commit": "pretty-quick --staged"
50 | }
51 | },
52 | "ava": {
53 | "require": [
54 | "ts-node/register"
55 | ],
56 | "extensions": [
57 | "ts",
58 | "tsx"
59 | ],
60 | "environmentVariables": {
61 | "TS_NODE_PROJECT": "./tsconfig.test.json"
62 | }
63 | },
64 | "config": {
65 | "commitizen": {
66 | "path": "cz-conventional-changelog"
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/tsconfig.common.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "esModuleInterop": true,
4 | "target": "esnext",
5 | "module": "esnext",
6 | "moduleResolution": "node",
7 | "jsx": "react",
8 | "strict": true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/tsconfig.test.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.common.json",
3 | "compilerOptions": {
4 | "target": "es2015",
5 | "module": "commonjs",
6 | "noImplicitAny": false
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turborepo.org/schema.json",
3 | "pipeline": {
4 | "lint": {},
5 | "test": {},
6 | "test:coverage": {},
7 | "dev": {
8 | "cache": false
9 | },
10 | "build": {
11 | "dependsOn": ["^build"]
12 | },
13 | "publish": {
14 | "dependsOn": ["build"]
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------