Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement isemail v4 #200

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"presets": [
"@babel/flow"
],
"plugins": [
"@babel/plugin-transform-flow-strip-types",
"@babel/plugin-transform-modules-commonjs"
]
}
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/dist
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "hapi"
}
11 changes: 11 additions & 0 deletions .flowconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[ignore]

[include]

[libs]

[lints]

[options]

[strict]
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/coverage.html
/coverage.lcov
/dist
/node_modules
29 changes: 29 additions & 0 deletions .lab.transform.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict';

const Babel = require('@babel/core');

const internals = {
GEN_COV_HTML: !!process.env.GEN_COV_HTML
};

// Adapted from https://github.com/hapijs/lab/issues/338 and
// https://github.com/nlf/lab-babel (which doesn't yet support Babel v7).
module.exports = [{
ext: '.js',
transform(content, filename) {

if (filename.startsWith('node_modules')) {
return content;
}

return Babel.transformSync(content, {
auxiliaryCommentBefore: '$lab:coverage:off$',
auxiliaryCommentAfter: '$lab:coverage:on$',
filename,
retainLines: !internals.GEN_COV_HTML,
sourceFileName: filename,
sourceMap: internals.GEN_COV_HTML ? 'inline' : false,
sourceType: 'module'
}).code;
}
}];
3 changes: 3 additions & 0 deletions flow-typed/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "../lib/.eslintrc.json"
}
84 changes: 84 additions & 0 deletions flow-typed/npm/punycode_v2.x.x.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// flow-typed signature: ff1199d785cbf7a22553277f393e5fb0
// flow-typed version: <<STUB>>/punycode_v2.1.1/flow_v0.92.1

// From
// https://github.com/flow-typed/flow-typed/blob/9d7a8571fde3e7573486d8262a1b29dfe9ab2df8/definitions/npm/punycode_v2.1.x/flow_v0.30.x-/punycode_v2.1.x.js
// because flow-typed wasn't cooperating.
declare module 'punycode' {
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @param {String} string The Unicode input string (UCS-2).
* @return {Array} The new array of code points.
*/
declare function ucs2decode(string: string): Array<number>;

/**
* Creates a string based on an array of numeric code points.
* @param {Array} codePoints The array of numeric code points.
* @return {String} The new Unicode string (UCS-2).
*/
declare function ucs2encode(codePoints: Array<number>): string;

/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @param {String} input The Punycode string of ASCII-only symbols.
* @return {String} The resulting string of Unicode symbols.
*/
declare function decode(input: string): string;

/**
* Converts a string of Unicode symbols (e.g. a domain name label) to a
* Punycode string of ASCII-only symbols.
* @param {String} input The string of Unicode symbols.
* @return {String} The resulting Punycode string of ASCII-only symbols.
*/
declare function encode(input: string): string;

/**
* Converts a Punycode string representing a domain name or an email address
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
* it doesn't matter if you call it on a string that has already been
* converted to Unicode.
* @param {String} input The Punycoded domain name or email address to
* convert to Unicode.
* @return {String} The Unicode representation of the given Punycode
* string.
*/
declare function toUnicode(input: string): string;

/**
* Converts a Unicode string representing a domain name or an email address to
* Punycode. Only the non-ASCII parts of the domain name will be converted,
* i.e. it doesn't matter if you call it with a domain that's already in
* ASCII.
* @param {String} input The domain name or email address to convert, as a
* Unicode string.
* @return {String} The Punycode representation of the given domain name or
* email address.
*/
declare function toASCII(input: string): string;

declare module.exports: {
/**
* A string representing the current Punycode.js version number.
*/
version: string,
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
*/
ucs2: {
decode: typeof ucs2decode,
encode: typeof ucs2encode,
},
decode: typeof decode,
encode: typeof encode,
toASCII: typeof toASCII,
toUnicode: typeof toUnicode,
};
}
15 changes: 15 additions & 0 deletions lib/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"extends": "../.eslintrc.json",
"globals": {
"$Keys": true,
"Iterable": true,
"IteratorResult": true
},
"parser": "babel-eslint",
"parserOptions": {
"sourceType": "module"
},
"plugins": [
"flowtype"
]
}
10 changes: 7 additions & 3 deletions lib/constants.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';
// @flow strict

