Code Monkey home page Code Monkey logo

email_validator's Introduction

EmailValidator

Gem Version Build Status Code Climate Test Coverage

An email validator for Rails 3+.

Supports RFC-2822-compliant and RFC-5321-compliant email validation using RFC-3696 validation.

Formerly found at: https://github.com/balexand/email_validator

Validation philosophy

The default validation provided by this gem (the :loose configuration option) is extremely loose. It just checks that there's an @ with something before and after it without any whitespace. See this article by David Gilbertson for an explanation of why.

We understand that many use cases require an increased level of validation. This is supported by using the :strict validation mode. Additionally, the :rfc RFC-compliant mode will consider technically valid emails address as valid which may not be wanted, such as the valid user or user@somehost addresses. These would be valid in :rfc mode but not valid in :loose or :strict.

Installation

Add to your Gemfile:

gem 'email_validator'

Run:

bundle install

Usage

Add the following to your model:

validates :my_email_attribute, email: true

You may wish to allow domains without a FQDN, like user@somehost. While this is technically a valid address, it is uncommon to consider such address valid. We will consider them valid by default with the :loose checking. Disallowed by setting require_fqdn: true or by enabling :strict checking:

validates :my_email_attribute, email: {mode: :strict, require_fqdn: true}

You can also limit to a single domain (e.g: you have separate User and AdminUser models and want to ensure that AdminUser emails are on a specific domain):

validates :my_email_attribute, email: {domain: 'example.com'}

Configuration

Default configuration can be overridden by setting options in config/initializers/email_validator.rb:

if defined?(EmailValidator)
  # To completely override the defaults
  EmailValidator.default_options = {
    allow_nil: false,
    domain: nil,
    require_fqdn: nil,
    mode: :loose
  }

  # or just a few options
  EmailValidator.default_options.merge!({ domain: 'mydomain.com' })
end

Loose mode

