Skip to content

Commit

Permalink
feat(Recaptcha): component first commit 🤘
Browse files Browse the repository at this point in the history
  • Loading branch information
evenchange4 committed May 17, 2016
0 parents commit 55867bd
Show file tree
Hide file tree
Showing 12 changed files with 359 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# editorconfig.org
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.md]
trim_trailing_whitespace = false

[Makefile]
indent_style = tab
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# OS X crap
.DS_Store

# no log
*.log

# Node.js / npm
node_modules

# build
lib

# code coverage
.nyc_output
coverage/
6 changes: 6 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
src
.editorconfig
.nyc_output
.npmignore
.stylelintrc
coverage/
20 changes: 20 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
sudo: false
language: node_js
node_js:
- "4"
- "4.2.2"

notifications:
email: [email protected]

before_install:
# remove useless/non listed deps
- npm prune
# faster npm install
- npm set progress=false

script:
- npm run lint
- npm run test:coverage

after_success: npm run coverage
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# react-grecaptcha

## [HEAD]
> Unreleased
## [v1.0.0]
> May 17, 2016
* init commit
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2016 Michael Hsu

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# react-grecaptcha

> React.js Google reCAPTCHA v2 integration component.
[![Travis][build-badge]][build] [![Codecov Status][codecov-badge]][codecov] [![npm package][npm-badge]][npm] [![npm downloads][npm-downloads]][npm] [![license][license-badge]][license]

[![Dependency Status][dependency-badge]][dependency] [![devDependency Status][devDependency-badge]][devDependency] [![peerDependency Status][peerDependency-badge]][peerDependency]

[build-badge]: https://img.shields.io/travis/evenchange4/react-grecaptcha/master.svg?style=flat-square
[build]: https://travis-ci.org/evenchange4/react-grecaptcha

[npm-badge]: https://img.shields.io/npm/v/react-grecaptcha.svg?style=flat-square
[npm]: https://www.npmjs.org/package/react-grecaptcha

[codecov-badge]: https://img.shields.io/codecov/c/github/evenchange4/react-grecaptcha.svg?style=flat-square
[codecov]: https://codecov.io/github/evenchange4/react-grecaptcha?branch=master

[npm-downloads]: https://img.shields.io/npm/dt/react-grecaptcha.svg?style=flat-square

[license-badge]: https://img.shields.io/npm/l/react-grecaptcha.svg?style=flat-square
[license]: http:https://michaelhsu.mit-license.org/

[dependency-badge]: https://david-dm.org/evenchange4/react-grecaptcha.svg?style=flat-square
[dependency]: https://david-dm.org/evenchange4/react-grecaptcha
[devDependency-badge]: https://david-dm.org/evenchange4/react-grecaptcha/dev-status.svg?style=flat-square
[devDependency]: https://david-dm.org/evenchange4/react-grecaptcha#info=devDependencies
[peerDependency-badge]: https://david-dm.org/evenchange4/react-grecaptcha/peer-status.svg?style=flat-square
[peerDependency]: https://david-dm.org/evenchange4/react-grecaptcha#info=peerDependencies

## Feature

1. Isomorphic support. (Only render on client side.)
2. Lazy load scripts for routing.
3. Automatically render the reCAPTCHA widget.
4. I18n support.
- https://developers.google.com/recaptcha/docs/language

## Installation

```console
$ npm install react-grecaptcha --save
```

## Usage

```js
const verifyCallback = response => console.log(response);
const expiredCallback = () => {...};

<Recaptcha
sitekey={process.env.RECAPTCHA_SITE_KEY}
callback={verifyCallback}
expiredCallback={expiredCallback}
locale="zh-TW"
/>
```

## API

```
window.grecaptcha.reset();
```

## Test

```
$ npm run test:watch
```

---

## CONTRIBUTING

* ⇄ Pull requests and ★ Stars are always welcome.
* For bugs and feature requests, please create an issue.
* Pull requests must be accompanied by passing automated tests (`$ npm test`).

## [CHANGELOG](CHANGELOG.md)

## [LICENSE](LICENSE)