exports.categories = {
export const categories = {
valid: 1,
dnsWarn: 7,
rfc5321: 15,
Expand All @@ -10,7 +10,9 @@ exports.categories = {
error: 255
};

exports.diagnoses = {
export type CategoryName = $Keys<typeof categories>;

export const diagnoses = {

// Address is valid

Expand Down Expand Up @@ -89,3 +91,5 @@ exports.diagnoses = {
errDotAfterDomainLiteral: 162,
errMalformedUnicode: 163
};

export type DiagnosisName = $Keys<typeof diagnoses>;
48 changes: 25 additions & 23 deletions lib/diagnoses.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
'use strict';
// @flow strict

// Load modules

const Constants = require('./constants');
import * as Constants from './constants';

/**
* Diagnosis stores a diagnosis-index pair.
*/
class Diagnosis {
type: number;
index: number | null;

/**
* @param {number} type The diagnostic code.
* @param {number} index The index of the diagnosis.
* @param type The diagnostic code.
* @param index The index of the diagnosis.
*/
constructor(type, index) {
constructor(type: number, index: number | null) {

this.type = type;
this.index = index;
Expand All @@ -24,7 +27,10 @@ class Diagnosis {
* Diagnoses tracks a set of diagnostic codes for a string, along with their
* positions in the string.
*/
class Diagnoses {
export default class Diagnoses {
_diagnoses: Diagnosis[];
_worstDiagnosis: Diagnosis | null;

constructor() {

this._diagnoses = [];
Expand All @@ -34,10 +40,11 @@ class Diagnoses {
/**
* Report the given diagnosis at the given index.
*
* @param {number} type The diagnosis to report.
* @param {number} index The
* @param type The diagnosis to report.
* @param index The string offset in the input where the diagnosis occurs,
* if applicable.
*/
diagnose(type, index) {
diagnose(type: number, index: number | null = null) {

const diagnosis = new Diagnosis(type, index);

Expand All @@ -51,22 +58,21 @@ class Diagnoses {
/**
* Check whether the given diagnosis has been reported.
*
* @param {number} queryType The diagnosis to query.
* @return {boolean} Whether the diagnosis has been reported.
* @param queryType The diagnosis to query.
* @return Whether the diagnosis has been reported.
*/
hasDiagnosis(queryType) {
hasDiagnosis(queryType: number): boolean {

return this._diagnoses.some(({ type }) => type === queryType);
}

/**
* Get the worst diagnosis encountered.
*
* @param {Set<number>=} exclusions The set of diagnoses to exclude per the
* configuration.
* @return {?Diagnosis} The worst diagnosis.
* @param exclusions The set of diagnoses to exclude per the configuration.
* @return The worst diagnosis.
*/
getWorstDiagnosis(exclusions = new Set()) {
getWorstDiagnosis(exclusions: Set<number> = new Set()): Diagnosis | null {

// Use the precomputed worst diagnosis if it's not excluded.
if (!this._worstDiagnosis || !exclusions.has(this._worstDiagnosis.type)) {
Expand All @@ -88,11 +94,10 @@ class Diagnoses {
* For compatibility with existing versions of isemail, this function gets
* the first fatal diagnosis, or the worst non-fatal diagnosis.
*
* @param {Set<number>} exclusions The set of diagnoses to exclude per the
* configuration.
* @return {?Diagnosis} The backwards-compatible diagnosis.
* @param exclusions The set of diagnoses to exclude per the configuration.
* @return The backwards-compatible diagnosis.
*/
getLegacyDiagnosis(exclusions) {
getLegacyDiagnosis(exclusions: Set<number>): Diagnosis | null {

const firstFatalDiagnosis = this._diagnoses.find(({ type }) => type >= Constants.categories.rfc5322 && !exclusions.has(type));

Expand All @@ -103,6 +108,3 @@ class Diagnoses {
return this.getWorstDiagnosis(exclusions);
}
}


module.exports = Diagnoses;
Loading