This it the default validation mode of this gem. It is intentionally extremely loose (see the Validation Philosophy section above. It just checks that there's an @ with something before and after it without any whitespace.

Strict mode

Enabling :strict checking will check for a "normal" email format that would be expected in most common everyday usage. Strict mode basically checks for a properly sized and formatted mailbox label, a single "@" symbol, and a properly sized and formatted FQDN. Enabling :strict mode will also enable :require_fqdn configuration option.

Strict mode can be enabled globally by requiring email_validator/strict in your Gemfile, by setting the option in config/initializers/email_validator.rb, or by specifying the option in a specific validates call.

  • Gemfile:

    gem 'email_validator', require: 'email_validator/strict'
  • config/initializers/email_validator.rb:

    if defined?(EmailValidator)
      EmailValidator.default_options[:mode] = :strict
    end
  • validates call:

    validates :my_email_attribute, email: {mode: :strict}

RFC mode

In order to have RFC-compliant validation (according to http://www.remote.org/jochen/mail/info/chars.html), enable :rfc mode.

You can do this globally by requiring email_validator/rfc in your Gemfile, by setting the options in config/initializers/email_validator.rb, or you can do this in a specific validates call.

  • Gemfile:

    gem 'email_validator', require: 'email_validator/rfc'
  • config/initializers/email_validator.rb:

    if defined?(EmailValidator)
      EmailValidator.default_options[:mode] = :rfc
    end
  • validates call:

    validates :my_email_attribute, email: {mode: :rfc}

Validation outside a model

If you need to validate an email outside a model, you can get the regexp:

Loose/default mode

EmailValidator.valid?('[email protected]') # boolean

Requiring a FQDN

EmailValidator.valid?('narf@somehost') # boolean false
EmailValidator.invalid?('narf@somehost', require_fqdn: false) # boolean true

NB: Enabling strict mode (mode: :strict) enables require_fqdn (require_fqdn: true), overridding any require_fqdn: false while mode: :strict is set.

Requiring a specific domain

EmailValidator.valid?('[email protected]', domain: 'foo.com') # boolean false
EmailValidator.invalid?('[email protected]', domain: 'foo.com') # boolean true

Strict mode

EmailValidator.regexp(mode: :strict) # returns the regex
EmailValidator.valid?('[email protected]', mode: :strict) # boolean

RFC mode

EmailValidator.regexp(mode: :rfc) # returns the regex
EmailValidator.valid?('[email protected]', mode: :rfc) # boolean

Thread safety

This gem is thread safe, with one caveat: EmailValidator.default_options must be configured before use in a multi-threaded environment. If you configure default_options in a Rails initializer file, then you're good to go since initializers are run before worker threads are spawned.

Alternative gems

Do you prefer a different email validation gem? If so, open an issue with a brief explanation of how it differs from this gem. I'll add a link to it in this README.

Maintainers

All thanks is given to Brian Alexander (balexand) for is initial work on this gem.

Currently maintained by:

email_validator's People

Contributors

balexand avatar cluesque avatar delphaber avatar dependabot[bot] avatar dmytrostepaniuk avatar f1sherman avatar gucki avatar kachick avatar karlwilbur avatar kerolloz avatar kida001 avatar msands avatar nageshlop avatar olleolleolle avatar raventid avatar strivedi183 avatar titeiko avatar yassenb avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

email_validator's Issues

Error in rails 3.2.14

in Gemfile:

gem 'email_validator', git: '[email protected]:balexand/email_validator.git'

in model:

validates :email, email: true

Error:

Exception encountered: #<ArgumentError: Unknown validator: 'EmailValidator'>
backtrace:
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.14/lib/active_model/validations/validates.rb:96:in `rescue in block in validates'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.14/lib/active_model/validations/validates.rb:93:in `block in validates'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.14/lib/active_model/validations/validates.rb:90:in `each'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activemodel-3.2.14/lib/active_model/validations/validates.rb:90:in `validates'
/Users/mzhukov/Work/RoR/libapp/app/models/reader.rb:4:in `<class:Reader>'
/Users/mzhukov/Work/RoR/libapp/app/models/reader.rb:1:in `<top (required)>'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in `require'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in `block in require'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:236:in `load_dependency'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in `require'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:359:in `require_or_load'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:502:in `load_missing_constant'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:192:in `block in const_missing'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:190:in `each'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:190:in `const_missing'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/inflector/methods.rb:230:in `block in constantize'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/inflector/methods.rb:229:in `each'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/inflector/methods.rb:229:in `constantize'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/inflector/methods.rb:260:in `safe_constantize'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/core_ext/string/inflections.rb:66:in `safe_constantize'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.14/lib/action_controller/metal/params_wrapper.rb:152:in `_default_wrap_model'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.14/lib/action_controller/metal/params_wrapper.rb:169:in `_set_wrapper_defaults'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.14/lib/action_controller/metal/params_wrapper.rb:133:in `inherited'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.14/lib/abstract_controller/railties/routes_helpers.rb:7:in `block (2 levels) in with'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/actionpack-3.2.14/lib/action_controller/railties/paths.rb:7:in `block (2 levels) in with'
/Users/mzhukov/Work/RoR/libapp/app/controllers/readers_controller.rb:1:in `<top (required)>'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in `require'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in `block in require'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:236:in `load_dependency'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:251:in `require'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:359:in `require_or_load'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:502:in `load_missing_constant'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:192:in `block in const_missing'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:190:in `each'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:190:in `const_missing'
/Users/mzhukov/Work/RoR/libapp/spec/controllers/readers_controller_spec.rb:3:in `<top (required)>'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:245:in `load'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:245:in `block in load'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:236:in `load_dependency'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/activesupport-3.2.14/lib/active_support/dependencies.rb:245:in `load'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.12.2/lib/rspec/core/configuration.rb:789:in `block in load_spec_files'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.12.2/lib/rspec/core/configuration.rb:789:in `each'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.12.2/lib/rspec/core/configuration.rb:789:in `load_spec_files'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/rspec-core-2.12.2/lib/rspec/core/command_line.rb:22:in `run'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/test_framework/rspec.rb:11:in `run_tests'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/run_strategy/forking.rb:13:in `block in run'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/forker.rb:21:in `block in initialize'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/forker.rb:18:in `fork'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/forker.rb:18:in `initialize'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/run_strategy/forking.rb:9:in `new'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/run_strategy/forking.rb:9:in `run'
/Users/mzhukov/.rvm/gems/ruby-2.0.0-p0/gems/spork-1.0.0rc4/lib/spork/server.rb:49:in `run'
/Users/mzhukov/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/drb/drb.rb:1588:in `perform_without_block'
/Users/mzhukov/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/drb/drb.rb:1548:in `perform'
/Users/mzhukov/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/drb/drb.rb:1626:in `block (2 levels) in main_loop'
/Users/mzhukov/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/drb/drb.rb:1622:in `loop'
/Users/mzhukov/.rvm/rubies/ruby-2.0.0-p0/lib/ruby/2.0.0/drb/drb.rb:1622:in `block in main_loop'

.tech domains

Using the gem as it is (not on strict mode), it appears that .tech domains are not allowed and appear as invalid during validation.

Allow blanks

Would it be possible to add an allow_blank configuration option that would treat "" as a valid email?

I see that it's possible to do validates :attribute, email: { allow_nil: true}, but for consistency with other gems like phonelib it would be nice if email_validator accepted both "" and nil as valid.

Alternative gem: validates_email_format_of

Shouldn't test.1#@mailinator.com fail ?

Hey, I am using email_validator in my application and according to the documentation , '#' isn't allowed in strict mode. Somehow though test.1#@mailinator.com passes the validation.

TravisCI Builds are failing for ppc64le+ruby 2.4

With the introduction of testing on ppc64le (added in PR #69), while building on TravisCI, we are seeing that Bundler will sometimes pull in activerecord > 5, which should not happen. This is not consistent.

Here is an example of failures for both 2.4.7 and 2.4.10
Build number 153: https://travis-ci.com/github/K-and-R/email_validator/builds/222180216

Yet here, with only a change to the README, only 2.4.10 gets activerecord > 5. This seems to be a bug in TravisCI.
Build number 154: https://travis-ci.com/github/K-and-R/email_validator/builds/222703882

I would expect that Bundler behave in a consistent manner across builds for the same Ruby version.

I am going to continue to monitor this. I will also try to find time to research what the cause may be. Right now, I am considering this a low priority since it doesn't impact the actual gem functionality.

(cc: @nageshlop)

Semicolon and emails with not tld in email addresses in version 2.0.1

In version 2.0.1: foo@example comes back valid
In versions 1.6.0 and 2.0.1: foo;@example.com comes back valid, but is invalid in version 1.4.0

Example from my specs:

User validations should not allow :email to be ‹"foo"›, ‹"foo@"›, ‹"foo@example"›, ‹"[email protected]"›, or ‹"example.com"›
     Failure/Error:
       is_expected.not_to allow_values(
         "foo",
         "foo@",
         "foo@example",
         "[email protected]",
         "example.com",
       ).for(:email)
     
       After setting :email to ‹"foo@example"›, the matcher expected the User
       to be invalid, but it was valid instead.

Apostrophe in Strict Mode

According to the linked docs, apostrophes are "maybe" allowed in emails. However, personal experience shows that certain main email vendors will allow ' in the local part of an email (gmail won't, but will deliver to one).

No double dots or dots at begin or end of name part should be allowed in strict mode

As said on the page http://www.remote.org/jochen/mail/info/chars.html (strict validator is based on it as said in README):

[Dots are] allowed in email addresses. Often used for addresses with the format '[email protected]'. There is one restriction however: Two dots next to each other or a dot at the beginning or end of the local part are not allowed by RFC2822. The reason is that in RFC2822 the dot is used as a separator for tokenizing the mail address. Dots at the named locations would mean an empty token, which is not allowed. Still, there are people who use it. Some MTAs accept it, some don't.

But currently such emails are treat as good:

> EmailValidator.regexp(strict_mode: true) =~ '[email protected]'
# => 0

And I see a lot of Net::SMTPError: bad address errors in log when trying to send emails. I filtering emails from user input with strict mode.

I think taht such emails should be forbidden in strict mode. What do you think?

Rails 4 compat?

Is this gem compatible with rails 4?
rails new emailtest
cd emailtest
rails -v #Rails 4.0.2
add gem 'email-validator' to Gemfile
bundle install
rails g scaffold User email:string
add to user.rb: validates :email, email: true
rake db:migrate
rails s

error at localhost:3000/users
undefined method `new' for EmailValidator:Module
the line highlighted is in user.rb:
validates :email, email: true

Active Model referenced but not required?

In line 2 where you define EmailValidator as a subclass of ActiveModel, I get an error "uninitialized constant ActiveModel (NameError)" - I have a very lean application and removed ActiveModel from the project. I think this is working for other people because it's using the ActiveModel that other gems have required. Just doing a require 'active_model' before the class definition should fix this.

IDN does not work?

http://ru.wikipedia.org/wiki/IDN

It seems email_validator does not consider emails like "user@domain.рф" as valid email addresses.

So, in model:

  validates :email, :email => true, :uniqueness => true

and then in console:

[44] studium »  u.valid? 
  User Exists (0.8ms)  SELECT  1 AS one FROM "users"  WHERE ("users"."email" = '[email protected]' AND "users"."id" != 18) LIMIT 1
=> true
[45] studium »  u.email = 'user@domain.рф' 
=> "user@domain.рф"
[46] studium »  u.valid?
  User Exists (0.7ms)  SELECT  1 AS one FROM "users"  WHERE ("users"."email" = 'user@domain.рф' AND "users"."id" != 18) LIMIT 1
  User Exists (0.5ms)  SELECT  1 AS one FROM "users"  WHERE ("users"."email" = 'user@domain.рф' AND "users"."id" != 18) LIMIT 1
=> false
[47] studium »  u.errors.full_messages
=> [
  [0] "Email имеет неверное значение"
]

validation runs even when email is blank

Right now we have to split out validations to avoid 2 error messages. Consider the following:

validates :email, presence: true, uniqueness: true, email: true

On a blank email submission, this will generate ["Email is blank", "Email is invalid"] for the error messages. Creates a bit of confusion and generally isn't desirable for users. To avoid this, we have to split it out into 2 validations.

validates :email, presence: true, uniqueness: true
validates :email, email: true, if: :email? # split out in case email is blank

Any chance we could add some smarts to only run the validation if email is present? I guess we could also drop the presence: true specifier, but then the error message won't be quite accurate ("blank" is more accurate than "invalid")

test@ru -valid?

The validator says that there is no problem with this email. Is this a bug?

Rails 6 support

After we upgraded to Rails 6, we noticed that email validation stopped working silently for email input like: base@example :(

Alternative gem: email_verifier

Hi 👋
Just found out that there is a gem that allows to not only be sure that email domain exists, but even such email identifier is real in that domain (like email ping or something) 🤔

Alternative gem: email_address

Hi 👋 ,

We've been using this gem for a while, then we started getting some "hackerish" invalid emails in our database as a result we had to look for alternative validations. At first we used the Ruby built-in regex URI::MailTo::EMAIL_REGEXP but this one has some use cases where it does not work with a valid email.

Looking at the source code I am under the impression this gem's regex is very simplistic "no spaces" plus "@ symbol" followed by "no spaces". That may result in invalid emails, also allows for stuff like <script>alert()</script>@domain.com.

I would like to promote this alternative https://github.com/afair/email_address that includes a Rails validator and has some other goodies like emails types, hashing, etc.

Thanks for sharing your project 💜

Security Warning

I think it would be prudent to include a security warning in your readme. This validation philosophy could leave your users open to XSS attacks, depending on their use case.

The regexp being used for validation will allow javascript email addresses.

False positive email validations

After I updated from version 1.6.0 to 2.0.1 I got some false positives on the email validation. I have a test on my application that doesn't let an object with an invalid email be saved.
Previously with the version 1.6.0 the tests were running as expected (object wasn't being created). The email that I use for this test is "b@man".
But now, the version 2.0.1 says this is a valid email, which makes my test fails and also, this is not a valid email, so this is an issue with the gem.

I did some other tests and these are the results:
Version 1.6.0
[STAG]US:(ec)[1] pry(main)> EmailValidator.valid?('b@man')
=> false
[STAG]US:(ec)[2] pry(main)> EmailValidator.valid?('email@[email protected]')
=> false

Version 2.0.1
USOps:(ec)[31] pry(main)> EmailValidator.valid?('b@man')
=> true
USOps:(ec)[32] pry(main)> EmailValidator.valid?('email@[email protected]')
=> true

More disposable domains

Hi there! First of all, thanks for the great gem!

I've found a couple more of popular disposable email domains and it would be nice to add them to the list:

10minutemail.net

  • xcoxc.com
  • jiooq.com
  • jeoce.com
  • zcrcd.com

temp-mail.org

  • tsclip.com
  • runchet.com
  • sceath.com
  • about27.com
  • nifect.com
  • lockaya.com
  • steamoh.com
  • sinyago.com

10minutemail.com

  • kvhrs.com
  • kvhrr.com
  • kvhrw.com
  • bvhrs.com
  • bvhrk.com
  • nthrl.com
  • nthrw.com

minuteinbox.com

  • ironflys.com

10minutesemail.net

  • 10minutesemail.net
  • email.edu.pl
  • edu.email.edu.pl

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.