├── .document ├── .editorconfig ├── .gitignore ├── .markdownlint.style.rb ├── .mdlrc ├── .rubocop.yml ├── .travis.yml ├── CHANGELOG.md ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── bin └── report-test-coverage ├── email_validator.gemspec ├── lib ├── email_validator.rb └── email_validator │ ├── rfc.rb │ └── strict.rb ├── package.json ├── spec ├── email_validator_spec.rb └── spec_helper.rb └── yarn.lock /.document: -------------------------------------------------------------------------------- 1 | README.rdoc 2 | lib/**/*.rb 3 | bin/* 4 | features/**/*.feature 5 | LICENSE 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | # Ignore paths 12 | [*.{enc,lock}] 13 | charset = unset 14 | end_of_line = unset 15 | insert_final_newline = unset 16 | trim_trailing_whitespace = unset 17 | indent_style = unset 18 | indent_size = unset 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Build artifacts 3 | *.gem 4 | *.rbc 5 | 6 | # Bundler artifacts 7 | .bundle 8 | Gemfile.lock 9 | 10 | # Development artifacts 11 | node_modules 12 | yarn-error.log 13 | yarn-debug.log* 14 | .yarn-integrity 15 | .byebug_history 16 | rdoc 17 | pkg 18 | .rspec 19 | .config 20 | .env 21 | 22 | # OS artifacts 23 | .DS_Store 24 | 25 | # IDE/Editor artifacts 26 | *.code-workspace 27 | *.tmproj 28 | tmtags 29 | *~ 30 | \#* 31 | .\#* 32 | *.swp 33 | 34 | # SimpleCov artifacts 35 | coverage 36 | 37 | -------------------------------------------------------------------------------- /.markdownlint.style.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Markdownlint style file 4 | # File syntax: Ruby (Markdownlint Style DSL) 5 | # 6 | 7 | # Refs: 8 | # Ruby version 9 | # Config: https://github.com/markdownlint/markdownlint/blob/master/docs/configuration.md 10 | # Styles: https://github.com/markdownlint/markdownlint/blob/master/docs/creating_styles.md 11 | # Rules: https://github.com/markdownlint/markdownlint/blob/master/docs/RULES.md 12 | # JS version (modeled after the Ruby version) 13 | # https://github.com/DavidAnson/markdownlint/blob/master/doc/Rules.md 14 | # 15 | # 16 | # Many of the defaults used by Markdownlint are chosen because of how renderers 17 | # interpret Markdown. The defaults are chosen for the greatest compatability and 18 | # confidence in proper rendering of the Markdown; for text-only viewing, it is 19 | # less relevant. 20 | 21 | # Enabled all rules 22 | # 23 | # This is makes many of the rules defined below, where they are just being 24 | # enabled and running with the defaults, unnecessary. They've been left in for 25 | # explanatory purposes. 26 | all 27 | 28 | # MD001 - Header levels should only increment by one level at a time 29 | rule 'MD001' 30 | 31 | # MD002 - First header should be a top level header 32 | rule 'MD002' 33 | 34 | # MD003 - Header style 35 | # Default: always use the same header style of any of the allowed header styles 36 | # 37 | # Headers should use the `#` ('atx') style headers 38 | rule 'MD003', :style => :atx 39 | 40 | # MD004 - Unordered list style 41 | # Default: always use the same character (any one of `*`,`+`,`-`) 42 | # 43 | # Do not force a single unordered list character, we should be using them to 44 | # visually indicate nested lists. Since this rule cannot support validating 45 | # our usage, we are disabling it. 46 | exclude_rule 'MD004' 47 | 48 | # MD005 - Inconsistent indentation for list items at the same level 49 | # Default: don't allow inconsistent indentation for list items 50 | rule 'MD005' 51 | 52 | # MD006 - Start bulleted lists at the beginning of the line 53 | rule 'MD006' 54 | 55 | # MD007 - Unordered list indentation 56 | # Default: 2 spaces 57 | # 58 | # Use 4 spaces because using 2 doesn't always render a sublist. 59 | rule 'MD007', :indent => 4 60 | 61 | # No rule MD008 62 | 63 | # MD009 - Trailing spaces 64 | # Default: trailing spaces not allowed 65 | rule 'MD009' 66 | 67 | # MD010 - Hard tabs 68 | # Default: hard tabs not allowed 69 | rule 'MD010' 70 | 71 | # MD011 - Reversed link syntax 72 | # Default: alert when link syntax seems to be reversed 73 | # (the `[]` and `()` are reversed) 74 | rule 'MD011' 75 | 76 | # MD012 - Multiple consecutive blank lines 77 | # Default: No multiple consecutive blank lines 78 | rule 'MD012' 79 | 80 | # MD013 - Line length 81 | # Default: Max 80 characters per line 82 | # 83 | # Set line length limit to 120 characters (default: 80 characters) 84 | rule 'MD013', :line_length => 120, :code_blocks => false 85 | 86 | # MD014 - Dollar signs used before commands without showing output 87 | # Default: No dollars signs before shell commands w/o showing shell output 88 | rule 'MD014' 89 | 90 | # No rule MD015 to MD017 91 | 92 | # MD018 - No space after hash on atx style header 93 | # Default: Must have space after header style 94 | rule 'MD018' 95 | 96 | # MD019 - Multiple spaces after hash on atx style header 97 | # Default: No multiple spaces after hash in header 98 | rule 'MD019' 99 | 100 | # MD020 - No space inside hashes on closed atx style header 101 | # Default: Must have space before closing hash in closed atx style headers 102 | # 103 | # We don't use closed ATX style headers 104 | rule 'MD020' 105 | 106 | # MD021 - Multiple spaces inside hashes on closed atx style header 107 | # Default: No multiple spaces before closing hash in closed atx style headers 108 | # 109 | # We don't use closed ATX style headers 110 | rule 'MD021' 111 | 112 | # MD022 - Headers should be surrounded by blank lines 113 | # Default: Must have a blank line above and below headers 114 | rule 'MD022' # headers should be surrounded by blank lines 115 | 116 | # MD023 - Headers must start at the beginning of the line 117 | rule 'MD023' 118 | 119 | # MD024 - Multiple headers with the same content 120 | # Default: No multiple headers with same content, no duplicate header text 121 | rule 'MD024', :allow_different_nesting => true 122 | 123 | # MD025 - Multiple top level headers in the same document 124 | # Default: The is onlt one level 1 header; it's the title of the document 125 | rule 'MD025' 126 | 127 | # MD026 - Trailing punctuation in header 128 | # Default: No trailling punctuation in headers 129 | rule 'MD026' 130 | 131 | # MD027 - Multiple spaces after blockquote symbol 132 | # Default: Only a single spaces after blockquote symbol 133 | rule 'MD027' 134 | 135 | # MD028 - Blank line inside blockquote 136 | # Default: Blockquote right next to each other must have text between them 137 | rule 'MD028' 138 | 139 | # MD029 - Ordered list item prefix 140 | # Default: 141 | # 142 | # ordered list item prefix, should be ordered 143 | rule 'MD029', :style => :ordered 144 | 145 | # MD030 - Spaces after list markers 146 | # Default: Only one space character after a list marker 147 | rule 'MD030' 148 | 149 | # MD031 - Fenced code blocks should be surrounded by blank lines 150 | # Default: Fenced code blocks ("```") must have a blank line above and below 151 | rule 'MD031' 152 | 153 | # MD032 - Lists should be surrounded by blank lines 154 | # Default: Lists must have a blank line above and below the list (not each item) 155 | rule 'MD032' 156 | 157 | # MD033 - Inline HTML 158 | # Default: No raw HTML 159 | rule 'MD033' 160 | 161 | # MD034 - Bare URL used 162 | # Default: No bare URLs 163 | rule 'MD034' 164 | 165 | # MD035 - Horizontal rule style 166 | # Default: Be consistent, use only one of `---`, `- - -`, `***`, or `* * *` 167 | # 168 | # We want to enforce `---` 169 | rule 'MD035', :style => '---' 170 | 171 | # MD036 - Emphasis used instead of a header 172 | # Default: Do not use emphasis (bold, italic, etc) as header, use actual headers 173 | rule 'MD036' 174 | 175 | # MD037 - Spaces inside emphasis markers 176 | # Default: No leading/trailing spaces inside emphasis markers 177 | rule 'MD037' 178 | 179 | # MD038 - Spaces inside code span elements 180 | # Default: No leading/trailing spaces inside code markers ("`") 181 | rule 'MD038' 182 | 183 | # MD039 - Spaces inside link text 184 | # Default: No leading/trailing spaces inside link text ("[]") 185 | rule 'MD039' 186 | 187 | # MD040 - Fenced code blocks should have a language specified 188 | # Default: Fenced code blocks ("```") must have a language specified 189 | rule 'MD040' 190 | 191 | # MD041 - First line in file should be a top level header 192 | # Default: First line in file must be a top level header 193 | rule 'MD041' 194 | 195 | # Rule MD042 to MD045, and MD047 are only supported by the JavScript version 196 | 197 | # # MD042 - No empty links 198 | # # Default: Links URLs cannot be empty; empty fragments (`#`) are still empty 199 | # rule 'MD042' 200 | 201 | # # MD043 - Required heading structure 202 | # # Default: disabled 203 | # # 204 | # # This requires headings from a predetermined list (`headings` array). 205 | # rule 'MD043' 206 | 207 | # # MD044 - Proper names should have the correct capitalization 208 | # # Default: names: nil, code_blocks: true 209 | # # 210 | # # This preforms a case-insensitive search for srtings from the `names` array. 211 | # # then checks capatilization of those strings against the element from `names` 212 | # rule 'MD044' 213 | 214 | # # MD045 - Images should have alternate text (alt text) 215 | # # Default: Alt text is required for all images 216 | # rule 'MD045' 217 | 218 | # MD046 - Code block style 219 | # Default: Always used fenced code blocks ("```") 220 | rule 'MD046' 221 | 222 | # # MD047 - Files should end with a single newline character 223 | # # Default: Requires newline at end of file 224 | # rule 'MD047' 225 | -------------------------------------------------------------------------------- /.mdlrc: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Markdownlint style file 4 | # File syntax: Ruby 5 | # 6 | # This file is used by the version of Markdownlint in the CodeClimate image: 7 | # `codeclimate/codeclimate-markdownlint` 8 | # 9 | # It can also be used by the `markdownlint` gem when run directly, outside of 10 | # CodeClimate. 11 | # 12 | 13 | style './.markdownlint.style.rb' 14 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | # The behavior of RuboCop can be controlled via the .rubocop.yml 2 | # configuration file. It makes it possible to enable/disable 3 | # certain cops (checks) and to alter their behavior if they accept 4 | # any parameters. The file can be placed either in your home 5 | # directory or in some project directory. 6 | # 7 | # RuboCop will start looking for the configuration file in the directory 8 | # where the inspected file is and continue its way up to the root directory. 9 | # 10 | # See https://github.com/rubocop-hq/rubocop/blob/master/manual/configuration.md 11 | require: 12 | - rubocop-rake 13 | - rubocop-rspec 14 | 15 | AllCops: 16 | Exclude: 17 | - 'bin/*' 18 | NewCops: enable 19 | TargetRubyVersion: 2.4 20 | 21 | Bundler/GemComment: 22 | Enabled: true 23 | 24 | Bundler/OrderedGems: 25 | TreatCommentsAsGroupSeparators: true 26 | 27 | RSpec/Capybara/FeatureMethods: 28 | Enabled: true 29 | EnabledMethods: 30 | - feature 31 | - given 32 | - background 33 | - scenario 34 | 35 | Layout/ArgumentAlignment: 36 | Enabled: true 37 | 38 | Layout/BlockAlignment: 39 | Enabled: true 40 | 41 | Layout/BlockEndNewline: 42 | Enabled: true 43 | 44 | Layout/ClassStructure: 45 | Enabled: true 46 | Categories: 47 | module_inclusion: 48 | - include 49 | - prepend 50 | - extend 51 | ExpectedOrder: 52 | - module_inclusion 53 | - constants 54 | - public_class_methods 55 | - initializer 56 | - instance_methods 57 | - protected_methods 58 | - private_methods 59 | 60 | Layout/ClosingParenthesisIndentation: 61 | Enabled: true 62 | 63 | Layout/EndOfLine: 64 | EnforcedStyle: lf 65 | 66 | Layout/EmptyLineAfterGuardClause: 67 | Enabled: false 68 | 69 | Layout/EmptyLinesAroundAttributeAccessor: 70 | Enabled: true 71 | 72 | Layout/FirstArgumentIndentation: 73 | Enabled: true 74 | 75 | Layout/FirstArrayElementIndentation: 76 | Enabled: true 77 | EnforcedStyle: consistent 78 | IndentationWidth: 2 79 | 80 | Layout/FirstHashElementIndentation: 81 | Enabled: true 82 | EnforcedStyle: consistent 83 | 84 | Layout/FirstParameterIndentation: 85 | Enabled: true 86 | EnforcedStyle: consistent 87 | 88 | Layout/HashAlignment: 89 | Enabled: true 90 | 91 | Layout/IndentationWidth: 92 | Enabled: true 93 | Width: 2 94 | 95 | Layout/LineLength: 96 | AllowHeredoc: true 97 | AllowURI: true 98 | AutoCorrect: false 99 | Max: 120 100 | URISchemes: 101 | - http 102 | - https 103 | - mysql 104 | - mysql2 105 | - postgres 106 | - postgresql 107 | 108 | Layout/MultilineArrayLineBreaks: 109 | Enabled: true 110 | 111 | Layout/MultilineBlockLayout: 112 | Enabled: true 113 | 114 | Layout/MultilineHashBraceLayout: 115 | Enabled: true 116 | 117 | Layout/MultilineHashKeyLineBreaks: 118 | Enabled: true 119 | 120 | Layout/MultilineMethodArgumentLineBreaks: 121 | Enabled: true 122 | 123 | Layout/MultilineMethodCallBraceLayout: 124 | EnforcedStyle: new_line 125 | 126 | Layout/ParameterAlignment: 127 | Enabled: true 128 | 129 | Layout/SpaceAroundMethodCallOperator: 130 | Enabled: true 131 | 132 | Lint/DeprecatedOpenSSLConstant: 133 | Enabled: true 134 | 135 | Lint/DuplicateElsifCondition: 136 | Enabled: true 137 | 138 | Lint/MixedRegexpCaptureTypes: 139 | Enabled: true 140 | 141 | Lint/RaiseException: 142 | Enabled: true 143 | 144 | Lint/StructNewOverride: 145 | Enabled: true 146 | 147 | Metrics/BlockLength: 148 | Exclude: 149 | - 'spec/**/*.rb' 150 | - '**/*.gemspec' 151 | 152 | Metrics/ClassLength: 153 | Max: 150 154 | 155 | Metrics/MethodLength: 156 | Max: 15 157 | 158 | Metrics/ModuleLength: 159 | Exclude: 160 | - 'spec/**/*.rb' 161 | 162 | RSpec/ExampleLength: 163 | Max: 10 164 | 165 | RSpec/NestedGroups: 166 | Max: 7 167 | 168 | RSpec/PredicateMatcher: 169 | Enabled: true 170 | Strict: false 171 | EnforcedStyle: inflected 172 | 173 | Style/AccessorGrouping: 174 | Enabled: true 175 | 176 | Style/Alias: 177 | EnforcedStyle: prefer_alias_method 178 | 179 | Style/ArrayCoercion: 180 | Enabled: false 181 | 182 | Style/BisectedAttrAccessor: 183 | Enabled: true 184 | 185 | Style/BlockDelimiters: 186 | Enabled: true 187 | 188 | Style/CaseLikeIf: 189 | Enabled: true 190 | 191 | Style/DoubleNegation: 192 | Enabled: false 193 | 194 | Style/ExponentialNotation: 195 | Enabled: true 196 | 197 | Style/FrozenStringLiteralComment: 198 | Enabled: false 199 | 200 | Style/HashAsLastArrayItem: 201 | Enabled: true 202 | 203 | Style/HashEachMethods: 204 | Enabled: true 205 | 206 | Style/HashLikeCase: 207 | Enabled: true 208 | 209 | Style/HashSyntax: 210 | Enabled: true 211 | EnforcedStyle: hash_rockets 212 | 213 | Style/HashTransformKeys: 214 | Enabled: true 215 | 216 | Style/HashTransformValues: 217 | Enabled: true 218 | 219 | Style/RedundantAssignment: 220 | Enabled: true 221 | 222 | Style/RedundantFetchBlock: 223 | Enabled: true 224 | 225 | Style/RedundantFileExtensionInRequire: 226 | Enabled: true 227 | 228 | Style/RedundantRegexpCharacterClass: 229 | Enabled: true 230 | 231 | Style/RedundantRegexpEscape: 232 | Enabled: true 233 | 234 | Style/SignalException: 235 | EnforcedStyle: semantic 236 | 237 | Style/SlicingWithRange: 238 | Enabled: true 239 | 240 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | arch: 3 | - amd64 4 | - ppc64le 5 | 6 | rvm: 7 | - 2.5.0 8 | - 2.5.8 9 | - 2.6.0 10 | - 2.6.10 11 | - 2.7.0 12 | - 2.7.6 13 | - 3.0.1 14 | - 3.0.4 15 | - 3.1.0 16 | - 3.1.2 17 | - ruby-head 18 | - jruby-head 19 | notifications: 20 | recipients: 21 | - karl@kandrsoftware.com 22 | branches: 23 | only: 24 | - master 25 | - develop 26 | before_install: 27 | # ensure that we are building/testing againt the newest depencency versions 28 | - rm -f Gemfile.lock 29 | bundler_args: --without development 30 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | This file is used to list changes made in `email_validator`. 4 | 5 | All notable changes to this project will be documented in this file. 6 | This project adheres to [Semantic Versioning](http://semver.org/). 7 | 8 | ## 2.2.4 (2022-11-09) 9 | 10 | * [karlwilbur] - Remove Ruby 2.4 from tested versions; add Ruby 3.0 and 3.1 to tested versions 11 | * [karlwilbur] - Fix issue where `domain: ''` wasn't requiring empty domain 12 | * [karlwilbur] - Remove checks for double hyphens (fixes [#87](https://github.com/K-and-R/email_validator/issues/87)) 13 | * [dependabot] - Security updates 14 | - [#89](https://github.com/K-and-R/email_validator/pull/89) 15 | + Bump `minimist` from `1.2.5` to `1.2.7` 16 | - [#86](https://github.com/K-and-R/email_validator/pull/86) 17 | + Bump `node-fetch` from `2.6.1` to `2.6.7` 18 | + Add `whatwg-url` at `5.0.0` 19 | + Add `tr46` at `0.0.3` 20 | + Add `webidl-conversions` at `3.0.0` 21 | - [#80](https://github.com/K-and-R/email_validator/pull/80) 22 | + Bump `tar` from `6.0.5` to `6.1.11` 23 | + Bump `minipass` from `3.1.3` to `3.1.5` 24 | - [#79](https://github.com/K-and-R/email_validator/pull/79) 25 | + Bump `path-parse` from `1.0.6` to `1.0.7` 26 | - [#76](https://github.com/K-and-R/email_validator/pull/76) 27 | + Bump `lodash` from `4.17.20` to `4.17.21` 28 | - [#75](https://github.com/K-and-R/email_validator/pull/75) 29 | + Bump `hosted-git-info` from `2.8.8` to `2.8.9` 30 | * [msands] - Fix URL in `README.md` [#81](https://github.com/K-and-R/email_validator/pull/81) 31 | * [kerolloz] - Fix typo in `README.md` [#73](https://github.com/K-and-R/email_validator/pull/73) 32 | 33 | ## 2.2.3 (2021-04-05) 34 | 35 | * [karlwilbur] - Fix regexp for numeric domains (fixes [#72](https://github.com/K-and-R/email_validator/issues/72)) 36 | - [delphaber] - Add checks for numeric-only domains in tests (should be considered valid) 37 | - [karlwilbur] - Fix specs for numeric-only domains labels (should be considered valid) 38 | - [karlwilbur] - Add checks for numeric-only TLDs in tests (should be considered invalid) 39 | - [karlwilbur] - Add tests to ensure that `regexp` returns expected value 40 | * [karlwilbur] - Add checks for double dash in domain (should be considered invalid) 41 | * [karlwilbur] - Add `EmailValidator::Error` class, raise `EmailValidator::Error` when invalid `mode` 42 | 43 | ## 2.2.2 (2020-12-10) 44 | 45 | * [karlwilbur] - Fix includes for `:rfc` and `:strict` modes from `Gemfile` 46 | 47 | ## 2.2.1 (2020-12-10) 48 | 49 | * [karlwilbur] - Modify regexp to: 50 | - allow numeric-only hosts [#68] 51 | - allow mailbox-only addresses in `:rfc` mode 52 | - enforce the 255-char domain limit (not in `:loose` mode unless using `:domain`) 53 | 54 | ## 2.2.0 (2020-12-09) 55 | 56 | * [karlwilbur] - Rename `:strict` -> `:rfc`; `:moderate` -> `:strict` 57 | 58 | ## 2.1.0 (2020-12-09) 59 | 60 | * [karlwilbur] - Add linters and commit hooks to validate code prior to commits 61 | * [karlwilbur] - Add `:mode` config option; values `:loose`, `:moderate`, `:strict`; default to `:loose` 62 | * [karlwilbur] - Merge in changes from fork 63 | 64 | ## 1.9.0.pre (2020-10-14) 65 | 66 | * [karlwilbur] - Add `require_fqdn` option, require FQDN by default 67 | * [karlwilbur] - Add support for IPv4 and IPv6 address hosts 68 | * [karlwilbur] - Add Rubocop, `.editorconfig`; code cleanup/linting 69 | 70 | ## 1.8.0 (2019-06-14) 71 | 72 | * [karlwilbur] - Refactor class methods for readability 73 | * [karlwilbur] - `gemspec` meta updates 74 | * [karlwilbur] - Use POSIX classes for better performance 75 | * [karlwilbur] - Refactored tests to check specical characters one at a time 76 | * [karlwilbur] - Refactored validation regex to be more techincally correct 77 | * [karlwilbur] - Add this `CHANGELOG` 78 | 79 | ## 1.7.0 (2019-04-20) 80 | 81 | * [karlwilbur] - Added test coverage badge to README 82 | * [karlwilbur] - Added I18n directive to remove warning message in testing 83 | * [karlwilbur] - Added RFC-2822 reference 84 | * [karlwilbur] - Ignore local rspec config file 85 | * [karlwilbur] - Check for invalid double dots in strict mode 86 | * [karlwilbur] - Updated spec_helper to remove Code Climate Test Reporter; it is to be run separately now 87 | * [karlwilbur] - Allow leading/trailing whitespace in normal, not strict 88 | * [karlwilbur] - Added `invalid?` as inverse of `valid?` 89 | * [karlwilbur] - Add the ability to limit to a domain 90 | * [karlwilbur] - Removed CodeShip badge 91 | * [karlwilbur] - Make the dot in the domain part non-conditional 92 | * [karlwilbur] - Fix domain label pattern to allow numbers per rfc5321 93 | 94 | ## 1.6.0 (2015-06-14) 95 | 96 | * [karlwilbur] - Fixed validation to be closer to RFC-5321 97 | * [karlwilbur] - Updated specs to use Rspec 3 syntax 98 | * [karlwilbur] - Added unicode suport to validation regexp 99 | * [karlwilbur] - Added class access to regexp, and `valid?` calss method 100 | * [karlwilbur] - Simplified code using new methods 101 | * [karlwilbur] - Added CodeClimate and SimpleCov 102 | * [karlwilbur] - Updated version and contact info 103 | 104 | *** Forked from 105 | 106 | ## 2.0.1 (2019-03-09) 107 | 108 | * Add email value to error details [f1sherman #50] 109 | * CI doesn't test Ruby versions that no longer receive updates [f1sherman #51] 110 | 111 | ## 2.0.0 (2019-03-02) 112 | 113 | * Looser validation [#49] 114 | 115 | ## 1.6.0 (2015-05-12) 116 | 117 | * Unicode characters support [i7an #24] 118 | 119 | ## 1.5.0 (2014-12-08) 120 | 121 | * Add a class method for simpler validation [TiteiKo and cluesque #19] 122 | * RSpec 3.0 syntax [strivedi183 #17] 123 | * Create Changes.md 124 | 125 | --- 126 | 127 | Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) 128 | for help with Markdown. 129 | 130 | The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/) 131 | describes the differences between markdown on github and standard markdown. 132 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Determine from where we get our gems 4 | if File.exist?(File.expand_path('.rubygems-proxy-url', __dir__)) 5 | rubygems_url = File.read( 6 | File.expand_path('../.rubygems-proxy-url', __dir__), 7 | :mode => 'rb' 8 | ).chomp 9 | end 10 | # rubocop:disable Style/IfUnlessModifier 11 | if rubygems_url.nil? || rubygems_url.empty? 12 | rubygems_url = 'https://rubygems.org' 13 | end 14 | # rubocop:enable Style/IfUnlessModifier 15 | source rubygems_url 16 | 17 | # Normalize repo path 18 | def github_repo_path(repo_name) 19 | repo_name.include?('/') ? repo_name : "#{repo_name}/#{repo_name}" 20 | end 21 | # Add source for GitHub 22 | git_source(:github) do |repo_name| 23 | "https://github.com/#{github_repo_path(repo_name)}.git" 24 | end 25 | 26 | # load requirements from the `*.gemspec` file 27 | gemspec 28 | 29 | # Make-like utility 30 | gem 'rake' 31 | 32 | # RSpec testing framework 33 | gem 'rspec' 34 | 35 | # Pry, an IRB alternative 36 | gem 'pry' 37 | 38 | # Simplecov for code coverage reporting 39 | # gem 'simplecov', '>= 0.20.0' 40 | gem 'simplecov', '>= 0.17.0', '< 0.18' 41 | 42 | # These are all development dependencies, since the Gemfile is only used in development 43 | group :development do 44 | # Pry addons, from K&R repo 45 | gem 'kandr-pry-plus' 46 | # Pry Rails extensions 47 | gem 'pry-rails' 48 | 49 | # Rubocop for ensuring well written code 50 | gem 'rubocop', '>= 1.0' 51 | # Rubocop performance evaluation 52 | gem 'rubocop-performance', '>= 1.0' 53 | # Rubocop Rake evaluation 54 | gem 'rubocop-rake' 55 | # Rubocop RSpec evaluation 56 | gem 'rubocop-rspec', '>= 2.0' 57 | 58 | # Markdown lint tool 59 | gem 'mdl' 60 | end 61 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 Brian Alexander 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # EmailValidator 2 | 3 | [![Gem Version](https://badge.fury.io/rb/email_validator.svg)](https://badge.fury.io/rb/email_validator) 4 | [![Build Status](https://travis-ci.com/K-and-R/email_validator.svg?branch=master)](http://travis-ci.com/github/K-and-R/email_validator) 5 | [![Code Climate](https://codeclimate.com/github/K-and-R/email_validator/badges/gpa.svg)](https://codeclimate.com/github/K-and-R/email_validator) 6 | [![Test Coverage](https://codeclimate.com/github/K-and-R/email_validator/badges/coverage.svg)](https://codeclimate.com/github/K-and-R/email_validator/coverage) 7 | 8 | An email validator for Rails 3+. 9 | 10 | Supports RFC-2822-compliant and RFC-5321-compliant email validation using RFC-3696 validation. 11 | 12 | Formerly found at: 13 | 14 | ## Validation philosophy 15 | 16 | The default validation provided by this gem (the `:loose` configuration option) 17 | is extremely loose. It just checks that there's an `@` with something before and 18 | after it without any whitespace. See [this article by David Gilbertson](https://medium.com/hackernoon/the-100-correct-way-to-validate-email-addresses-7c4818f24643) 19 | for an explanation of why. 20 | 21 | We understand that many use cases require an increased level of validation. This 22 | is supported by using the `:strict` validation mode. Additionally, the `:rfc` 23 | RFC-compliant mode will consider technically valid emails address as valid which 24 | may not be wanted, such as the valid `user` or `user@somehost` addresses. These 25 | would be valid in `:rfc` mode but not valid in `:loose` or `:strict`. 26 | 27 | ## Installation 28 | 29 | Add to your Gemfile: 30 | 31 | ```ruby 32 | gem 'email_validator' 33 | ``` 34 | 35 | Run: 36 | 37 | ```bash 38 | bundle install 39 | ``` 40 | 41 | ## Usage 42 | 43 | Add the following to your model: 44 | 45 | ```ruby 46 | validates :my_email_attribute, email: true 47 | ``` 48 | 49 | You may wish to allow domains without a FQDN, like `user@somehost`. While this 50 | is technically a valid address, it is uncommon to consider such address valid. 51 | We will consider them valid by default with the `:loose` checking. Disallowed 52 | by setting `require_fqdn: true` or by enabling `:strict` checking: 53 | 54 | ```ruby 55 | validates :my_email_attribute, email: {mode: :strict, require_fqdn: true} 56 | ``` 57 | 58 | You can also limit to a single domain (e.g: you have separate `User` and 59 | `AdminUser` models and want to ensure that `AdminUser` emails are on a specific 60 | domain): 61 | 62 | ```ruby 63 | validates :my_email_attribute, email: {domain: 'example.com'} 64 | ``` 65 | 66 | ## Configuration 67 | 68 | Default configuration can be overridden by setting options in `config/initializers/email_validator.rb`: 69 | 70 | ```ruby 71 | if defined?(EmailValidator) 72 | # To completely override the defaults 73 | EmailValidator.default_options = { 74 | allow_nil: false, 75 | domain: nil, 76 | require_fqdn: nil, 77 | mode: :loose 78 | } 79 | 80 | # or just a few options 81 | EmailValidator.default_options.merge!({ domain: 'mydomain.com' }) 82 | end 83 | ``` 84 | 85 | ### Loose mode 86 | 87 | This it the default validation mode of this gem. It is intentionally extremely 88 | loose (see the [Validation Philosophy section](#validation_philosophy) above. It 89 | just checks that there's an `@` with something before and after it without any 90 | whitespace. 91 | 92 | ### Strict mode 93 | 94 | Enabling `:strict` checking will check for a "normal" email format that would 95 | be expected in most common everyday usage. Strict mode basically checks for a 96 | properly sized and formatted mailbox label, a single "@" symbol, and a properly 97 | sized and formatted FQDN. Enabling `:strict` mode will also enable `:require_fqdn` 98 | configuration option. 99 | 100 | Strict mode can be enabled globally by requiring `email_validator/strict` in 101 | your `Gemfile`, by setting the option in `config/initializers/email_validator.rb`, 102 | or by specifying the option in a specific `validates` call. 103 | 104 | * `Gemfile`: 105 | 106 | ```ruby 107 | gem 'email_validator', require: 'email_validator/strict' 108 | ``` 109 | 110 | * `config/initializers/email_validator.rb`: 111 | 112 | ```ruby 113 | if defined?(EmailValidator) 114 | EmailValidator.default_options[:mode] = :strict 115 | end 116 | ``` 117 | 118 | * `validates` call: 119 | 120 | ```ruby 121 | validates :my_email_attribute, email: {mode: :strict} 122 | ``` 123 | 124 | ### RFC mode 125 | 126 | In order to have RFC-compliant validation (according to [http://www.remote.org/jochen/mail/info/chars.html](https://web.archive.org/web/20150508102948/http://www.remote.org/jochen/mail/info/chars.html)), 127 | enable `:rfc` mode. 128 | 129 | You can do this globally by requiring `email_validator/rfc` in your `Gemfile`, 130 | by setting the options in `config/initializers/email_validator.rb`, or you can do 131 | this in a specific `validates` call. 132 | 133 | * `Gemfile`: 134 | 135 | ```ruby 136 | gem 'email_validator', require: 'email_validator/rfc' 137 | ``` 138 | 139 | * `config/initializers/email_validator.rb`: 140 | 141 | ```ruby 142 | if defined?(EmailValidator) 143 | EmailValidator.default_options[:mode] = :rfc 144 | end 145 | ``` 146 | 147 | * `validates` call: 148 | 149 | ```ruby 150 | validates :my_email_attribute, email: {mode: :rfc} 151 | ``` 152 | 153 | ## Validation outside a model 154 | 155 | If you need to validate an email outside a model, you can get the regexp: 156 | 157 | ### Loose/default mode 158 | 159 | ```ruby 160 | EmailValidator.valid?('narf@example.com') # boolean 161 | ``` 162 | 163 | ### Requiring a FQDN 164 | 165 | ```ruby 166 | EmailValidator.valid?('narf@somehost') # boolean false 167 | EmailValidator.invalid?('narf@somehost', require_fqdn: false) # boolean true 168 | ``` 169 | 170 | _NB: Enabling strict mode (`mode: :strict`) enables `require_fqdn` 171 | (`require_fqdn: true`), overridding any `require_fqdn: false` while 172 | `mode: :strict` is set._ 173 | 174 | ### Requiring a specific domain 175 | 176 | ```ruby 177 | EmailValidator.valid?('narf@example.com', domain: 'foo.com') # boolean false 178 | EmailValidator.invalid?('narf@example.com', domain: 'foo.com') # boolean true 179 | ``` 180 | 181 | ### Strict mode 182 | 183 | ```ruby 184 | EmailValidator.regexp(mode: :strict) # returns the regex 185 | EmailValidator.valid?('narf@example.com', mode: :strict) # boolean 186 | ``` 187 | 188 | ### RFC mode 189 | 190 | ```ruby 191 | EmailValidator.regexp(mode: :rfc) # returns the regex 192 | EmailValidator.valid?('narf@example.com', mode: :rfc) # boolean 193 | ``` 194 | 195 | ## Thread safety 196 | 197 | This gem is thread safe, with one caveat: `EmailValidator.default_options` must 198 | be configured before use in a multi-threaded environment. If you configure 199 | `default_options` in a Rails initializer file, then you're good to go since 200 | initializers are run before worker threads are spawned. 201 | 202 | ## Alternative gems 203 | 204 | Do you prefer a different email validation gem? If so, open an issue with a brief 205 | explanation of how it differs from this gem. I'll add a link to it in this README. 206 | 207 | * [`email_address`](https://github.com/afair/email_address) () 208 | * [`email_verifier`](https://github.com/kamilc/email_verifier) () 209 | 210 | ## Maintainers 211 | 212 | All thanks is given to [Brian Alexander (balexand)](https://github.com/balexand) 213 | for is initial work on this gem. 214 | 215 | Currently maintained by: 216 | 217 | * Karl Wilbur () 218 | * K&R Software () 219 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'bundler' 2 | require 'rspec/core/rake_task' 3 | 4 | Bundler::GemHelper.install_tasks 5 | 6 | RSpec::Core::RakeTask.new do |t| 7 | t.rspec_opts = %w[--format documentation --colour] 8 | end 9 | 10 | task :default => 'spec' 11 | -------------------------------------------------------------------------------- /bin/report-test-coverage: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # `CC_TEST_REPORTER_ID` should be defined is `.env`. Its value is the 4 | # `TEST REPORTER ID` obtained here: 5 | # https://codeclimate.com/repos/5f874a7355b6af500d008806/settings/test_reporter 6 | . .env 7 | # cc-test-reporter format-coverage 8 | # cc-test-reporter upload-coverage coverage/codeclimate.json -r ${CC_TEST_REPORTER_ID} 9 | cc-test-reporter after-build 10 | -------------------------------------------------------------------------------- /email_validator.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'email_validator' 3 | s.version = '2.2.4' 4 | s.authors = ['Brian Alexander', 'Karl Wilbur'] 5 | s.summary = 'An email validator for Rails 3+.' 6 | s.description = 'An email validator for Rails 3+. See homepage for details: http://github.com/K-and-R/email_validator' 7 | s.email = 'karl@kandrsoftware.com' 8 | s.homepage = 'https://github.com/K-and-R/email_validator' 9 | s.licenses = ['MIT'] 10 | s.extra_rdoc_files = %w[ 11 | LICENSE 12 | README.md 13 | CHANGELOG.md 14 | ] 15 | s.files = `git ls-files -- lib/*`.split("\n") 16 | s.require_paths = %w[lib] 17 | 18 | s.test_files = `git ls-files -- spec/*`.split("\n") 19 | 20 | # This gem will work with 2.4.0 or greater... but *should* work with 1.8.7+ 21 | s.required_ruby_version = '>= 2.4.0' 22 | 23 | s.add_dependency('activemodel') 24 | 25 | s.add_development_dependency('rubysl', '~> 2.0') if RUBY_ENGINE == 'rbx' 26 | end 27 | -------------------------------------------------------------------------------- /lib/email_validator.rb: -------------------------------------------------------------------------------- 1 | # Based on work from http://thelucid.com/2010/01/08/sexy-validation-in-edge-rails-rails-3/ 2 | 3 | # EmailValidator class 4 | class EmailValidator < ActiveModel::EachValidator 5 | # rubocop:disable Style/ClassVars 6 | @@default_options = { 7 | :allow_nil => false, 8 | :domain => nil, 9 | :require_fqdn => nil, 10 | :mode => :loose 11 | } 12 | # rubocop:enable Style/ClassVars 13 | 14 | # EmailValidator::Error class 15 | class Error < StandardError 16 | def initialize(msg = 'EmailValidator error') 17 | super 18 | end 19 | end 20 | 21 | class << self 22 | def default_options 23 | @@default_options 24 | end 25 | 26 | def valid?(value, options = {}) 27 | options = parse_options(options) 28 | return true if value.nil? && options[:allow_nil] == true 29 | return false if value.nil? 30 | # quickly fail if domain is required but doesn't match 31 | return false unless options[:domain].nil? || value[/^.*@#{regexp_safe_domain(options)}$/] 32 | !!(value =~ regexp(options)) 33 | end 34 | 35 | def invalid?(value, options = {}) 36 | !valid?(value, options) 37 | end 38 | 39 | # Refs: 40 | # https://tools.ietf.org/html/rfc2822 : 3.2. Lexical Tokens, 3.4.1. Addr-spec specification 41 | # https://tools.ietf.org/html/rfc5321 : 4.1.2. Command Argument Syntax 42 | def regexp(options = {}) 43 | options = parse_options(options) 44 | case options[:mode] 45 | when :loose 46 | loose_regexp(options) 47 | when :rfc 48 | rfc_regexp(options) 49 | when :strict 50 | options[:require_fqdn] = true 51 | strict_regexp(options) 52 | else 53 | fail EmailValidator::Error, "Validation mode '#{options[:mode]}' is not supported by EmailValidator" 54 | end 55 | end 56 | 57 | protected 58 | 59 | def loose_regexp(options = {}) 60 | return /\A[^\s]+@[^\s]+\z/ if options[:domain].nil? 61 | /\A[^\s]+@#{domain_part_pattern(options)}\z/ 62 | end 63 | 64 | def strict_regexp(options = {}) 65 | /\A(?>#{local_part_pattern})@#{domain_part_pattern(options)}\z/i 66 | end 67 | 68 | def rfc_regexp(options = {}) 69 | /\A(?>#{local_part_pattern})(?:@#{domain_part_pattern(options)})?\z/i 70 | end 71 | 72 | def alpha 73 | '[[:alpha:]]' 74 | end 75 | 76 | def alnum 77 | '[[:alnum:]]' 78 | end 79 | 80 | def alnumhy 81 | "(?:#{alnum}|-)" 82 | end 83 | 84 | def ipv4 85 | '\d{1,3}(?:\.\d{1,3}){3}' 86 | end 87 | 88 | def ipv6 89 | # only supporting full IPv6 addresses right now 90 | 'IPv6:[[:xdigit:]]{1,4}(?::[[:xdigit:]]{1,4}){7}' 91 | end 92 | 93 | def address_literal 94 | "\\[(?:#{ipv4}|#{ipv6})\\]" 95 | end 96 | 97 | def host_label_pattern 98 | "#{label_is_correct_length}" \ 99 | "#{alnum}(?:#{alnumhy}{,61}#{alnum})?" 100 | end 101 | 102 | # splitting this up into separate regex pattern for performance; let's not 103 | # try the "contains" pattern unless we have to 104 | def domain_label_pattern 105 | "#{host_label_pattern}\\.#{tld_label_pattern}" 106 | end 107 | 108 | # While, techincally, TLDs can be numeric-only, this is not allowed by ICANN 109 | # Ref: ICANN Application Guidebook for new TLDs (June 2012) 110 | # says the following starting at page 64: 111 | # 112 | # > The ASCII label must consist entirely of letters (alphabetic characters a-z) 113 | # 114 | # -- https://newgtlds.icann.org/en/applicants/agb/guidebook-full-04jun12-en.pdf 115 | def tld_label_pattern 116 | "#{alpha}{1,64}" 117 | end 118 | 119 | def label_is_correct_length 120 | '(?=[^.]{1,63}(?:\.|$))' 121 | end 122 | 123 | def domain_part_is_correct_length 124 | '(?=.{1,255}$)' 125 | end 126 | 127 | def atom_char 128 | # The `atext` spec 129 | # We are looking at this without whitespace; no whitespace support here 130 | "[-#{alpha}#{alnum}+_!\"'#$%^&*{}/=?`|~]" 131 | end 132 | 133 | def local_part_pattern 134 | # the `dot-atom-text` spec, but with a 64 character limit 135 | "#{atom_char}(?:\\.?#{atom_char}){,63}" 136 | end 137 | 138 | def domain_part_pattern(options) 139 | return regexp_safe_domain(options) unless options[:domain].nil? 140 | return fqdn_pattern if options[:require_fqdn] 141 | "#{domain_part_is_correct_length}(?:#{address_literal}|(?:#{host_label_pattern}\\.)*#{tld_label_pattern})" 142 | end 143 | 144 | def fqdn_pattern 145 | "(?=.{1,255}$)(?:#{host_label_pattern}\\.)*#{domain_label_pattern}" 146 | end 147 | 148 | private 149 | 150 | def parse_options(options) 151 | # `:strict` mode enables `:require_fqdn`, unless it is already explicitly disabled 152 | options[:require_fqdn] = true if options[:require_fqdn].nil? && options[:mode] == :strict 153 | default_options.merge(options) 154 | end 155 | 156 | def regexp_safe_domain(options) 157 | options[:domain].sub(/\./, '\.') 158 | end 159 | end 160 | 161 | def validate_each(record, attribute, value) 162 | options = @@default_options.merge(self.options) 163 | record.errors.add(attribute, options[:message] || :invalid) unless self.class.valid?(value, options) 164 | end 165 | end 166 | -------------------------------------------------------------------------------- /lib/email_validator/rfc.rb: -------------------------------------------------------------------------------- 1 | # require this file to enable `:rfc` mode by default 2 | 3 | require 'email_validator' 4 | EmailValidator.default_options[:mode] = :rfc 5 | -------------------------------------------------------------------------------- /lib/email_validator/strict.rb: -------------------------------------------------------------------------------- 1 | # require this file to enable `:strict` mode by default 2 | 3 | require 'email_validator' 4 | EmailValidator.default_options[:mode] = :strict 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "email_validator", 3 | "engines": { 4 | "node": ">=12.0.0", 5 | "npm": ">=6.0.0", 6 | "yarn": ">=1.17.3" 7 | }, 8 | "dependencies": { 9 | }, 10 | "version": "2.1.0", 11 | "devDependencies": { 12 | "editorconfig-checker": "^3.0.3", 13 | "husky": "^2.0.0", 14 | "lint-staged": "^6.0.0", 15 | "markdownlint": "^0.16.0", 16 | "markdownlint-cli": "^0.18.0", 17 | "prettier": "^1.11.0", 18 | "yaml-lint": "^1.2.4" 19 | }, 20 | "lint-staged": { 21 | "linters": { 22 | "*.{json,graphql}": [ 23 | "prettier" 24 | ], 25 | "*.md": [ 26 | "bundle exec mdl" 27 | ], 28 | "{Gemfile,*.{rb,erb}}": [ 29 | "bundle exec rubocop --force-exclusion" 30 | ], 31 | "*.{yml,yaml}": [ 32 | "yamllint" 33 | ], 34 | "*": [ 35 | "editorconfig-checker -exclude '/^.*.lock$/'" 36 | ] 37 | }, 38 | "ignore": [ 39 | "**/dist/*.min.js", 40 | "**/node_modules/*", 41 | "**/vendor/*" 42 | ] 43 | }, 44 | "husky": { 45 | "hooks": { 46 | "pre-commit": "yarn run test-rb && lint-staged" 47 | } 48 | }, 49 | "scripts": { 50 | "lint-rb": "bundle exec rubocop .", 51 | "lint-md": "bundle exec mdl --git-recurse node_modules . ", 52 | "lint-yaml": "yamllint ./**/*.{yml,yaml}", 53 | "lint": "yarn run lint-rb && yarn run lint-md && yarn run lint-yaml && editorconfig-checker", 54 | "ruby-tests": "bundle exec rspec .", 55 | "test": "yarn run tests", 56 | "tests": "yarn run lint && yarn run ruby-tests", 57 | "test-rb": "yarn run ruby-tests" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /spec/email_validator_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | class DefaultUser < TestModel 4 | validates :email, :email => true 5 | end 6 | 7 | class StrictUser < TestModel 8 | validates :email, :email => { :mode => :strict } 9 | end 10 | 11 | class RfcUser < TestModel 12 | validates :email, :email => { :mode => :rfc } 13 | end 14 | 15 | class AllowNilDefaultUser < TestModel 16 | validates :email, :email => { :allow_nil => true } 17 | end 18 | 19 | class AllowNilStrictUser < TestModel 20 | validates :email, :email => { :allow_nil => true, :mode => :strict } 21 | end 22 | 23 | class AllowNilRfcUser < TestModel 24 | validates :email, :email => { :allow_nil => true, :mode => :rfc } 25 | end 26 | 27 | class DisallowNilDefaultUser < TestModel 28 | validates :email, :email => { :allow_nil => false } 29 | end 30 | 31 | class DisallowNilStrictUser < TestModel 32 | validates :email, :email => { :allow_nil => false, :mode => :strict } 33 | end 34 | 35 | class DisallowNilRfcUser < TestModel 36 | validates :email, :email => { :allow_nil => false, :mode => :rfc } 37 | end 38 | 39 | class DomainStrictUser < TestModel 40 | validates :email, :email => { :domain => 'example.com', :mode => :strict } 41 | end 42 | 43 | class DomainRfcUser < TestModel 44 | validates :email, :email => { :domain => 'example.com', :mode => :rfc } 45 | end 46 | 47 | class NonFqdnStrictUser < TestModel 48 | validates :email, :email => { :require_fqdn => false, :mode => :strict } 49 | end 50 | 51 | class NonFqdnRfcUser < TestModel 52 | validates :email, :email => { :require_fqdn => false, :mode => :rfc } 53 | end 54 | 55 | class RequireFqdnWithEmptyDomainUser < TestModel 56 | validates :email_address, :email => { :require_fqdn => true, :domain => '' } 57 | end 58 | 59 | class RequireEmptyDomainStrictUser < TestModel 60 | validates :email_address, :email => { :require_fqdn => true, :domain => '', :mode => :strict } 61 | end 62 | 63 | class RequireEmptyDomainRfcUser < TestModel 64 | validates :email_address, :email => { :require_fqdn => true, :domain => '', :mode => :rfc } 65 | end 66 | 67 | class DefaultUserWithMessage < TestModel 68 | validates :email_address, :email => { :message => 'is not looking very good!' } 69 | end 70 | 71 | RSpec.describe EmailValidator do 72 | describe 'validation' do 73 | valid_special_chars = { 74 | :ampersand => '&', 75 | :asterisk => '*', 76 | :backtick => '`', 77 | :braceleft => '{', 78 | :braceright => '}', 79 | :caret => '^', 80 | :dollar => '$', 81 | :equals => '=', 82 | :exclaim => '!', 83 | :hash => '#', 84 | :hyphen => '-', 85 | :percent => '%', 86 | :plus => '+', 87 | :pipe => '|', 88 | :question => '?', 89 | :quotedouble => '"', 90 | :quotesingle => "'", 91 | :slash => '/', 92 | :tilde => '~', 93 | :underscore => '_' 94 | } 95 | 96 | invalid_special_chars = { 97 | :backslash => '\\', 98 | :braketleft => '[', 99 | :braketright => ']', 100 | :colon => ':', 101 | :comma => ',', 102 | :greater => '>', 103 | :lesser => '<', 104 | :parenleft => '(', 105 | :parenright => ')', 106 | :semicolon => ';' 107 | } 108 | 109 | valid_includable = valid_special_chars.merge({ :dot => '.' }) 110 | valid_beginable = valid_special_chars 111 | valid_endable = valid_special_chars 112 | invalid_includable = { :at => '@' } 113 | whitespace = { :newline => "\n", :tab => "\t", :carriage_return => "\r", :space => ' ' } 114 | strictly_invalid_includable = invalid_special_chars 115 | strictly_invalid_beginable = strictly_invalid_includable.merge({ :dot => '.' }) 116 | strictly_invalid_endable = strictly_invalid_beginable 117 | domain_invalid_beginable = invalid_special_chars.merge(valid_special_chars) 118 | domain_invalid_endable = domain_invalid_beginable 119 | domain_invalid_includable = domain_invalid_beginable.reject { |k, _v| k == :hyphen } 120 | 121 | # rubocop:disable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain 122 | context 'when given the valid email' do 123 | valid_includable.map { |k, v| [ 124 | "include-#{v}-#{k}@valid-characters-in-local.dev" 125 | ]}.concat(valid_beginable.map { |k, v| [ 126 | "#{v}start-with-#{k}@valid-characters-in-local.dev" 127 | ]}).concat(valid_endable.map { |k, v| [ 128 | "end-with-#{k}-#{v}@valid-characters-in-local.dev" 129 | ]}).concat([ 130 | 'a+b@plus-in-local.com', 131 | 'a_b@underscore-in-local.com', 132 | 'user@example.com', 133 | 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@letters-in-local.dev', 134 | '01234567890@numbers-in-local.dev', 135 | 'a@single-character-in-local.dev', 136 | 'one-character-third-level@a.example.com', 137 | 'single-character-in-sld@x.dev', 138 | 'local@dash-in-sld.com', 139 | 'numbers-in-sld@s123.com', 140 | 'one-letter-sld@x.dev', 141 | 'uncommon-tld@sld.museum', 142 | 'uncommon-tld@sld.travel', 143 | 'uncommon-tld@sld.mobi', 144 | 'country-code-tld@sld.uk', 145 | 'country-code-tld@sld.rw', 146 | 'local@sld.newTLD', 147 | 'local@sub.domains.com', 148 | 'aaa@bbb.co.jp', 149 | 'nigel.worthington@big.co.uk', 150 | 'f@c.com', 151 | 'f@s.c', 152 | 'someuser@somehost.somedomain', 153 | 'mixed-1234-in-{+^}-local@sld.dev', 154 | 'partially."quoted"@sld.com', 155 | 'areallylongnameaasdfasdfasdfasdf@asdfasdfasdfasdfasdf.ab.cd.ef.gh.co.ca', 156 | 'john.doe@2020.example.com', 157 | 'john.doe@2a.com', 158 | 'john.doe@a2.com', 159 | 'john.doe@2020.a-z.com', 160 | 'john.doe@2020.a2z.com', 161 | 'john.doe@2020.12345a6789.com', 162 | 'jonh.doe@163.com', 163 | 'test@umläut.com', # non-ASCII 164 | 'test@xn--umlut-ira.com' # ASCII-compatibale encoding of non-ASCII 165 | ]).flatten.each do |email| 166 | context 'when using defaults' do 167 | it "'#{email}' should be valid" do 168 | expect(DefaultUser.new(:email => email)).to be_valid 169 | end 170 | 171 | it "'#{email}' should be valid using EmailValidator.valid?" do 172 | expect(described_class).to be_valid(email) 173 | end 174 | 175 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 176 | expect(described_class).not_to be_invalid(email) 177 | end 178 | 179 | it "'#{email}' should match the regexp" do 180 | expect(!!(email.strip =~ described_class.regexp)).to be(true) 181 | end 182 | end 183 | 184 | context 'when in `:strict` mode' do 185 | it "'#{email}' should be valid" do 186 | expect(StrictUser.new(:email => email)).to be_valid 187 | end 188 | 189 | it "'#{email}' should be valid using EmailValidator.valid?" do 190 | expect(described_class).to be_valid(email, :mode => :strict) 191 | end 192 | 193 | it "'#{email}' should not be invalid using EmailValidator.valid?" do 194 | expect(described_class).not_to be_invalid(email, :mode => :strict) 195 | end 196 | 197 | it "'#{email}' should match the regexp" do 198 | expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true) 199 | end 200 | end 201 | 202 | context 'when in `:rfc` mode' do 203 | it "'#{email}' should be valid" do 204 | expect(RfcUser.new(:email => email)).to be_valid 205 | end 206 | 207 | it "'#{email}' should be valid using EmailValidator.valid?" do 208 | expect(described_class).to be_valid(email, :mode => :rfc) 209 | end 210 | 211 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 212 | expect(described_class).not_to be_invalid(email, :mode => :rfc) 213 | end 214 | 215 | it "'#{email}' should match the regexp" do 216 | expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) 217 | end 218 | end 219 | end 220 | end 221 | 222 | context 'when given the valid host-only email' do 223 | [ 224 | 'f@s', 225 | 'user@localhost', 226 | 'someuser@somehost' 227 | ].each do |email| 228 | context 'when using defaults' do 229 | it "'#{email}' should be valid" do 230 | expect(DefaultUser.new(:email => email)).to be_valid 231 | end 232 | 233 | it "'#{email}' should be valid using EmailValidator.valid?" do 234 | expect(described_class).to be_valid(email) 235 | end 236 | 237 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 238 | expect(described_class).not_to be_invalid(email) 239 | end 240 | 241 | it "'#{email}' should match the regexp" do 242 | expect(!!(email.strip =~ described_class.regexp)).to be(true) 243 | end 244 | end 245 | 246 | context 'when in `:strict` mode' do 247 | it "'#{email}' should not be valid" do 248 | expect(StrictUser.new(:email => email)).not_to be_valid 249 | end 250 | 251 | it "'#{email}' should not be valid using EmailValidator.valid?" do 252 | expect(described_class).not_to be_valid(email, :mode => :strict) 253 | end 254 | 255 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 256 | expect(described_class).to be_invalid(email, :mode => :strict) 257 | end 258 | 259 | it "'#{email}' should not match the regexp" do 260 | expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) 261 | end 262 | end 263 | 264 | context 'when in `:rfc` mode' do 265 | it "'#{email}' should be valid" do 266 | expect(RfcUser.new(:email => email)).to be_valid 267 | end 268 | 269 | it "'#{email}' should be valid using EmailValidator.valid?" do 270 | expect(described_class).to be_valid(email, :mode => :rfc) 271 | end 272 | 273 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 274 | expect(described_class).not_to be_invalid(email, :mode => :rfc) 275 | end 276 | 277 | it "'#{email}' should match the regexp" do 278 | expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) 279 | end 280 | end 281 | end 282 | end 283 | 284 | context 'when given the numeric domain' do 285 | [ 286 | 'only-numbers-in-domain-label@sub.123.custom' 287 | ].each do |email| 288 | context 'when using defaults' do 289 | it "'#{email}' should be valid" do 290 | expect(DefaultUser.new(:email => email)).to be_valid 291 | end 292 | 293 | it "'#{email}' should be valid using EmailValidator.valid?" do 294 | expect(described_class).to be_valid(email) 295 | end 296 | 297 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 298 | expect(described_class).not_to be_invalid(email) 299 | end 300 | 301 | it "'#{email}' should match the regexp" do 302 | expect(!!(email.strip =~ described_class.regexp)).to be(true) 303 | end 304 | end 305 | 306 | context 'when in `:strict` mode' do 307 | it "'#{email}' should be valid" do 308 | expect(StrictUser.new(:email => email)).to be_valid 309 | end 310 | 311 | it "'#{email}' should be valid using EmailValidator.valid?" do 312 | expect(described_class).to be_valid(email, :mode => :strict) 313 | end 314 | 315 | it "'#{email}' should be not invalid using EmailValidator.invalid?" do 316 | expect(described_class).not_to be_invalid(email, :mode => :strict) 317 | end 318 | 319 | it "'#{email}' should match the regexp" do 320 | expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(true) 321 | end 322 | end 323 | 324 | context 'when in `:rfc` mode' do 325 | it "'#{email}' should be valid" do 326 | expect(RfcUser.new(:email => email)).to be_valid 327 | end 328 | 329 | it "'#{email}' should be valid using EmailValidator.valid?" do 330 | expect(described_class).to be_valid(email, :mode => :rfc) 331 | end 332 | 333 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 334 | expect(described_class).not_to be_invalid(email, :mode => :rfc) 335 | end 336 | 337 | it "'#{email}' should match the regexp" do 338 | expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) 339 | end 340 | end 341 | end 342 | end 343 | 344 | context 'when given the valid mailbox-only email' do 345 | valid_includable.map { |k, v| [ 346 | "user-#{v}-#{k}-name" 347 | ]}.concat(valid_beginable.map { |k, v| [ 348 | "#{v}-start-with-#{k}-user" 349 | ]}).concat(valid_endable.map { |k, v| [ 350 | "end-with-#{k}-#{v}" 351 | ]}).concat([ 352 | 'user' 353 | ]).flatten.each do |email| 354 | context 'when using defaults' do 355 | it "'#{email}' should not be valid" do 356 | expect(DefaultUser.new(:email => email)).not_to be_valid 357 | end 358 | 359 | it "'#{email}' should not be valid using EmailValidator.valid?" do 360 | expect(described_class).not_to be_valid(email) 361 | end 362 | 363 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 364 | expect(described_class).to be_invalid(email) 365 | end 366 | 367 | it "'#{email}' should not match the regexp" do 368 | expect(!!(email.strip =~ described_class.regexp)).to be(false) 369 | end 370 | end 371 | 372 | context 'when in `:strict` mode' do 373 | it "'#{email}' should not be valid" do 374 | expect(StrictUser.new(:email => email)).not_to be_valid 375 | end 376 | 377 | it "'#{email}' should not be valid using EmailValidator.valid?" do 378 | expect(described_class).not_to be_valid(email, :mode => :strict) 379 | end 380 | 381 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 382 | expect(described_class).to be_invalid(email, :mode => :strict) 383 | end 384 | 385 | it "'#{email}' should not match the regexp" do 386 | expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) 387 | end 388 | end 389 | 390 | context 'when in `:rfc` mode' do 391 | it "'#{email}' should be valid" do 392 | expect(RfcUser.new(:email => email)).to be_valid 393 | end 394 | 395 | it "'#{email}' should be valid using EmailValidator.valid?" do 396 | expect(described_class).to be_valid(email, :mode => :rfc) 397 | end 398 | 399 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 400 | expect(described_class).not_to be_invalid(email, :mode => :rfc) 401 | end 402 | 403 | it "'#{email}' should match the regexp" do 404 | expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) 405 | end 406 | end 407 | end 408 | end 409 | 410 | context 'when given the valid IP address email' do 411 | [ 412 | 'bracketed-IP@[127.0.0.1]', 413 | 'bracketed-and-labeled-IPv6@[IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678]' 414 | ].each do |email| 415 | context 'when using defaults' do 416 | it "'#{email}' should be valid" do 417 | expect(DefaultUser.new(:email => email)).to be_valid 418 | end 419 | 420 | it "'#{email}' should be valid using EmailValidator.valid?" do 421 | expect(described_class).to be_valid(email) 422 | end 423 | 424 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 425 | expect(described_class).not_to be_invalid(email) 426 | end 427 | 428 | it "'#{email}' should match the regexp" do 429 | expect(!!(email.strip =~ described_class.regexp)).to be(true) 430 | end 431 | end 432 | 433 | context 'when in `:strict` mode' do 434 | it "'#{email}' should not be valid" do 435 | expect(StrictUser.new(:email => email)).not_to be_valid 436 | end 437 | 438 | it "'#{email}' should not be valid using EmailValidator.valid?" do 439 | expect(described_class).not_to be_valid(email, :mode => :strict) 440 | end 441 | 442 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 443 | expect(described_class).to be_invalid(email, :mode => :strict) 444 | end 445 | 446 | it "'#{email}' should not match the regexp" do 447 | expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) 448 | end 449 | end 450 | 451 | context 'when in `:rfc` mode' do 452 | it "'#{email}' should be valid" do 453 | expect(RfcUser.new(:email => email)).to be_valid 454 | end 455 | 456 | it "'#{email}' should be valid using EmailValidator.valid?" do 457 | expect(described_class).to be_valid(email, :mode => :rfc) 458 | end 459 | 460 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 461 | expect(described_class).not_to be_invalid(email, :mode => :rfc) 462 | end 463 | 464 | it "'#{email}' should match the regexp" do 465 | expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(true) 466 | end 467 | end 468 | end 469 | end 470 | 471 | context 'when given the invalid email' do 472 | invalid_includable.map { |k, v| [ 473 | "include-#{v}-#{k}@invalid-characters-in-local.dev" 474 | ]}.concat(domain_invalid_beginable.map { |k, v| [ 475 | "start-with-#{k}@#{v}invalid-characters-in-domain.dev" 476 | ]}).concat(domain_invalid_endable.map { |k, v| [ 477 | "end-with-#{k}@invalid-characters-in-domain#{v}.dev" 478 | ]}).concat(domain_invalid_includable.map { |k, v| [ 479 | "include-#{k}@invalid-characters-#{v}-in-domain.dev" 480 | ]}).concat([ 481 | 'test@example.com@example.com', 482 | 'missing-sld@.com', 483 | 'missing-tld@sld.', 484 | 'unbracketed-IPv6@abcd:ef01:1234:5678:9abc:def0:1234:5678', 485 | 'unbracketed-and-labled-IPv6@IPv6:abcd:ef01:1234:5678:9abc:def0:1234:5678', 486 | 'bracketed-and-unlabeled-IPv6@[abcd:ef01:1234:5678:9abc:def0:1234:5678]', 487 | 'unbracketed-IPv4@127.0.0.1', 488 | 'invalid-IPv4@127.0.0.1.26', 489 | 'another-invalid-IPv4@127.0.0.256', 490 | 'IPv4-and-port@127.0.0.1:25', 491 | 'host-beginning-with-dot@.example.com', 492 | 'domain-beginning-with-dash@-example.com', 493 | 'domain-ending-with-dash@example-.com', 494 | 'the-local-part-is-invalid-if-it-is-longer-than-sixty-four-characters@sld.dev', 495 | "domain-too-long@t#{".#{'o' * 63}" * 5}.long", 496 | "user@example.com" 497 | ]).flatten.each do |email| 498 | context 'when using defaults' do 499 | it "'#{email}' should be valid" do 500 | expect(DefaultUser.new(:email => email)).to be_valid 501 | end 502 | 503 | it "'#{email}' should be valid using EmailValidator.valid?" do 504 | expect(described_class).to be_valid(email) 505 | end 506 | 507 | it "'#{email}' should not be invalid using EmailValidator.invalid?" do 508 | expect(described_class).not_to be_invalid(email) 509 | end 510 | 511 | it "'#{email}' should match the regexp" do 512 | expect(!!(email.strip =~ described_class.regexp)).to be(true) 513 | end 514 | end 515 | 516 | context 'when in `:strict` mode' do 517 | it "'#{email}' should not be valid" do 518 | expect(StrictUser.new(:email => email)).not_to be_valid 519 | end 520 | 521 | it "'#{email}' should not be valid using EmailValidator.valid?" do 522 | expect(described_class).not_to be_valid(email, :mode => :strict) 523 | end 524 | 525 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 526 | expect(described_class).to be_invalid(email, :mode => :strict) 527 | end 528 | 529 | it "'#{email}' should not match the regexp" do 530 | expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) 531 | end 532 | end 533 | 534 | context 'when in `:rfc` mode' do 535 | it "'#{email}' should not be valid" do 536 | expect(RfcUser.new(:email => email)).not_to be_valid 537 | end 538 | 539 | it "'#{email}' should not be valid using EmailValidator.valid?" do 540 | expect(described_class).not_to be_valid(email, :mode => :rfc) 541 | end 542 | 543 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 544 | expect(described_class).to be_invalid(email, :mode => :rfc) 545 | end 546 | 547 | it "'#{email}' should not match the regexp" do 548 | expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false) 549 | end 550 | end 551 | end 552 | end 553 | 554 | context 'when given the invalid email with whitespace in parts' do 555 | whitespace.map { |k, v| [ 556 | "include-#{v}-#{k}@invalid-characters-in-local.dev" 557 | ]}.concat([ 558 | 'foo @bar.com', 559 | "foo\t@bar.com", 560 | "foo\n@bar.com", 561 | "foo\r@bar.com", 562 | 'test@ example.com', 563 | 'user@example .com', 564 | "user@example\t.com", 565 | "user@example\n.com", 566 | "user@example\r.com", 567 | 'user@exam ple.com', 568 | "user@exam\tple.com", 569 | "user@exam\nple.com", 570 | "user@exam\rple.com", 571 | 'us er@example.com', 572 | "us\ter@example.com", 573 | "us\ner@example.com", 574 | "us\rer@example.com", 575 | "user@example.com\n", 576 | "user@example.com\t", 577 | "user@example.com\r", 578 | "user@example.com ", 579 | ' leading-whitespace@example.com', 580 | 'trailing-whitespace@example.com ', 581 | ' leading-and-trailing-whitespace@example.com ', 582 | ' user-with-leading-whitespace-space@example.com', 583 | "\tuser-with-leading-whitespace-tab@example.com", 584 | " 585 | user-with-leading-whitespace-newline@example.com", 586 | 'domain-with-trailing-whitespace-space@example.com ', 587 | "domain-with-trailing-whitespace-tab@example.com\t", 588 | "domain-with-trailing-whitespace-newline@example.com 589 | " 590 | ]).flatten.each do |email| 591 | context 'when using defaults' do 592 | it "'#{email}' should not be valid" do 593 | expect(DefaultUser.new(:email => email)).not_to be_valid 594 | end 595 | 596 | it "'#{email}' should not be valid using EmailValidator.valid?" do 597 | expect(described_class).not_to be_valid(email) 598 | end 599 | 600 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 601 | expect(described_class).to be_invalid(email) 602 | end 603 | 604 | it "'#{email}' should not match the regexp" do 605 | expect(!!(email =~ described_class.regexp)).to be(false) 606 | end 607 | end 608 | 609 | context 'when in `:strict` mode' do 610 | it "'#{email}' should not be valid" do 611 | expect(StrictUser.new(:email => email)).not_to be_valid 612 | end 613 | 614 | it "'#{email}' should not be valid using EmailValidator.valid?" do 615 | expect(described_class).not_to be_valid(email, :mode => :strict) 616 | end 617 | 618 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 619 | expect(described_class).to be_invalid(email, :mode => :strict) 620 | end 621 | 622 | it "'#{email}' should not match the regexp" do 623 | expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false) 624 | end 625 | end 626 | 627 | context 'when in `:rfc` mode' do 628 | it "'#{email}' should not be valid" do 629 | expect(RfcUser.new(:email => email)).not_to be_valid 630 | end 631 | 632 | it "'#{email}' should not be valid using EmailValidator.valid?" do 633 | expect(described_class).not_to be_valid(email, :mode => :rfc) 634 | end 635 | 636 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 637 | expect(described_class).to be_invalid(email, :mode => :rfc) 638 | end 639 | 640 | it "'#{email}' should not match the regexp" do 641 | expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false) 642 | end 643 | end 644 | end 645 | end 646 | 647 | context 'when given the invalid email with missing parts' do 648 | [ 649 | '', 650 | '@bar.com', 651 | 'test@', 652 | '@missing-local.dev', 653 | ' ' 654 | ].each do |email| 655 | context 'when using defaults' do 656 | it "'#{email}' should not be valid" do 657 | expect(DefaultUser.new(:email => email)).not_to be_valid 658 | end 659 | 660 | it "'#{email}' should not be valid using EmailValidator.valid?" do 661 | expect(described_class).not_to be_valid(email) 662 | end 663 | 664 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 665 | expect(described_class).to be_invalid(email) 666 | end 667 | 668 | it "'#{email}' should not match the regexp" do 669 | expect(!!(email.strip =~ described_class.regexp)).to be(false) 670 | end 671 | end 672 | 673 | context 'when in `:strict` mode' do 674 | it "'#{email}' should not be valid" do 675 | expect(StrictUser.new(:email => email)).not_to be_valid 676 | end 677 | 678 | it "'#{email}' should not be valid using EmailValidator.valid?" do 679 | expect(described_class).not_to be_valid(email, :mode => :strict) 680 | end 681 | 682 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 683 | expect(described_class).to be_invalid(email, :mode => :strict) 684 | end 685 | 686 | it "'#{email}' should not match the regexp" do 687 | expect(!!(email.strip =~ described_class.regexp(:mode => :strict))).to be(false) 688 | end 689 | end 690 | 691 | context 'when in `:rfc` mode' do 692 | it "'#{email}' should not be valid" do 693 | expect(RfcUser.new(:email => email)).not_to be_valid 694 | end 695 | 696 | it "'#{email}' should not be valid using EmailValidator.valid?" do 697 | expect(described_class).not_to be_valid(email, :mode => :rfc) 698 | end 699 | 700 | it "'#{email}' should be invalid using EmailValidator.invalid?" do 701 | expect(described_class).to be_invalid(email, :mode => :rfc) 702 | end 703 | 704 | it "'#{email}' should not match the regexp" do 705 | expect(!!(email.strip =~ described_class.regexp(:mode => :rfc))).to be(false) 706 | end 707 | end 708 | end 709 | end 710 | 711 | context 'when given the strictly invalid email' do 712 | strictly_invalid_includable.map { |k, v| [ 713 | "include-#{v}-#{k}@invalid-characters-in-local.dev" 714 | ]}.concat(strictly_invalid_beginable.map { |k, v| [ 715 | "#{v}start-with-#{k}@invalid-characters-in-local.dev" 716 | ]}).concat(strictly_invalid_endable.map { |k, v| [ 717 | "end-with-#{k}#{v}@invalid-characters-in-local.dev" 718 | ]}).concat([ 719 | 'user..-with-double-dots@example.com', 720 | '.user-beginning-with-dot@example.com', 721 | 'user-ending-with-dot.@example.com', 722 | 'fully-numeric-tld@example.123' 723 | ]).flatten.each do |email| 724 | context 'when using defaults' do 725 | it "#{email.strip} in a model should be valid" do 726 | expect(DefaultUser.new(:email => email)).to be_valid 727 | end 728 | 729 | it "#{email.strip} should be valid using EmailValidator.valid?" do 730 | expect(described_class).to be_valid(email) 731 | end 732 | 733 | it "#{email.strip} should not be invalid using EmailValidator.invalid?" do 734 | expect(described_class).not_to be_invalid(email) 735 | end 736 | 737 | it "#{email.strip} should match the regexp" do 738 | expect(!!(email =~ described_class.regexp)).to be(true) 739 | end 740 | end 741 | 742 | context 'when in `:strict` mode' do 743 | it "#{email.strip} in a model should not be valid" do 744 | expect(StrictUser.new(:email => email)).not_to be_valid 745 | end 746 | 747 | it "#{email.strip} should not be valid using EmailValidator.valid?" do 748 | expect(described_class).not_to be_valid(email, :mode => :strict) 749 | end 750 | 751 | it "#{email.strip} should be invalid using EmailValidator.invalid?" do 752 | expect(described_class).to be_invalid(email, :mode => :strict) 753 | end 754 | 755 | it "#{email.strip} should not match the regexp" do 756 | expect(!!(email =~ described_class.regexp(:mode => :strict))).to be(false) 757 | end 758 | end 759 | 760 | context 'when in `:rfc` mode' do 761 | it "#{email.strip} in a model should not be valid" do 762 | expect(RfcUser.new(:email => email)).not_to be_valid 763 | end 764 | 765 | it "#{email.strip} should not be valid using EmailValidator.valid?" do 766 | expect(described_class).not_to be_valid(email, :mode => :rfc) 767 | end 768 | 769 | it "#{email.strip} should be invalid using EmailValidator.invalid?" do 770 | expect(described_class).to be_invalid(email, :mode => :rfc) 771 | end 772 | 773 | it "#{email.strip} should not match the regexp" do 774 | expect(!!(email =~ described_class.regexp(:mode => :rfc))).to be(false) 775 | end 776 | end 777 | end 778 | end 779 | 780 | context 'when `require_fqdn` is explicitly enabled with a blank domain' do 781 | let(:opts) { { :require_fqdn => true, :domain => '' } } 782 | 783 | context 'when given a email containing any domain' do 784 | let(:email) { 'someuser@somehost' } 785 | 786 | context 'when using defaults' do 787 | it 'is not valid in a model' do 788 | expect(RequireFqdnWithEmptyDomainUser.new(:email => email)).not_to be_valid 789 | end 790 | 791 | it 'is not using EmailValidator.valid?' do 792 | expect(described_class).not_to be_valid(email, opts) 793 | end 794 | 795 | it 'is invalid using EmailValidator.invalid?' do 796 | expect(described_class).to be_invalid(email, opts) 797 | end 798 | 799 | it 'does not match the regexp' do 800 | expect(!!(email =~ described_class.regexp(opts))).to be(false) 801 | end 802 | end 803 | 804 | context 'when in `:strict` mode' do 805 | it 'is not valid in a model' do 806 | expect(RequireEmptyDomainStrictUser.new(:email => email)).not_to be_valid 807 | end 808 | 809 | it 'is not using EmailValidator.valid?' do 810 | expect(described_class).not_to be_valid(email, opts.merge({ :mode => :strict })) 811 | end 812 | 813 | it 'is invalid using EmailValidator.invalid?' do 814 | expect(described_class).to be_invalid(email, opts.merge({ :mode => :strict })) 815 | end 816 | 817 | it 'does not match the regexp' do 818 | expect(!!(email =~ described_class.regexp(opts.merge({ :mode => :strict })))).to be(false) 819 | end 820 | end 821 | 822 | context 'when in `:rfc` mode' do 823 | it 'is not valid in a model' do 824 | expect(RequireEmptyDomainRfcUser.new(:email => email)).not_to be_valid 825 | end 826 | 827 | it 'is not using EmailValidator.valid?' do 828 | expect(described_class).not_to be_valid(email, opts.merge({ :mode => :rfc })) 829 | end 830 | 831 | it 'is invalid using EmailValidator.invalid?' do 832 | expect(described_class).to be_invalid(email, opts.merge({ :mode => :rfc })) 833 | end 834 | 835 | it 'does not match the regexp' do 836 | expect(!!(email =~ described_class.regexp(opts.merge({ :mode => :rfc })))).to be(false) 837 | end 838 | end 839 | end 840 | end 841 | 842 | context 'when `require_fqdn` is explicitly disabled' do 843 | let(:opts) { { :require_fqdn => false } } 844 | 845 | context 'when given a valid hostname-only email' do 846 | let(:email) { 'someuser@somehost' } 847 | 848 | context 'when using defaults' do 849 | it 'is valid using EmailValidator.valid?' do 850 | expect(described_class).to be_valid(email, opts) 851 | end 852 | 853 | it 'is not invalid using EmailValidator.invalid?' do 854 | expect(described_class).not_to be_invalid(email, opts) 855 | end 856 | 857 | it 'matches the regexp' do 858 | expect(!!(email =~ described_class.regexp(opts))).to be(true) 859 | end 860 | end 861 | 862 | # Strict mode enables `require_fqdn` anyway 863 | context 'when in `:strict` mode' do 864 | let(:opts) { { :require_fqdn => false, :mode => :strict } } 865 | 866 | it 'is not valid' do 867 | expect(NonFqdnStrictUser.new(:email => email)).not_to be_valid 868 | end 869 | 870 | it 'is not valid using EmailValidator.valid?' do 871 | expect(described_class).not_to be_valid(email, opts) 872 | end 873 | 874 | it 'is invalid using EmailValidator.invalid?' do 875 | expect(described_class).to be_invalid(email, opts) 876 | end 877 | 878 | it 'matches the regexp' do 879 | expect(!!(email =~ described_class.regexp(opts))).to be(false) 880 | end 881 | end 882 | 883 | context 'when in `:rfc` mode' do 884 | let(:opts) { { :require_fqdn => false, :mode => :rfc } } 885 | 886 | it 'is valid' do 887 | expect(NonFqdnRfcUser.new(:email => email)).to be_valid 888 | end 889 | 890 | it 'is valid using EmailValidator.valid?' do 891 | expect(described_class).to be_valid(email, opts) 892 | end 893 | 894 | it 'is not invalid using EmailValidator.invalid?' do 895 | expect(described_class).not_to be_invalid(email, opts) 896 | end 897 | 898 | it 'matches the regexp' do 899 | expect(!!(email =~ described_class.regexp(opts))).to be(true) 900 | end 901 | end 902 | end 903 | 904 | context 'when given a valid email using an FQDN' do 905 | let(:email) { 'someuser@somehost.somedomain' } 906 | 907 | it 'is valid' do 908 | expect(NonFqdnStrictUser.new(:email => email)).to be_valid 909 | end 910 | 911 | # rubocop:disable RSpec/PredicateMatcher 912 | it 'is valid using EmailValidator.valid?' do 913 | expect(described_class.valid?(email, opts)).to be(true) 914 | end 915 | 916 | it 'is not invalid using EmailValidator.invalid?' do 917 | expect(described_class.invalid?(email, opts)).to be(false) 918 | end 919 | # rubocop:enable RSpec/PredicateMatcher 920 | 921 | it 'matches the regexp' do 922 | expect(!!(email =~ described_class.regexp(opts))).to be(true) 923 | end 924 | 925 | context 'when in `:rfc` mode' do 926 | let(:opts) { { :require_fqdn => false, :mode => :rfc } } 927 | 928 | # rubocop:disable RSpec/PredicateMatcher 929 | it 'is valid using EmailValidator.valid?' do 930 | expect(described_class.valid?(email, opts)).to be(true) 931 | end 932 | 933 | it 'is not invalid using EmailValidator.invalid?' do 934 | expect(described_class.invalid?(email, opts)).to be(false) 935 | end 936 | # rubocop:enable RSpec/PredicateMatcher 937 | 938 | it 'is valid' do 939 | expect(NonFqdnRfcUser.new(:email => email)).to be_valid 940 | end 941 | 942 | it 'matches the regexp' do 943 | expect(!!(email =~ described_class.regexp(opts))).to be(true) 944 | end 945 | end 946 | 947 | context 'when requiring a non-matching domain' do 948 | let(:domain) { 'example.com' } 949 | let(:opts) { { :domain => domain } } 950 | 951 | it 'is not valid' do 952 | expect(DomainStrictUser.new(:email => email)).not_to be_valid 953 | end 954 | 955 | it 'is not valid using EmailValidator.valid?' do 956 | expect(described_class).not_to be_valid(email, opts) 957 | end 958 | 959 | it 'is invalid using EmailValidator.invalid?' do 960 | expect(described_class).to be_invalid(email, opts) 961 | end 962 | 963 | it 'does not matches the regexp' do 964 | expect(!!(email =~ described_class.regexp(opts))).to be(false) 965 | end 966 | 967 | context 'when in `:rfc` mode' do 968 | let(:opts) { { :domain => domain, :require_fqdn => false, :mode => :rfc } } 969 | 970 | it 'is not valid using EmailValidator.valid?' do 971 | expect(described_class).not_to be_valid(email, opts) 972 | end 973 | 974 | it 'is invalid using EmailValidator.invalid?' do 975 | expect(described_class).to be_invalid(email, opts) 976 | end 977 | 978 | it 'is not valid' do 979 | expect(DomainRfcUser.new(:email => email)).not_to be_valid 980 | end 981 | 982 | it 'does not match the regexp' do 983 | expect(!!(email =~ described_class.regexp(opts))).to be(false) 984 | end 985 | end 986 | end 987 | end 988 | end 989 | end 990 | # rubocop:enable Layout/BlockEndNewline, Layout/MultilineBlockLayout, Layout/MultilineMethodCallBraceLayout, Style/BlockDelimiters, Style/MultilineBlockChain 991 | 992 | describe 'error messages' do 993 | context 'when the message is not defined' do 994 | let(:model) { DefaultUser.new :email => 'invalidemail@' } 995 | 996 | before { model.valid? } 997 | 998 | it 'adds the default message' do 999 | expect(model.errors[:email]).to include 'is invalid' 1000 | end 1001 | end 1002 | 1003 | context 'when the message is defined' do 1004 | let(:model) { DefaultUserWithMessage.new :email_address => 'invalidemail@' } 1005 | 1006 | before { model.valid? } 1007 | 1008 | it 'adds the customized message' do 1009 | expect(model.errors[:email_address]).to include 'is not looking very good!' 1010 | end 1011 | end 1012 | end 1013 | 1014 | describe 'nil email' do 1015 | it 'is not valid when :allow_nil option is missing' do 1016 | expect(DefaultUser.new(:email => nil)).not_to be_valid 1017 | end 1018 | 1019 | it 'is valid when :allow_nil options is set to true' do 1020 | expect(AllowNilDefaultUser.new(:email => nil)).to be_valid 1021 | end 1022 | 1023 | it 'is not valid when :allow_nil option is set to false' do 1024 | expect(DisallowNilDefaultUser.new(:email => nil)).not_to be_valid 1025 | end 1026 | end 1027 | 1028 | describe 'limited to a domain' do 1029 | context 'when in `:strict` mode' do 1030 | it 'is not valid with mismatched domain' do 1031 | expect(DomainStrictUser.new(:email => 'user@not-matching.io')).not_to be_valid 1032 | end 1033 | 1034 | it 'is valid with matching domain' do 1035 | expect(DomainStrictUser.new(:email => 'user@example.com')).to be_valid 1036 | end 1037 | 1038 | it 'does not interpret the dot as any character' do 1039 | expect(DomainStrictUser.new(:email => 'user@example-com')).not_to be_valid 1040 | end 1041 | end 1042 | 1043 | context 'when in `:rfc` mode' do 1044 | it 'does not interpret the dot as any character' do 1045 | expect(DomainRfcUser.new(:email => 'user@example-com')).not_to be_valid 1046 | end 1047 | 1048 | it 'is valid with matching domain' do 1049 | expect(DomainRfcUser.new(:email => 'user@example.com')).to be_valid 1050 | end 1051 | 1052 | it 'is not valid with mismatched domain' do 1053 | expect(DomainRfcUser.new(:email => 'user@not-matching.io')).not_to be_valid 1054 | end 1055 | end 1056 | end 1057 | 1058 | describe 'default_options' do 1059 | let(:valid_email) { 'valid-email@localhost.localdomain' } 1060 | let(:invalid_email) { 'invalid email@localhost.localdomain' } 1061 | 1062 | it 'validates valid using `:loose` mode' do 1063 | expect(DefaultUser.new(:email => valid_email)).to be_valid 1064 | end 1065 | 1066 | it 'invalidates invalid using `:loose` mode' do 1067 | expect(DefaultUser.new(:email => invalid_email)).to be_invalid 1068 | end 1069 | 1070 | context 'when `email_validator/strict` has been required' do 1071 | before { require 'email_validator/strict' } 1072 | 1073 | it 'validates valid using `:strict` mode' do 1074 | expect(DefaultUser.new(:email => valid_email)).to be_valid 1075 | end 1076 | 1077 | it 'invalidates invalid using `:strict` mode' do 1078 | expect(DefaultUser.new(:email => invalid_email)).to be_invalid 1079 | end 1080 | end 1081 | 1082 | context 'when `email_validator/rfc` has been required' do 1083 | before { require 'email_validator/rfc' } 1084 | 1085 | it 'validates valid using `:rfc` mode' do 1086 | expect(DefaultUser.new(:email => valid_email)).to be_valid 1087 | end 1088 | 1089 | it 'invalidates invalid using `:rfc` mode' do 1090 | expect(DefaultUser.new(:email => invalid_email)).to be_invalid 1091 | end 1092 | end 1093 | end 1094 | 1095 | context 'with regexp' do 1096 | it 'returns a regexp when asked' do 1097 | expect(described_class.regexp).to be_a(Regexp) 1098 | end 1099 | 1100 | it 'returns a strict regexp when asked' do 1101 | expect(described_class.regexp(:mode => :strict)).to be_a(Regexp) 1102 | end 1103 | 1104 | it 'returns a RFC regexp when asked' do 1105 | expect(described_class.regexp(:mode => :rfc)).to be_a(Regexp) 1106 | end 1107 | 1108 | it 'has different regexp for strict and loose' do 1109 | expect(described_class.regexp(:mode => :strict)).not_to eq(described_class.regexp(:mode => :loose)) 1110 | end 1111 | 1112 | it 'has different regexp for RFC and loose' do 1113 | expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :loose)) 1114 | end 1115 | 1116 | it 'has different regexp for RFC and strict' do 1117 | expect(described_class.regexp(:mode => :rfc)).not_to eq(described_class.regexp(:mode => :strict)) 1118 | end 1119 | end 1120 | 1121 | context 'with invalid `:mode`' do 1122 | it 'raises an error' do 1123 | expect { described_class.regexp(:mode => :invalid) }.to raise_error(EmailValidator::Error) 1124 | end 1125 | end 1126 | end 1127 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'rubygems' 4 | require 'pry' 5 | require 'rspec' 6 | require 'active_model' 7 | 8 | I18n.enforce_available_locales = false 9 | 10 | require 'simplecov' 11 | SimpleCov.start 'rails' 12 | 13 | $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib')) 14 | $LOAD_PATH.unshift(File.dirname(__FILE__)) 15 | 16 | require 'email_validator' 17 | 18 | class TestModel 19 | include ActiveModel::Validations 20 | 21 | def initialize(attributes = {}) 22 | @attributes = attributes 23 | end 24 | 25 | def read_attribute_for_validation(key) 26 | @attributes[key] 27 | end 28 | end 29 | 30 | RSpec.configure(&:disable_monkey_patching!) 31 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.10.4" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" 8 | integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== 9 | dependencies: 10 | "@babel/highlight" "^7.10.4" 11 | 12 | "@babel/helper-validator-identifier@^7.10.4": 13 | version "7.10.4" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" 15 | integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== 16 | 17 | "@babel/highlight@^7.10.4": 18 | version "7.10.4" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" 20 | integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.10.4" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@types/normalize-package-data@^2.4.0": 27 | version "2.4.0" 28 | resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" 29 | integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== 30 | 31 | agent-base@6: 32 | version "6.0.2" 33 | resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" 34 | integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== 35 | dependencies: 36 | debug "4" 37 | 38 | ansi-escapes@^1.0.0: 39 | version "1.4.0" 40 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 41 | integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= 42 | 43 | ansi-regex@^2.0.0: 44 | version "2.1.1" 45 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 46 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 47 | 48 | ansi-regex@^3.0.0: 49 | version "3.0.0" 50 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 51 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 52 | 53 | ansi-styles@^2.2.1: 54 | version "2.2.1" 55 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 56 | integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= 57 | 58 | ansi-styles@^3.2.0, ansi-styles@^3.2.1: 59 | version "3.2.1" 60 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 61 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 62 | dependencies: 63 | color-convert "^1.9.0" 64 | 65 | any-observable@^0.2.0: 66 | version "0.2.0" 67 | resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.2.0.tgz#c67870058003579009083f54ac0abafb5c33d242" 68 | integrity sha1-xnhwBYADV5AJCD9UrAq6+1wz0kI= 69 | 70 | app-root-path@^2.0.0: 71 | version "2.2.1" 72 | resolved "https://registry.yarnpkg.com/app-root-path/-/app-root-path-2.2.1.tgz#d0df4a682ee408273583d43f6f79e9892624bc9a" 73 | integrity sha512-91IFKeKk7FjfmezPKkwtaRvSpnUc4gDwPAjA1YZ9Gn0q0PPeW+vbeUsZuyDwjI7+QTHhcLen2v25fi/AmhvbJA== 74 | 75 | argparse@^1.0.7: 76 | version "1.0.10" 77 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 78 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 79 | dependencies: 80 | sprintf-js "~1.0.2" 81 | 82 | async@^1.4.0: 83 | version "1.5.2" 84 | resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" 85 | integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= 86 | 87 | balanced-match@^1.0.0: 88 | version "1.0.0" 89 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 90 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 91 | 92 | brace-expansion@^1.1.7: 93 | version "1.1.11" 94 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 95 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 96 | dependencies: 97 | balanced-match "^1.0.0" 98 | concat-map "0.0.1" 99 | 100 | caller-callsite@^2.0.0: 101 | version "2.0.0" 102 | resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" 103 | integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= 104 | dependencies: 105 | callsites "^2.0.0" 106 | 107 | caller-path@^2.0.0: 108 | version "2.0.0" 109 | resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" 110 | integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= 111 | dependencies: 112 | caller-callsite "^2.0.0" 113 | 114 | callsites@^2.0.0: 115 | version "2.0.0" 116 | resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" 117 | integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= 118 | 119 | camelcase@^2.0.1: 120 | version "2.1.1" 121 | resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" 122 | integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= 123 | 124 | chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: 125 | version "1.1.3" 126 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 127 | integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= 128 | dependencies: 129 | ansi-styles "^2.2.1" 130 | escape-string-regexp "^1.0.2" 131 | has-ansi "^2.0.0" 132 | strip-ansi "^3.0.0" 133 | supports-color "^2.0.0" 134 | 135 | chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: 136 | version "2.4.2" 137 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 138 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 139 | dependencies: 140 | ansi-styles "^3.2.1" 141 | escape-string-regexp "^1.0.5" 142 | supports-color "^5.3.0" 143 | 144 | chownr@^2.0.0: 145 | version "2.0.0" 146 | resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" 147 | integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== 148 | 149 | ci-info@^2.0.0: 150 | version "2.0.0" 151 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" 152 | integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== 153 | 154 | cli-cursor@^1.0.2: 155 | version "1.0.2" 156 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" 157 | integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= 158 | dependencies: 159 | restore-cursor "^1.0.1" 160 | 161 | cli-spinners@^0.1.2: 162 | version "0.1.2" 163 | resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" 164 | integrity sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw= 165 | 166 | cli-truncate@^0.2.1: 167 | version "0.2.1" 168 | resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" 169 | integrity sha1-nxXPuwcFAFNpIWxiasfQWrkN1XQ= 170 | dependencies: 171 | slice-ansi "0.0.4" 172 | string-width "^1.0.1" 173 | 174 | cliui@^3.0.3: 175 | version "3.2.0" 176 | resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" 177 | integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= 178 | dependencies: 179 | string-width "^1.0.1" 180 | strip-ansi "^3.0.1" 181 | wrap-ansi "^2.0.0" 182 | 183 | code-point-at@^1.0.0: 184 | version "1.1.0" 185 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 186 | integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 187 | 188 | color-convert@^1.9.0: 189 | version "1.9.3" 190 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 191 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 192 | dependencies: 193 | color-name "1.1.3" 194 | 195 | color-name@1.1.3: 196 | version "1.1.3" 197 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 198 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 199 | 200 | commander@^2.11.0, commander@^2.9.0: 201 | version "2.20.3" 202 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 203 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 204 | 205 | commander@~2.9.0: 206 | version "2.9.0" 207 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 208 | integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= 209 | dependencies: 210 | graceful-readlink ">= 1.0.0" 211 | 212 | concat-map@0.0.1: 213 | version "0.0.1" 214 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 215 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 216 | 217 | cosmiconfig@^4.0.0: 218 | version "4.0.0" 219 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" 220 | integrity sha512-6e5vDdrXZD+t5v0L8CrurPeybg4Fmf+FCSYxXKYVAqLUtyCSbuyqE059d0kDthTNRzKVjL7QMgNpEUlsoYH3iQ== 221 | dependencies: 222 | is-directory "^0.3.1" 223 | js-yaml "^3.9.0" 224 | parse-json "^4.0.0" 225 | require-from-string "^2.0.1" 226 | 227 | cosmiconfig@^5.2.0: 228 | version "5.2.1" 229 | resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" 230 | integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== 231 | dependencies: 232 | import-fresh "^2.0.0" 233 | is-directory "^0.3.1" 234 | js-yaml "^3.13.1" 235 | parse-json "^4.0.0" 236 | 237 | cross-spawn@^5.0.1: 238 | version "5.1.0" 239 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" 240 | integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= 241 | dependencies: 242 | lru-cache "^4.0.1" 243 | shebang-command "^1.2.0" 244 | which "^1.2.9" 245 | 246 | cross-spawn@^6.0.0: 247 | version "6.0.5" 248 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" 249 | integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== 250 | dependencies: 251 | nice-try "^1.0.4" 252 | path-key "^2.0.1" 253 | semver "^5.5.0" 254 | shebang-command "^1.2.0" 255 | which "^1.2.9" 256 | 257 | date-fns@^1.27.2: 258 | version "1.30.1" 259 | resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.30.1.tgz#2e71bf0b119153dbb4cc4e88d9ea5acfb50dc05c" 260 | integrity sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw== 261 | 262 | debug@4: 263 | version "4.3.1" 264 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" 265 | integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== 266 | dependencies: 267 | ms "2.1.2" 268 | 269 | debug@^3.1.0: 270 | version "3.2.7" 271 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" 272 | integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== 273 | dependencies: 274 | ms "^2.1.1" 275 | 276 | decamelize@^1.1.1: 277 | version "1.2.0" 278 | resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" 279 | integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= 280 | 281 | dedent@^0.7.0: 282 | version "0.7.0" 283 | resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" 284 | integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= 285 | 286 | deep-extend@^0.6.0: 287 | version "0.6.0" 288 | resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" 289 | integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== 290 | 291 | deep-extend@~0.5.1: 292 | version "0.5.1" 293 | resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.5.1.tgz#b894a9dd90d3023fbf1c55a394fb858eb2066f1f" 294 | integrity sha512-N8vBdOa+DF7zkRrDCsaOXoCs/E2fJfx9B9MrKnnSiHNh4ws7eSys6YQE4KvT1cecKmOASYQBhbKjeuDD9lT81w== 295 | 296 | editorconfig-checker@^3.0.3: 297 | version "3.3.0" 298 | resolved "https://registry.yarnpkg.com/editorconfig-checker/-/editorconfig-checker-3.3.0.tgz#a354e9d7903d392a8f14586f0b965255caba1acc" 299 | integrity sha512-WJ/P5/wPU87qXen/79e7iwBu1SNpr6ZVe7LzTQdp5Ft7IfMaS4GldAQsPDSRcbMjSYzQd2trADNGPY1DZBWFBA== 300 | dependencies: 301 | https-proxy-agent "^5.0.0" 302 | node-fetch "^2.6.0" 303 | tar "^6.0.0" 304 | 305 | elegant-spinner@^1.0.1: 306 | version "1.0.1" 307 | resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" 308 | integrity sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4= 309 | 310 | end-of-stream@^1.1.0: 311 | version "1.4.4" 312 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 313 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 314 | dependencies: 315 | once "^1.4.0" 316 | 317 | entities@~1.1.1: 318 | version "1.1.2" 319 | resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" 320 | integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== 321 | 322 | error-ex@^1.3.1: 323 | version "1.3.2" 324 | resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" 325 | integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== 326 | dependencies: 327 | is-arrayish "^0.2.1" 328 | 329 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 330 | version "1.0.5" 331 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 332 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 333 | 334 | esprima@^4.0.0: 335 | version "4.0.1" 336 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 337 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 338 | 339 | execa@^0.8.0: 340 | version "0.8.0" 341 | resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" 342 | integrity sha1-2NdrvBtVIX7RkP1t1J08d07PyNo= 343 | dependencies: 344 | cross-spawn "^5.0.1" 345 | get-stream "^3.0.0" 346 | is-stream "^1.1.0" 347 | npm-run-path "^2.0.0" 348 | p-finally "^1.0.0" 349 | signal-exit "^3.0.0" 350 | strip-eof "^1.0.0" 351 | 352 | execa@^1.0.0: 353 | version "1.0.0" 354 | resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" 355 | integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== 356 | dependencies: 357 | cross-spawn "^6.0.0" 358 | get-stream "^4.0.0" 359 | is-stream "^1.1.0" 360 | npm-run-path "^2.0.0" 361 | p-finally "^1.0.0" 362 | signal-exit "^3.0.0" 363 | strip-eof "^1.0.0" 364 | 365 | exit-hook@^1.0.0: 366 | version "1.1.1" 367 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" 368 | integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= 369 | 370 | figures@^1.7.0: 371 | version "1.7.0" 372 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 373 | integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= 374 | dependencies: 375 | escape-string-regexp "^1.0.5" 376 | object-assign "^4.1.0" 377 | 378 | find-parent-dir@^0.3.0: 379 | version "0.3.0" 380 | resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" 381 | integrity sha1-M8RLQpqysvBkYpnF+fcY83b/jVQ= 382 | 383 | find-up@^3.0.0: 384 | version "3.0.0" 385 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" 386 | integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== 387 | dependencies: 388 | locate-path "^3.0.0" 389 | 390 | find-up@^4.0.0: 391 | version "4.1.0" 392 | resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" 393 | integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== 394 | dependencies: 395 | locate-path "^5.0.0" 396 | path-exists "^4.0.0" 397 | 398 | fs-minipass@^2.0.0: 399 | version "2.1.0" 400 | resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" 401 | integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== 402 | dependencies: 403 | minipass "^3.0.0" 404 | 405 | fs.realpath@^1.0.0: 406 | version "1.0.0" 407 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 408 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 409 | 410 | function-bind@^1.1.1: 411 | version "1.1.1" 412 | resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" 413 | integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== 414 | 415 | get-own-enumerable-property-symbols@^3.0.0: 416 | version "3.0.2" 417 | resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" 418 | integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== 419 | 420 | get-stdin@^7.0.0: 421 | version "7.0.0" 422 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-7.0.0.tgz#8d5de98f15171a125c5e516643c7a6d0ea8a96f6" 423 | integrity sha512-zRKcywvrXlXsA0v0i9Io4KDRaAw7+a1ZpjRwl9Wox8PFlVCCHra7E9c4kqXCoCM9nR5tBkaTTZRBoCm60bFqTQ== 424 | 425 | get-stdin@~5.0.1: 426 | version "5.0.1" 427 | resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" 428 | integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= 429 | 430 | get-stream@^3.0.0: 431 | version "3.0.0" 432 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" 433 | integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= 434 | 435 | get-stream@^4.0.0: 436 | version "4.1.0" 437 | resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" 438 | integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== 439 | dependencies: 440 | pump "^3.0.0" 441 | 442 | glob@^7.1.2, glob@~7.1.2: 443 | version "7.1.6" 444 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 445 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 446 | dependencies: 447 | fs.realpath "^1.0.0" 448 | inflight "^1.0.4" 449 | inherits "2" 450 | minimatch "^3.0.4" 451 | once "^1.3.0" 452 | path-is-absolute "^1.0.0" 453 | 454 | "graceful-readlink@>= 1.0.0": 455 | version "1.0.1" 456 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 457 | integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= 458 | 459 | has-ansi@^2.0.0: 460 | version "2.0.0" 461 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 462 | integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= 463 | dependencies: 464 | ansi-regex "^2.0.0" 465 | 466 | has-flag@^3.0.0: 467 | version "3.0.0" 468 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 469 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 470 | 471 | has@^1.0.3: 472 | version "1.0.3" 473 | resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" 474 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 475 | dependencies: 476 | function-bind "^1.1.1" 477 | 478 | hosted-git-info@^2.1.4: 479 | version "2.8.9" 480 | resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" 481 | integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== 482 | 483 | https-proxy-agent@^5.0.0: 484 | version "5.0.0" 485 | resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" 486 | integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== 487 | dependencies: 488 | agent-base "6" 489 | debug "4" 490 | 491 | husky@^2.0.0: 492 | version "2.7.0" 493 | resolved "https://registry.yarnpkg.com/husky/-/husky-2.7.0.tgz#c0a9a6a3b51146224e11bba0b46bba546e461d05" 494 | integrity sha512-LIi8zzT6PyFpcYKdvWRCn/8X+6SuG2TgYYMrM6ckEYhlp44UcEduVymZGIZNLiwOUjrEud+78w/AsAiqJA/kRg== 495 | dependencies: 496 | cosmiconfig "^5.2.0" 497 | execa "^1.0.0" 498 | find-up "^3.0.0" 499 | get-stdin "^7.0.0" 500 | is-ci "^2.0.0" 501 | pkg-dir "^4.1.0" 502 | please-upgrade-node "^3.1.1" 503 | read-pkg "^5.1.1" 504 | run-node "^1.0.0" 505 | slash "^3.0.0" 506 | 507 | import-fresh@^2.0.0: 508 | version "2.0.0" 509 | resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" 510 | integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= 511 | dependencies: 512 | caller-path "^2.0.0" 513 | resolve-from "^3.0.0" 514 | 515 | indent-string@^2.1.0: 516 | version "2.1.0" 517 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" 518 | integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= 519 | dependencies: 520 | repeating "^2.0.0" 521 | 522 | indent-string@^3.0.0: 523 | version "3.2.0" 524 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" 525 | integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= 526 | 527 | inflight@^1.0.4: 528 | version "1.0.6" 529 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 530 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 531 | dependencies: 532 | once "^1.3.0" 533 | wrappy "1" 534 | 535 | inherits@2: 536 | version "2.0.4" 537 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 538 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 539 | 540 | ini@^1.3.0, ini@~1.3.0: 541 | version "1.3.6" 542 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.6.tgz#f1c46a2a93a253e7b3905115e74d527cd23061a1" 543 | integrity sha512-IZUoxEjNjubzrmvzZU4lKP7OnYmX72XRl3sqkfJhBKweKi5rnGi5+IUdlj/H1M+Ip5JQ1WzaDMOBRY90Ajc5jg== 544 | 545 | invert-kv@^1.0.0: 546 | version "1.0.0" 547 | resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" 548 | integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= 549 | 550 | is-arrayish@^0.2.1: 551 | version "0.2.1" 552 | resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" 553 | integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= 554 | 555 | is-ci@^2.0.0: 556 | version "2.0.0" 557 | resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" 558 | integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== 559 | dependencies: 560 | ci-info "^2.0.0" 561 | 562 | is-core-module@^2.1.0: 563 | version "2.2.0" 564 | resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" 565 | integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== 566 | dependencies: 567 | has "^1.0.3" 568 | 569 | is-directory@^0.3.1: 570 | version "0.3.1" 571 | resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" 572 | integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= 573 | 574 | is-extglob@^2.1.1: 575 | version "2.1.1" 576 | resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 577 | integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= 578 | 579 | is-finite@^1.0.0: 580 | version "1.1.0" 581 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" 582 | integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== 583 | 584 | is-fullwidth-code-point@^1.0.0: 585 | version "1.0.0" 586 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 587 | integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 588 | dependencies: 589 | number-is-nan "^1.0.0" 590 | 591 | is-glob@^4.0.0: 592 | version "4.0.1" 593 | resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" 594 | integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== 595 | dependencies: 596 | is-extglob "^2.1.1" 597 | 598 | is-obj@^1.0.1: 599 | version "1.0.1" 600 | resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" 601 | integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= 602 | 603 | is-observable@^0.2.0: 604 | version "0.2.0" 605 | resolved "https://registry.yarnpkg.com/is-observable/-/is-observable-0.2.0.tgz#b361311d83c6e5d726cabf5e250b0237106f5ae2" 606 | integrity sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI= 607 | dependencies: 608 | symbol-observable "^0.2.2" 609 | 610 | is-promise@^2.1.0: 611 | version "2.2.2" 612 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" 613 | integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== 614 | 615 | is-regexp@^1.0.0: 616 | version "1.0.0" 617 | resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" 618 | integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= 619 | 620 | is-stream@^1.1.0: 621 | version "1.1.0" 622 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 623 | integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= 624 | 625 | isexe@^2.0.0: 626 | version "2.0.0" 627 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 628 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 629 | 630 | jest-get-type@^21.2.0: 631 | version "21.2.0" 632 | resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23" 633 | integrity sha512-y2fFw3C+D0yjNSDp7ab1kcd6NUYfy3waPTlD8yWkAtiocJdBRQqNoRqVfMNxgj+IjT0V5cBIHJO0z9vuSSZ43Q== 634 | 635 | jest-validate@^21.1.0: 636 | version "21.2.1" 637 | resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7" 638 | integrity sha512-k4HLI1rZQjlU+EC682RlQ6oZvLrE5SCh3brseQc24vbZTxzT/k/3urar5QMCVgjadmSO7lECeGdc6YxnM3yEGg== 639 | dependencies: 640 | chalk "^2.0.1" 641 | jest-get-type "^21.2.0" 642 | leven "^2.1.0" 643 | pretty-format "^21.2.1" 644 | 645 | js-tokens@^4.0.0: 646 | version "4.0.0" 647 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 648 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 649 | 650 | js-yaml@^3.10.0, js-yaml@^3.13.1, js-yaml@^3.9.0: 651 | version "3.14.1" 652 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" 653 | integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== 654 | dependencies: 655 | argparse "^1.0.7" 656 | esprima "^4.0.0" 657 | 658 | json-parse-better-errors@^1.0.1: 659 | version "1.0.2" 660 | resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" 661 | integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== 662 | 663 | json-parse-even-better-errors@^2.3.0: 664 | version "2.3.1" 665 | resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" 666 | integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== 667 | 668 | lcid@^1.0.0: 669 | version "1.0.0" 670 | resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" 671 | integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= 672 | dependencies: 673 | invert-kv "^1.0.0" 674 | 675 | leprechaun@0.0.2: 676 | version "0.0.2" 677 | resolved "https://registry.yarnpkg.com/leprechaun/-/leprechaun-0.0.2.tgz#8b96514a9e634c53fbe59a8094f3378c8fb2084d" 678 | integrity sha1-i5ZRSp5jTFP75ZqAlPM3jI+yCE0= 679 | dependencies: 680 | log-symbols "^1.0.2" 681 | 682 | leven@^2.1.0: 683 | version "2.1.0" 684 | resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" 685 | integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= 686 | 687 | lines-and-columns@^1.1.6: 688 | version "1.1.6" 689 | resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" 690 | integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= 691 | 692 | linkify-it@^2.0.0: 693 | version "2.2.0" 694 | resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" 695 | integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== 696 | dependencies: 697 | uc.micro "^1.0.1" 698 | 699 | lint-staged@^6.0.0: 700 | version "6.1.1" 701 | resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-6.1.1.tgz#cd08c4d9b8ccc2d37198d1c47ce77d22be6cf324" 702 | integrity sha512-M/7bwLdXbeG7ZNLcasGeLMBDg60/w6obj3KOtINwJyxAxb53XGY0yH5FSZlWklEzuVbTtqtIfAajh6jYIN90AA== 703 | dependencies: 704 | app-root-path "^2.0.0" 705 | chalk "^2.1.0" 706 | commander "^2.11.0" 707 | cosmiconfig "^4.0.0" 708 | debug "^3.1.0" 709 | dedent "^0.7.0" 710 | execa "^0.8.0" 711 | find-parent-dir "^0.3.0" 712 | is-glob "^4.0.0" 713 | jest-validate "^21.1.0" 714 | listr "^0.13.0" 715 | lodash "^4.17.4" 716 | log-symbols "^2.0.0" 717 | minimatch "^3.0.0" 718 | npm-which "^3.0.1" 719 | p-map "^1.1.1" 720 | path-is-inside "^1.0.2" 721 | pify "^3.0.0" 722 | staged-git-files "1.0.0" 723 | stringify-object "^3.2.0" 724 | 725 | listr-silent-renderer@^1.1.1: 726 | version "1.1.1" 727 | resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" 728 | integrity sha1-kktaN1cVN3C/Go4/v3S4u/P5JC4= 729 | 730 | listr-update-renderer@^0.4.0: 731 | version "0.4.0" 732 | resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.4.0.tgz#344d980da2ca2e8b145ba305908f32ae3f4cc8a7" 733 | integrity sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc= 734 | dependencies: 735 | chalk "^1.1.3" 736 | cli-truncate "^0.2.1" 737 | elegant-spinner "^1.0.1" 738 | figures "^1.7.0" 739 | indent-string "^3.0.0" 740 | log-symbols "^1.0.2" 741 | log-update "^1.0.2" 742 | strip-ansi "^3.0.1" 743 | 744 | listr-verbose-renderer@^0.4.0: 745 | version "0.4.1" 746 | resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" 747 | integrity sha1-ggb0z21S3cWCfl/RSYng6WWTOjU= 748 | dependencies: 749 | chalk "^1.1.3" 750 | cli-cursor "^1.0.2" 751 | date-fns "^1.27.2" 752 | figures "^1.7.0" 753 | 754 | listr@^0.13.0: 755 | version "0.13.0" 756 | resolved "https://registry.yarnpkg.com/listr/-/listr-0.13.0.tgz#20bb0ba30bae660ee84cc0503df4be3d5623887d" 757 | integrity sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0= 758 | dependencies: 759 | chalk "^1.1.3" 760 | cli-truncate "^0.2.1" 761 | figures "^1.7.0" 762 | indent-string "^2.1.0" 763 | is-observable "^0.2.0" 764 | is-promise "^2.1.0" 765 | is-stream "^1.1.0" 766 | listr-silent-renderer "^1.1.1" 767 | listr-update-renderer "^0.4.0" 768 | listr-verbose-renderer "^0.4.0" 769 | log-symbols "^1.0.2" 770 | log-update "^1.0.2" 771 | ora "^0.2.3" 772 | p-map "^1.1.1" 773 | rxjs "^5.4.2" 774 | stream-to-observable "^0.2.0" 775 | strip-ansi "^3.0.1" 776 | 777 | locate-path@^3.0.0: 778 | version "3.0.0" 779 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" 780 | integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== 781 | dependencies: 782 | p-locate "^3.0.0" 783 | path-exists "^3.0.0" 784 | 785 | locate-path@^5.0.0: 786 | version "5.0.0" 787 | resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" 788 | integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== 789 | dependencies: 790 | p-locate "^4.1.0" 791 | 792 | lodash.differencewith@~4.5.0: 793 | version "4.5.0" 794 | resolved "https://registry.yarnpkg.com/lodash.differencewith/-/lodash.differencewith-4.5.0.tgz#bafafbc918b55154e179176a00bb0aefaac854b7" 795 | integrity sha1-uvr7yRi1UVTheRdqALsK76rIVLc= 796 | 797 | lodash.flatten@~4.4.0: 798 | version "4.4.0" 799 | resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" 800 | integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= 801 | 802 | lodash.merge@^4.6.1: 803 | version "4.6.2" 804 | resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" 805 | integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== 806 | 807 | lodash.snakecase@^4.1.1: 808 | version "4.1.1" 809 | resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d" 810 | integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40= 811 | 812 | lodash@^4.17.4: 813 | version "4.17.21" 814 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" 815 | integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== 816 | 817 | log-symbols@^1.0.2: 818 | version "1.0.2" 819 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" 820 | integrity sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg= 821 | dependencies: 822 | chalk "^1.0.0" 823 | 824 | log-symbols@^2.0.0: 825 | version "2.2.0" 826 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" 827 | integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== 828 | dependencies: 829 | chalk "^2.0.1" 830 | 831 | log-update@^1.0.2: 832 | version "1.0.2" 833 | resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" 834 | integrity sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE= 835 | dependencies: 836 | ansi-escapes "^1.0.0" 837 | cli-cursor "^1.0.2" 838 | 839 | lru-cache@^4.0.1: 840 | version "4.1.5" 841 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" 842 | integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== 843 | dependencies: 844 | pseudomap "^1.0.2" 845 | yallist "^2.1.2" 846 | 847 | markdown-it@9.0.1: 848 | version "9.0.1" 849 | resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-9.0.1.tgz#aafe363c43718720b6575fd10625cde6e4ff2d47" 850 | integrity sha512-XC9dMBHg28Xi7y5dPuLjM61upIGPJG8AiHNHYqIaXER2KNnn7eKnM5/sF0ImNnyoV224Ogn9b1Pck8VH4k0bxw== 851 | dependencies: 852 | argparse "^1.0.7" 853 | entities "~1.1.1" 854 | linkify-it "^2.0.0" 855 | mdurl "^1.0.1" 856 | uc.micro "^1.0.5" 857 | 858 | markdownlint-cli@^0.18.0: 859 | version "0.18.0" 860 | resolved "https://registry.yarnpkg.com/markdownlint-cli/-/markdownlint-cli-0.18.0.tgz#bd1cee72739049d42dcea5f6db0c0f57c6eb8096" 861 | integrity sha512-mQ2zvjMLoy0P2kb9Y03SqC24WPH4fTRN0/CyCorB122c4Chg9vWJKgUKBz3KR7swpzqmlI0SYq/7Blbqe4kb2g== 862 | dependencies: 863 | commander "~2.9.0" 864 | deep-extend "~0.5.1" 865 | get-stdin "~5.0.1" 866 | glob "~7.1.2" 867 | js-yaml "^3.13.1" 868 | lodash.differencewith "~4.5.0" 869 | lodash.flatten "~4.4.0" 870 | markdownlint "~0.16.0" 871 | minimatch "~3.0.4" 872 | rc "~1.2.7" 873 | 874 | markdownlint@^0.16.0, markdownlint@~0.16.0: 875 | version "0.16.0" 876 | resolved "https://registry.yarnpkg.com/markdownlint/-/markdownlint-0.16.0.tgz#69f73cc755a44231fbe5dc7c37a5909cedc0ac6e" 877 | integrity sha512-Zo+iPezP3eM6lLhKepkUw+X98H44lipIdx4d6faaugfB0+7VuDB3R0hXmx7z9F1N3/ypn46oOFgAD9iF++Ie6A== 878 | dependencies: 879 | markdown-it "9.0.1" 880 | 881 | mdurl@^1.0.1: 882 | version "1.0.1" 883 | resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" 884 | integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= 885 | 886 | minimatch@^3.0.0, minimatch@^3.0.4, minimatch@~3.0.4: 887 | version "3.0.4" 888 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 889 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 890 | dependencies: 891 | brace-expansion "^1.1.7" 892 | 893 | minimist@^1.2.0: 894 | version "1.2.7" 895 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" 896 | integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== 897 | 898 | minipass@^3.0.0: 899 | version "3.1.5" 900 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.5.tgz#71f6251b0a33a49c01b3cf97ff77eda030dff732" 901 | integrity sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw== 902 | dependencies: 903 | yallist "^4.0.0" 904 | 905 | minizlib@^2.1.1: 906 | version "2.1.2" 907 | resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" 908 | integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== 909 | dependencies: 910 | minipass "^3.0.0" 911 | yallist "^4.0.0" 912 | 913 | mkdirp@^1.0.3: 914 | version "1.0.4" 915 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" 916 | integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== 917 | 918 | ms@2.1.2: 919 | version "2.1.2" 920 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 921 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 922 | 923 | ms@^2.1.1: 924 | version "2.1.3" 925 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" 926 | integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== 927 | 928 | nconf@^0.10.0: 929 | version "0.10.0" 930 | resolved "https://registry.yarnpkg.com/nconf/-/nconf-0.10.0.tgz#da1285ee95d0a922ca6cee75adcf861f48205ad2" 931 | integrity sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q== 932 | dependencies: 933 | async "^1.4.0" 934 | ini "^1.3.0" 935 | secure-keys "^1.0.0" 936 | yargs "^3.19.0" 937 | 938 | nice-try@^1.0.4: 939 | version "1.0.5" 940 | resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" 941 | integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== 942 | 943 | node-fetch@^2.6.0: 944 | version "2.6.7" 945 | resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" 946 | integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== 947 | dependencies: 948 | whatwg-url "^5.0.0" 949 | 950 | normalize-package-data@^2.5.0: 951 | version "2.5.0" 952 | resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" 953 | integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== 954 | dependencies: 955 | hosted-git-info "^2.1.4" 956 | resolve "^1.10.0" 957 | semver "2 || 3 || 4 || 5" 958 | validate-npm-package-license "^3.0.1" 959 | 960 | npm-path@^2.0.2: 961 | version "2.0.4" 962 | resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" 963 | integrity sha512-IFsj0R9C7ZdR5cP+ET342q77uSRdtWOlWpih5eC+lu29tIDbNEgDbzgVJ5UFvYHWhxDZ5TFkJafFioO0pPQjCw== 964 | dependencies: 965 | which "^1.2.10" 966 | 967 | npm-run-path@^2.0.0: 968 | version "2.0.2" 969 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" 970 | integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= 971 | dependencies: 972 | path-key "^2.0.0" 973 | 974 | npm-which@^3.0.1: 975 | version "3.0.1" 976 | resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" 977 | integrity sha1-kiXybsOihcIJyuZ8OxGmtKtxQKo= 978 | dependencies: 979 | commander "^2.9.0" 980 | npm-path "^2.0.2" 981 | which "^1.2.10" 982 | 983 | number-is-nan@^1.0.0: 984 | version "1.0.1" 985 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 986 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 987 | 988 | object-assign@^4.0.1, object-assign@^4.1.0: 989 | version "4.1.1" 990 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 991 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 992 | 993 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 994 | version "1.4.0" 995 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 996 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 997 | dependencies: 998 | wrappy "1" 999 | 1000 | onetime@^1.0.0: 1001 | version "1.1.0" 1002 | resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" 1003 | integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= 1004 | 1005 | ora@^0.2.3: 1006 | version "0.2.3" 1007 | resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" 1008 | integrity sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q= 1009 | dependencies: 1010 | chalk "^1.1.1" 1011 | cli-cursor "^1.0.2" 1012 | cli-spinners "^0.1.2" 1013 | object-assign "^4.0.1" 1014 | 1015 | os-locale@^1.4.0: 1016 | version "1.4.0" 1017 | resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" 1018 | integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= 1019 | dependencies: 1020 | lcid "^1.0.0" 1021 | 1022 | p-finally@^1.0.0: 1023 | version "1.0.0" 1024 | resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" 1025 | integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= 1026 | 1027 | p-limit@^2.0.0, p-limit@^2.2.0: 1028 | version "2.3.0" 1029 | resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" 1030 | integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== 1031 | dependencies: 1032 | p-try "^2.0.0" 1033 | 1034 | p-locate@^3.0.0: 1035 | version "3.0.0" 1036 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" 1037 | integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== 1038 | dependencies: 1039 | p-limit "^2.0.0" 1040 | 1041 | p-locate@^4.1.0: 1042 | version "4.1.0" 1043 | resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" 1044 | integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== 1045 | dependencies: 1046 | p-limit "^2.2.0" 1047 | 1048 | p-map@^1.1.1: 1049 | version "1.2.0" 1050 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" 1051 | integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== 1052 | 1053 | p-try@^2.0.0: 1054 | version "2.2.0" 1055 | resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" 1056 | integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== 1057 | 1058 | parse-json@^4.0.0: 1059 | version "4.0.0" 1060 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" 1061 | integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= 1062 | dependencies: 1063 | error-ex "^1.3.1" 1064 | json-parse-better-errors "^1.0.1" 1065 | 1066 | parse-json@^5.0.0: 1067 | version "5.1.0" 1068 | resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" 1069 | integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ== 1070 | dependencies: 1071 | "@babel/code-frame" "^7.0.0" 1072 | error-ex "^1.3.1" 1073 | json-parse-even-better-errors "^2.3.0" 1074 | lines-and-columns "^1.1.6" 1075 | 1076 | path-exists@^3.0.0: 1077 | version "3.0.0" 1078 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" 1079 | integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= 1080 | 1081 | path-exists@^4.0.0: 1082 | version "4.0.0" 1083 | resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" 1084 | integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== 1085 | 1086 | path-is-absolute@^1.0.0: 1087 | version "1.0.1" 1088 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 1089 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 1090 | 1091 | path-is-inside@^1.0.2: 1092 | version "1.0.2" 1093 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 1094 | integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= 1095 | 1096 | path-key@^2.0.0, path-key@^2.0.1: 1097 | version "2.0.1" 1098 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" 1099 | integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= 1100 | 1101 | path-parse@^1.0.6: 1102 | version "1.0.7" 1103 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" 1104 | integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== 1105 | 1106 | pify@^3.0.0: 1107 | version "3.0.0" 1108 | resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" 1109 | integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= 1110 | 1111 | pkg-dir@^4.1.0: 1112 | version "4.2.0" 1113 | resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" 1114 | integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== 1115 | dependencies: 1116 | find-up "^4.0.0" 1117 | 1118 | please-upgrade-node@^3.1.1: 1119 | version "3.2.0" 1120 | resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" 1121 | integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg== 1122 | dependencies: 1123 | semver-compare "^1.0.0" 1124 | 1125 | prettier@^1.11.0: 1126 | version "1.19.1" 1127 | resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" 1128 | integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== 1129 | 1130 | pretty-format@^21.2.1: 1131 | version "21.2.1" 1132 | resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36" 1133 | integrity sha512-ZdWPGYAnYfcVP8yKA3zFjCn8s4/17TeYH28MXuC8vTp0o21eXjbFGcOAXZEaDaOFJjc3h2qa7HQNHNshhvoh2A== 1134 | dependencies: 1135 | ansi-regex "^3.0.0" 1136 | ansi-styles "^3.2.0" 1137 | 1138 | pseudomap@^1.0.2: 1139 | version "1.0.2" 1140 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 1141 | integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= 1142 | 1143 | pump@^3.0.0: 1144 | version "3.0.0" 1145 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 1146 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 1147 | dependencies: 1148 | end-of-stream "^1.1.0" 1149 | once "^1.3.1" 1150 | 1151 | rc@~1.2.7: 1152 | version "1.2.8" 1153 | resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" 1154 | integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== 1155 | dependencies: 1156 | deep-extend "^0.6.0" 1157 | ini "~1.3.0" 1158 | minimist "^1.2.0" 1159 | strip-json-comments "~2.0.1" 1160 | 1161 | read-pkg@^5.1.1: 1162 | version "5.2.0" 1163 | resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" 1164 | integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== 1165 | dependencies: 1166 | "@types/normalize-package-data" "^2.4.0" 1167 | normalize-package-data "^2.5.0" 1168 | parse-json "^5.0.0" 1169 | type-fest "^0.6.0" 1170 | 1171 | repeating@^2.0.0: 1172 | version "2.0.1" 1173 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 1174 | integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= 1175 | dependencies: 1176 | is-finite "^1.0.0" 1177 | 1178 | require-from-string@^2.0.1: 1179 | version "2.0.2" 1180 | resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" 1181 | integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== 1182 | 1183 | resolve-from@^3.0.0: 1184 | version "3.0.0" 1185 | resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" 1186 | integrity sha1-six699nWiBvItuZTM17rywoYh0g= 1187 | 1188 | resolve@^1.10.0: 1189 | version "1.19.0" 1190 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" 1191 | integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== 1192 | dependencies: 1193 | is-core-module "^2.1.0" 1194 | path-parse "^1.0.6" 1195 | 1196 | restore-cursor@^1.0.1: 1197 | version "1.0.1" 1198 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" 1199 | integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= 1200 | dependencies: 1201 | exit-hook "^1.0.0" 1202 | onetime "^1.0.0" 1203 | 1204 | run-node@^1.0.0: 1205 | version "1.0.0" 1206 | resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" 1207 | integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A== 1208 | 1209 | rxjs@^5.4.2: 1210 | version "5.5.12" 1211 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.12.tgz#6fa61b8a77c3d793dbaf270bee2f43f652d741cc" 1212 | integrity sha512-xx2itnL5sBbqeeiVgNPVuQQ1nC8Jp2WfNJhXWHmElW9YmrpS9UVnNzhP3EH3HFqexO5Tlp8GhYY+WEcqcVMvGw== 1213 | dependencies: 1214 | symbol-observable "1.0.1" 1215 | 1216 | secure-keys@^1.0.0: 1217 | version "1.0.0" 1218 | resolved "https://registry.yarnpkg.com/secure-keys/-/secure-keys-1.0.0.tgz#f0c82d98a3b139a8776a8808050b824431087fca" 1219 | integrity sha1-8MgtmKOxOah3aogIBQuCRDEIf8o= 1220 | 1221 | semver-compare@^1.0.0: 1222 | version "1.0.0" 1223 | resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc" 1224 | integrity sha1-De4hahyUGrN+nvsXiPavxf9VN/w= 1225 | 1226 | "semver@2 || 3 || 4 || 5", semver@^5.5.0: 1227 | version "5.7.1" 1228 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 1229 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 1230 | 1231 | shebang-command@^1.2.0: 1232 | version "1.2.0" 1233 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 1234 | integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= 1235 | dependencies: 1236 | shebang-regex "^1.0.0" 1237 | 1238 | shebang-regex@^1.0.0: 1239 | version "1.0.0" 1240 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 1241 | integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= 1242 | 1243 | signal-exit@^3.0.0: 1244 | version "3.0.3" 1245 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 1246 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 1247 | 1248 | slash@^3.0.0: 1249 | version "3.0.0" 1250 | resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" 1251 | integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== 1252 | 1253 | slice-ansi@0.0.4: 1254 | version "0.0.4" 1255 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" 1256 | integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= 1257 | 1258 | spdx-correct@^3.0.0: 1259 | version "3.1.1" 1260 | resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" 1261 | integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== 1262 | dependencies: 1263 | spdx-expression-parse "^3.0.0" 1264 | spdx-license-ids "^3.0.0" 1265 | 1266 | spdx-exceptions@^2.1.0: 1267 | version "2.3.0" 1268 | resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" 1269 | integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== 1270 | 1271 | spdx-expression-parse@^3.0.0: 1272 | version "3.0.1" 1273 | resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" 1274 | integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== 1275 | dependencies: 1276 | spdx-exceptions "^2.1.0" 1277 | spdx-license-ids "^3.0.0" 1278 | 1279 | spdx-license-ids@^3.0.0: 1280 | version "3.0.7" 1281 | resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" 1282 | integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== 1283 | 1284 | sprintf-js@~1.0.2: 1285 | version "1.0.3" 1286 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 1287 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 1288 | 1289 | staged-git-files@1.0.0: 1290 | version "1.0.0" 1291 | resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.0.0.tgz#cdb847837c1fcc52c08a872d4883cc0877668a80" 1292 | integrity sha1-zbhHg3wfzFLAioctSIPMCHdmioA= 1293 | 1294 | stream-to-observable@^0.2.0: 1295 | version "0.2.0" 1296 | resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.2.0.tgz#59d6ea393d87c2c0ddac10aa0d561bc6ba6f0e10" 1297 | integrity sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA= 1298 | dependencies: 1299 | any-observable "^0.2.0" 1300 | 1301 | string-width@^1.0.1: 1302 | version "1.0.2" 1303 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 1304 | integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 1305 | dependencies: 1306 | code-point-at "^1.0.0" 1307 | is-fullwidth-code-point "^1.0.0" 1308 | strip-ansi "^3.0.0" 1309 | 1310 | stringify-object@^3.2.0: 1311 | version "3.3.0" 1312 | resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" 1313 | integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== 1314 | dependencies: 1315 | get-own-enumerable-property-symbols "^3.0.0" 1316 | is-obj "^1.0.1" 1317 | is-regexp "^1.0.0" 1318 | 1319 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 1320 | version "3.0.1" 1321 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 1322 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 1323 | dependencies: 1324 | ansi-regex "^2.0.0" 1325 | 1326 | strip-eof@^1.0.0: 1327 | version "1.0.0" 1328 | resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" 1329 | integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= 1330 | 1331 | strip-json-comments@~2.0.1: 1332 | version "2.0.1" 1333 | resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" 1334 | integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= 1335 | 1336 | supports-color@^2.0.0: 1337 | version "2.0.0" 1338 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 1339 | integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= 1340 | 1341 | supports-color@^5.3.0: 1342 | version "5.5.0" 1343 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 1344 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 1345 | dependencies: 1346 | has-flag "^3.0.0" 1347 | 1348 | symbol-observable@1.0.1: 1349 | version "1.0.1" 1350 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" 1351 | integrity sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ= 1352 | 1353 | symbol-observable@^0.2.2: 1354 | version "0.2.4" 1355 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-0.2.4.tgz#95a83db26186d6af7e7a18dbd9760a2f86d08f40" 1356 | integrity sha1-lag9smGG1q9+ehjb2XYKL4bQj0A= 1357 | 1358 | tar@^6.0.0: 1359 | version "6.1.11" 1360 | resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621" 1361 | integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA== 1362 | dependencies: 1363 | chownr "^2.0.0" 1364 | fs-minipass "^2.0.0" 1365 | minipass "^3.0.0" 1366 | minizlib "^2.1.1" 1367 | mkdirp "^1.0.3" 1368 | yallist "^4.0.0" 1369 | 1370 | tr46@~0.0.3: 1371 | version "0.0.3" 1372 | resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" 1373 | integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== 1374 | 1375 | type-fest@^0.6.0: 1376 | version "0.6.0" 1377 | resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" 1378 | integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== 1379 | 1380 | uc.micro@^1.0.1, uc.micro@^1.0.5: 1381 | version "1.0.6" 1382 | resolved "https://registry.yarnpkg.com/uc.micro/-/uc.micro-1.0.6.tgz#9c411a802a409a91fc6cf74081baba34b24499ac" 1383 | integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== 1384 | 1385 | validate-npm-package-license@^3.0.1: 1386 | version "3.0.4" 1387 | resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" 1388 | integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== 1389 | dependencies: 1390 | spdx-correct "^3.0.0" 1391 | spdx-expression-parse "^3.0.0" 1392 | 1393 | webidl-conversions@^3.0.0: 1394 | version "3.0.1" 1395 | resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" 1396 | integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== 1397 | 1398 | whatwg-url@^5.0.0: 1399 | version "5.0.0" 1400 | resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" 1401 | integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== 1402 | dependencies: 1403 | tr46 "~0.0.3" 1404 | webidl-conversions "^3.0.0" 1405 | 1406 | which@^1.2.10, which@^1.2.9: 1407 | version "1.3.1" 1408 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1409 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 1410 | dependencies: 1411 | isexe "^2.0.0" 1412 | 1413 | window-size@^0.1.4: 1414 | version "0.1.4" 1415 | resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.1.4.tgz#f8e1aa1ee5a53ec5bf151ffa09742a6ad7697876" 1416 | integrity sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY= 1417 | 1418 | wrap-ansi@^2.0.0: 1419 | version "2.1.0" 1420 | resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" 1421 | integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= 1422 | dependencies: 1423 | string-width "^1.0.1" 1424 | strip-ansi "^3.0.1" 1425 | 1426 | wrappy@1: 1427 | version "1.0.2" 1428 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1429 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1430 | 1431 | y18n@^3.2.0: 1432 | version "3.2.2" 1433 | resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" 1434 | integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== 1435 | 1436 | yallist@^2.1.2: 1437 | version "2.1.2" 1438 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 1439 | integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= 1440 | 1441 | yallist@^4.0.0: 1442 | version "4.0.0" 1443 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" 1444 | integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== 1445 | 1446 | yaml-lint@^1.2.4: 1447 | version "1.2.4" 1448 | resolved "https://registry.yarnpkg.com/yaml-lint/-/yaml-lint-1.2.4.tgz#0dec2d1ef4e5ec999bba1e34d618fc60498d1bc5" 1449 | integrity sha512-qpKE0szyKsE9TrlVPi+bxKxVAjl30QjNAOyOxy7noQdf/WCCYUlT4xiCRxMG48eyeBzMBtBN6PgGfaB0MJePNw== 1450 | dependencies: 1451 | glob "^7.1.2" 1452 | js-yaml "^3.10.0" 1453 | leprechaun "0.0.2" 1454 | lodash.merge "^4.6.1" 1455 | lodash.snakecase "^4.1.1" 1456 | nconf "^0.10.0" 1457 | 1458 | yargs@^3.19.0: 1459 | version "3.32.0" 1460 | resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995" 1461 | integrity sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU= 1462 | dependencies: 1463 | camelcase "^2.0.1" 1464 | cliui "^3.0.3" 1465 | decamelize "^1.1.1" 1466 | os-locale "^1.4.0" 1467 | string-width "^1.0.1" 1468 | window-size "^0.1.4" 1469 | y18n "^3.2.0" 1470 | --------------------------------------------------------------------------------