MIT: [http:https://michaelhsu.mit-license.org](http:https://michaelhsu.mit-license.org)
99 changes: 99 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
"name": "react-grecaptcha",
"version": "0.0.0",
"description": "React.js Google reCAPTCHA v2 integration component.",
"author": "Michael Hsu",
"license": "MIT",
"bugs": {
"url": "https://github.com/evenchange4/react-grecaptcha/issues"
},
"homepage": "https://github.com/evenchange4/react-grecaptcha#readme",
"repository": {
"type": "git",
"url": "https://github.com/evenchange4/react-grecaptcha.git"
},
"main": "lib/index.js",
"files": [
"lib",
"src",
"test"
],
"keywords": [
"react",
"lifecycle",
"componentDidMount",
"HOC",
"decorator"
],
"scripts": {
"clean": "rm -rf lib",
"prebuild": "npm run clean",
"build": "NODE_ENV=production babel src --out-dir lib",
"test": "ava",
"test:watch": "npm test -- --watch",
"test:coverage": "nyc npm run test",
"coverage": "nyc report --reporter=lcov && codecov",
"lint:js": "eslint --ignore-path .gitignore .",
"lint": "npm run lint:js",
"prepublish": "npm run build"
},
"peerDependencies": {
"react": ">= 0.14.0"
},
"dependencies": {
"classnames": "^2.2.5"
},
"devDependencies": {
"ava": "^0.14.0",
"babel-cli": "^6.8.0",
"babel-plugin-add-module-exports": "^0.2.0",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-stage-0": "^6.5.0",
"babel-register": "^6.8.0",
"codecov": "^1.0.1",
"enzyme": "^2.2.0",
"eslint": "^2.7.0",
"jsdom": "^9.0.0",
"lint-config-m": "^1.1.1",
"nyc": "^6.4.0",
"react": "^15.0.0",
"react-addons-test-utils": "^15.0.0",
"react-dom": "^15.0.0"
},
"babel": {
"presets": [
"react",
"es2015",
"stage-0"
],
"plugins": [
"add-module-exports"
]
},
"ava": {
"files": [
"test/**/*.test.js"
],
"failFast": true,
"verbose": true,
"require": [
"babel-register",
"./test/.setup-browser-env.js"
],
"babel": "inherit"
},
"nyc": {
"exclude": [
"test/**"
],
"include": [
"src/**"
]
},
"eslintConfig": {
"extends": [
"./node_modules/lint-config-m/eslint.js"
]
}
}
60 changes: 60 additions & 0 deletions src/Recaptcha.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { default as React, PropTypes } from 'react';
import c from 'classnames';

// Constants
const ID = '_grecaptcha.element.id';
const CALLBACK_NAME = '_grecaptcha.data-callback';
const EXPIRED_CALLBACK_NAME = '_grecaptcha.data-expired-callback';

class Recaptcha extends React.Component {
static propTypes = {
// Required
sitekey: PropTypes.string.isRequired,
callback: PropTypes.func.isRequired,
expiredCallback: PropTypes.func.isRequired,

// Options
className: PropTypes.string,
locale: PropTypes.string,
}

static defaultProps = {
locale: 'en'
}

componentDidMount() {
const { locale, callback, expiredCallback } = this.props;

// 1. Async lazy load
const script = document.createElement('script');
script.id = ID;
script.src = `https://www.google.com/recaptcha/api.js?hl=${locale}`;
script.async = true;
script.defer = true;
document.body.appendChild(script);

// 2. Expose callback function to window object
window[CALLBACK_NAME] = callback;
window[EXPIRED_CALLBACK_NAME] = () => expiredCallback;
}

componentWillUnmount() {
document.getElementById(ID).remove();
}

render() {
const { className, sitekey, ...otherProps } = this.props;

return (
<div
{...otherProps}
className={c('g-recaptcha', className)}
data-sitekey={sitekey}
data-callback={CALLBACK_NAME}
data-expired-callback={EXPIRED_CALLBACK_NAME}
/>
);
}
}

export default Recaptcha;
3 changes: 3 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import Recaptcha from './Recaptcha';

export default Recaptcha;
7 changes: 7 additions & 0 deletions test/.setup-browser-env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/**
* Setup jsdom. [ref: https://goo.gl/LiNh3p]
*/

global.document = require('jsdom').jsdom('<body></body>');
global.window = document.defaultView;
global.navigator = window.navigator;
21 changes: 21 additions & 0 deletions test/Recaptcha.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';
import test from 'ava';
import { shallow } from 'enzyme';
import Recaptcha from '../src/Recaptcha';

const emptyFunction = () => {};

test('should render with `g-recaptcha` className', t => {
const wrapper = shallow(
<Recaptcha
sitekey="6Ldx8R4TAAAAAMB-6jJol-f-po1-Bbg0ArMGJ11L"
callback={emptyFunction}
expiredCallback={emptyFunction}
/>
);

t.is(
wrapper.find('.g-recaptcha').length,
1,
);
});

0 comments on commit 55867bd

Please sign in to comment.