diff --git a/README.md b/README.md
index c6db161..f60a274 100644
--- a/README.md
+++ b/README.md
@@ -65,7 +65,8 @@ const allColors = cssContent
### Contact info
-- __`emailRE`__: Match a valid email. Provides matching groups 1 (user name) and 2 (domain). When using the partial string to create a RE, you must use the 'u' flag.
+- __`emailRE`__: Match most valid emails. Provides matching groups 1 (user name) and 2 (domain). When using the partial string to create a RE, you must use the 'u' flag.
+- __`emailRFC5322RE`__: Match any valid email address as defined by [RFC 5322](https://www.rfc-editor.org/rfc/rfc5322). This is a large, complicated RE, you may want to use [`emailRE`](#emailre) in most cases.
- __`usPhoneRE`__: Matches US phone numbers with optional country code and area code.
- __`zipCodeRE`__: Matches 5 or 9 digit US zip codes.
@@ -114,7 +115,11 @@ const allColors = cssContent
- __`ipRE`__: Matches a valid, non-localhost IP address.
- __`subdomainLabelRE`__: Matches a registerable domain name. Partially enforces the 63 byte domain label limit, but this is only valid for non-international (all ASCII) labels because we can only count characters. See [domain name rules](#domain-name-rules). When using the partial string to create a RE, you must use the 'u' or 'v' flag.
- __`tldNameRE`__: Matches a Top Level Domain (TLD). See [domain name rules](#domain-name-rules). When using the partial string to create a RE, you must use the 'u' or 'v' flag.
-- __`urlRE`__: Matches a valid URL.
+- __`urlRE`__: Matches a valid URL. When using the partial string to create a RE, you must use the 'u' or 'v' flag.
+
+### export const fqDomainNameREString = `(?![0-9\\p{L}.\\-]{256,})(?
+
+- __`fqDomainNameREString`__: ${subdomainLabelREString}\\.)+${tldNameREString}`
## Domain name rules
@@ -127,5 +132,3 @@ Unfortunately, there isn't clear consensus on what is allowed in a subdomain vs
* are composed of alpha-numeric characters (any Unicode letter plus 0-9) and hyphens ('-'), except
* the label must begin and end with an alpha-numeric character (any Uniced letter, 0-9; no hyphens), and
* the label must not have consecutive hyphens in the 3rd and 4th position. E.g. 'xy--z' is invalid.
-
-Also note, the base domain label REs do not support International Domain Names (IDNs; also called 'special character domain names').
\ No newline at end of file
diff --git a/make/10-resources.mk b/make/10-resources.mk
index 63cf830..9b846ae 100644
--- a/make/10-resources.mk
+++ b/make/10-resources.mk
@@ -1,14 +1,14 @@
# This file was generated by @liquid-labs/catalyst-builder-node. Refer to
# https://npmjs.com/package/@liquid-labs/catalyst-builder-node for further details
-CATALYST_BABEL:=npx babel
-CATALYST_BABEL_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-babel-and-rollup -- pwd)/dist/babel/babel.config.cjs
+SDLC_BABEL:=npx babel
+SDLC_BABEL_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-babel-and-rollup -- pwd)/dist/babel/babel.config.cjs
-CATALYST_ROLLUP:=npx rollup
-CATALYST_ROLLUP_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-babel-and-rollup -- pwd)/dist/rollup/rollup.config.mjs
+SDLC_ROLLUP:=npx rollup
+SDLC_ROLLUP_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-babel-and-rollup -- pwd)/dist/rollup/rollup.config.mjs
-CATALYST_JEST:=npx jest
-CATALYST_JEST_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-jest -- pwd)/dist/jest.config.js
+SDLC_JEST:=npx jest
+SDLC_JEST_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-jest -- pwd)/dist/jest.config.js
-CATALYST_ESLINT:=npx eslint
-CATALYST_ESLINT_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-eslint -- pwd)/dist/eslint.config.cjs
+SDLC_ESLINT:=npx eslint
+SDLC_ESLINT_CONFIG:=$(shell npm explore @liquid-labs/sdlc-resource-eslint -- pwd)/dist/eslint.config.cjs
diff --git a/make/15-data-finder.mk b/make/15-data-finder.mk
index 66d1ee5..85c44ea 100644
--- a/make/15-data-finder.mk
+++ b/make/15-data-finder.mk
@@ -1,8 +1,8 @@
# This file was generated by @liquid-labs/catalyst-builder-node. Refer to
# https://npmjs.com/package/@liquid-labs/catalyst-builder-node for further details
-CATALYST_DATA_SELECTOR=\( -path "*/test/data/*" -o -path "*/test/data-*/*" -o -path "*/test-data/*" \)
+SDLC_DATA_SELECTOR=\( -path "*/test/data/*" -o -path "*/test/data-*/*" -o -path "*/test-data/*" \)
# all test data (cli and lib)
-CATALYST_TEST_DATA_SRC:=$(shell find $(SRC) -type f $(CATALYST_DATA_SELECTOR))
-CATALYST_TEST_DATA_BUILT:=$(patsubst $(SRC)/%, $(TEST_STAGING)/%, $(CATALYST_TEST_DATA_SRC))
+SDLC_TEST_DATA_SRC:=$(shell find $(SRC) -type f $(SDLC_DATA_SELECTOR))
+SDLC_TEST_DATA_BUILT:=$(patsubst $(SRC)/%, $(TEST_STAGING)/%, $(SDLC_TEST_DATA_SRC))
diff --git a/make/20-js-src-finder.mk b/make/20-js-src-finder.mk
index ed55cb1..fea420e 100644
--- a/make/20-js-src-finder.mk
+++ b/make/20-js-src-finder.mk
@@ -1,10 +1,10 @@
# This file was generated by @liquid-labs/catalyst-builder-node. Refer to
# https://npmjs.com/package/@liquid-labs/catalyst-builder-node for further details
-CATALYST_JS_SELECTOR=\( -name "*.js" -o -name "*.cjs" -o -name "*.mjs" \)
-CATALYST_TEST_SELECTOR=\( -name "*.test.*js" -o -path "*/test/*" \)
+SDLC_JS_SELECTOR=\( -name "*.js" -o -name "*.cjs" -o -name "*.mjs" \)
+SDLC_TEST_SELECTOR=\( -name "*.test.*js" -o -path "*/test/*" \)
# all source, non-test files (cli and lib)
-CATALYST_ALL_JS_FILES_SRC:=$(shell find $(SRC) $(CATALYST_JS_SELECTOR) -not $(CATALYST_DATA_SELECTOR) -type f)
-CATALYST_ALL_NON_TEST_JS_FILES_SRC:=$(shell find $(SRC) $(CATALYST_JS_SELECTOR) -not $(CATALYST_DATA_SELECTOR) -not $(CATALYST_TEST_SELECTOR) -type f)
-CATALYST_JS_TEST_FILES_BUILT:=$(patsubst %.cjs, %.js, $(patsubst %.mjs, %.js, $(patsubst $(SRC)/%, test-staging/%, $(CATALYST_ALL_JS_FILES_SRC))))
+SDLC_ALL_JS_FILES_SRC:=$(shell find $(SRC) $(SDLC_JS_SELECTOR) -not $(SDLC_DATA_SELECTOR) -type f)
+SDLC_ALL_NON_TEST_JS_FILES_SRC:=$(shell find $(SRC) $(SDLC_JS_SELECTOR) -not $(SDLC_DATA_SELECTOR) -not $(SDLC_TEST_SELECTOR) -type f)
+SDLC_JS_TEST_FILES_BUILT:=$(patsubst %.cjs, %.js, $(patsubst %.mjs, %.js, $(patsubst $(SRC)/%, test-staging/%, $(SDLC_ALL_JS_FILES_SRC))))
diff --git a/make/50-readme.mk b/make/50-readme.mk
index e7ad424..68942b6 100644
--- a/make/50-readme.mk
+++ b/make/50-readme.mk
@@ -2,10 +2,10 @@ README_SRC:=$(SRC)/doc/README.01.md $(SRC)/doc/README.02.md
README_BUILT:=README.md
DOC_EXTRACTOR:=$(SRC)/doc-extractor/doc-extractor.mjs
-$(README_BUILT): $(README_SRC) $(DOC_EXTRACTOR) $(CATALYST_ALL_NON_TEST_JS_FILES_SRC)
+$(README_BUILT): $(README_SRC) $(DOC_EXTRACTOR) $(SDLC_ALL_NON_TEST_JS_FILES_SRC)
cp $< $@
node $(DOC_EXTRACTOR)
cat $(SRC)/doc/README.02.md >> $@
-BUILD_TARGETS:=$(README_BUILT)
\ No newline at end of file
+BUILD_TARGETS+=$(README_BUILT)
\ No newline at end of file
diff --git a/make/50-regex-repo-js.mk b/make/50-regex-repo-js.mk
index 893a8ca..3ea062b 100644
--- a/make/50-regex-repo-js.mk
+++ b/make/50-regex-repo-js.mk
@@ -5,14 +5,14 @@
# build dist/regex-repo.js
#####
-CATALYST_REGEX_REPO_JS:=$(DIST)/regex-repo.js
-CATALYST_REGEX_REPO_JS_ENTRY=$(SRC)/index.js
-BUILD_TARGETS+=$(CATALYST_REGEX_REPO_JS)
+SDLC_REGEX_REPO_JS:=$(DIST)/regex-repo.js
+SDLC_REGEX_REPO_JS_ENTRY=$(SRC)/index.js
+BUILD_TARGETS+=$(SDLC_REGEX_REPO_JS)
-$(CATALYST_REGEX_REPO_JS): package.json $(CATALYST_ALL_NON_TEST_JS_FILES_SRC)
- JS_BUILD_TARGET=$(CATALYST_REGEX_REPO_JS_ENTRY) \
+$(SDLC_REGEX_REPO_JS): package.json $(SDLC_ALL_NON_TEST_JS_FILES_SRC)
+ JS_BUILD_TARGET=$(SDLC_REGEX_REPO_JS_ENTRY) \
JS_OUT=$@ \
- $(CATALYST_ROLLUP) --config $(CATALYST_ROLLUP_CONFIG)
+ $(SDLC_ROLLUP) --config $(SDLC_ROLLUP_CONFIG)
#####
# end dist/regex-repo.js
diff --git a/make/55-lint.mk b/make/55-lint.mk
index e8eee56..9a6e848 100644
--- a/make/55-lint.mk
+++ b/make/55-lint.mk
@@ -5,26 +5,26 @@
# lint rules
#####
-CATALYST_LINT_REPORT:=$(QA)/lint.txt
-CATALYST_LINT_PASS_MARKER:=$(QA)/.lint.passed
-LINT_TARGETS+=$(CATALYST_LINT_REPORT) $(CATALYST_LINT_PASS_MARKER)
-PRECIOUS_TARGETS+=$(CATALYST_LINT_REPORT)
+SDLC_LINT_REPORT:=$(QA)/lint.txt
+SDLC_LINT_PASS_MARKER:=$(QA)/.lint.passed
+LINT_TARGETS+=$(SDLC_LINT_REPORT) $(SDLC_LINT_PASS_MARKER)
+PRECIOUS_TARGETS+=$(SDLC_LINT_REPORT)
-$(CATALYST_LINT_REPORT) $(CATALYST_LINT_PASS_MARKER): $(CATALYST_ALL_JS_FILES_SRC)
+$(SDLC_LINT_REPORT) $(SDLC_LINT_PASS_MARKER): $(SDLC_ALL_JS_FILES_SRC)
mkdir -p $(dir $@)
- echo -n 'Test git rev: ' > $(CATALYST_LINT_REPORT)
- git rev-parse HEAD >> $(CATALYST_LINT_REPORT)
+ echo -n 'Test git rev: ' > $(SDLC_LINT_REPORT)
+ git rev-parse HEAD >> $(SDLC_LINT_REPORT)
( set -e; set -o pipefail; \
- ESLINT_USE_FLAT_CONFIG=true $(CATALYST_ESLINT) \
- --config $(CATALYST_ESLINT_CONFIG) \
+ ESLINT_USE_FLAT_CONFIG=true $(SDLC_ESLINT) \
+ --config $(SDLC_ESLINT_CONFIG) \
. \
- | tee -a $(CATALYST_LINT_REPORT); \
- touch $(CATALYST_LINT_PASS_MARKER) )
+ | tee -a $(SDLC_LINT_REPORT); \
+ touch $(SDLC_LINT_PASS_MARKER) )
lint-fix:
@( set -e; set -o pipefail; \
- ESLINT_USE_FLAT_CONFIG=true $(CATALYST_ESLINT) \
- --config $(CATALYST_ESLINT_CONFIG) \
+ ESLINT_USE_FLAT_CONFIG=true $(SDLC_ESLINT) \
+ --config $(SDLC_ESLINT_CONFIG) \
--fix . )
#####
diff --git a/make/55-test.mk b/make/55-test.mk
index c56f39b..1d57346 100644
--- a/make/55-test.mk
+++ b/make/55-test.mk
@@ -5,48 +5,48 @@
# test rules
#####
-CATALYST_TEST_REPORT:=$(QA)/unit-test.txt
-CATALYST_TEST_PASS_MARKER:=$(QA)/.unit-test.passed
-CATALYST_COVERAGE_REPORTS:=$(QA)/coverage
-TEST_TARGETS+=$(CATALYST_TEST_REPORT) $(CATALYST_TEST_PASS_MARKER) $(CATALYST_COVERAGE_REPORTS)
-PRECIOUS_TARGETS+=$(CATALYST_TEST_REPORT)
+SDLC_TEST_REPORT:=$(QA)/unit-test.txt
+SDLC_TEST_PASS_MARKER:=$(QA)/.unit-test.passed
+SDLC_COVERAGE_REPORTS:=$(QA)/coverage
+TEST_TARGETS+=$(SDLC_TEST_REPORT) $(SDLC_TEST_PASS_MARKER) $(SDLC_COVERAGE_REPORTS)
+PRECIOUS_TARGETS+=$(SDLC_TEST_REPORT)
-CATALYST_TEST_FILES_BUILT:=$(patsubst %.cjs, %.js, $(patsubst %.mjs, %.js, $(patsubst $(SRC)/%, $(TEST_STAGING)/%, $(CATALYST_ALL_JS_FILES_SRC))))
+SDLC_TEST_FILES_BUILT:=$(patsubst %.cjs, %.js, $(patsubst %.mjs, %.js, $(patsubst $(SRC)/%, $(TEST_STAGING)/%, $(SDLC_ALL_JS_FILES_SRC))))
-$(CATALYST_TEST_DATA_BUILT): $(TEST_STAGING)/%: $(SRC)/%
+$(SDLC_TEST_DATA_BUILT): $(TEST_STAGING)/%: $(SRC)/%
@echo "Copying test data..."
@mkdir -p $(dir $@)
@cp $< $@
# Jest is not picking up the external maps, so we inline them for the test. (As of?)
-$(CATALYST_TEST_FILES_BUILT) &: $(CATALYST_ALL_JS_FILES_SRC)
+$(SDLC_TEST_FILES_BUILT) &: $(SDLC_ALL_JS_FILES_SRC)
rm -rf $(TEST_STAGING)
mkdir -p $(TEST_STAGING)
- NODE_ENV=test $(CATALYST_BABEL) \
- --config-file=$(CATALYST_BABEL_CONFIG) \
+ NODE_ENV=test $(SDLC_BABEL) \
+ --config-file=$(SDLC_BABEL_CONFIG) \
--out-dir=./$(TEST_STAGING) \
--source-maps=inline \
$(SRC)
# remove because it's not really part of the test
rm $(TEST_STAGING)/doc-extractor/doc-extractor.js
-$(CATALYST_TEST_PASS_MARKER) $(CATALYST_TEST_REPORT) $(TEST_STAGING)/coverage &: package.json $(CATALYST_TEST_FILES_BUILT) $(CATALYST_TEST_DATA_BUILT)
+$(SDLC_TEST_PASS_MARKER) $(SDLC_TEST_REPORT) $(TEST_STAGING)/coverage &: package.json $(SDLC_TEST_FILES_BUILT) $(SDLC_TEST_DATA_BUILT)
rm -rf $@
mkdir -p $(dir $@)
- echo -n 'Test git rev: ' > $(CATALYST_TEST_REPORT)
- git rev-parse HEAD >> $(CATALYST_TEST_REPORT)
+ echo -n 'Test git rev: ' > $(SDLC_TEST_REPORT)
+ git rev-parse HEAD >> $(SDLC_TEST_REPORT)
( set -e; set -o pipefail; \
- ( cd $(TEST_STAGING) && $(CATALYST_JEST) \
- --config=$(CATALYST_JEST_CONFIG) \
+ ( cd $(TEST_STAGING) && $(SDLC_JEST) \
+ --config=$(SDLC_JEST_CONFIG) \
--runInBand \
$(TEST) 2>&1 ) \
- | tee -a $(CATALYST_TEST_REPORT); \
- touch $(CATALYST_TEST_PASS_MARKER) )
+ | tee -a $(SDLC_TEST_REPORT); \
+ touch $(SDLC_TEST_PASS_MARKER) )
-$(CATALYST_COVERAGE_REPORTS): $(CATALYST_TEST_PASS_MARKER) $(TEST_STAGING)/coverage
- rm -rf $(CATALYST_COVERAGE_REPORTS)
- mkdir -p $(CATALYST_COVERAGE_REPORTS)
- cp -r $(TEST_STAGING)/coverage/* $(CATALYST_COVERAGE_REPORTS)
+$(SDLC_COVERAGE_REPORTS): $(SDLC_TEST_PASS_MARKER) $(TEST_STAGING)/coverage
+ rm -rf $(SDLC_COVERAGE_REPORTS)
+ mkdir -p $(SDLC_COVERAGE_REPORTS)
+ cp -r $(TEST_STAGING)/coverage/* $(SDLC_COVERAGE_REPORTS)
#####
# end test
diff --git a/package-lock.json b/package-lock.json
index dd2a298..e7985a2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
"version": "3.0.0",
"license": "Apache-2.0",
"devDependencies": {
- "@liquid-labs/sdlc-resource-babel-and-rollup": "^1.0.0-alpha.8",
+ "@liquid-labs/sdlc-resource-babel-and-rollup": "^1.0.0-alpha.9",
"@liquid-labs/sdlc-resource-eslint": "^1.0.0-alpha.10",
"@liquid-labs/sdlc-resource-jest": "^1.0.0-alpha.7"
},
@@ -2969,9 +2969,9 @@
}
},
"node_modules/@liquid-labs/sdlc-resource-babel-and-rollup": {
- "version": "1.0.0-alpha.8",
- "resolved": "https://registry.npmjs.org/@liquid-labs/sdlc-resource-babel-and-rollup/-/sdlc-resource-babel-and-rollup-1.0.0-alpha.8.tgz",
- "integrity": "sha512-u4/s+Wojii9rLBHP/JGuwfh6MxoG5XpvoRJUwrKk9zFVawEvLhV63xu6NTxhktY9Gd6pHrUijNfHbEF5HMATUw==",
+ "version": "1.0.0-alpha.9",
+ "resolved": "https://registry.npmjs.org/@liquid-labs/sdlc-resource-babel-and-rollup/-/sdlc-resource-babel-and-rollup-1.0.0-alpha.9.tgz",
+ "integrity": "sha512-IEDiFYWok+mPyWcPRilOu9EhMcD1Y92OM3xqrjH113qjp/OtKOTMYqXNyU1xSsZWOSMU3ejCOH5n0S2yNtF/KQ==",
"dev": true,
"dependencies": {
"@babel/cli": "^7.23.4",
@@ -13262,9 +13262,9 @@
}
},
"@liquid-labs/sdlc-resource-babel-and-rollup": {
- "version": "1.0.0-alpha.8",
- "resolved": "https://registry.npmjs.org/@liquid-labs/sdlc-resource-babel-and-rollup/-/sdlc-resource-babel-and-rollup-1.0.0-alpha.8.tgz",
- "integrity": "sha512-u4/s+Wojii9rLBHP/JGuwfh6MxoG5XpvoRJUwrKk9zFVawEvLhV63xu6NTxhktY9Gd6pHrUijNfHbEF5HMATUw==",
+ "version": "1.0.0-alpha.9",
+ "resolved": "https://registry.npmjs.org/@liquid-labs/sdlc-resource-babel-and-rollup/-/sdlc-resource-babel-and-rollup-1.0.0-alpha.9.tgz",
+ "integrity": "sha512-IEDiFYWok+mPyWcPRilOu9EhMcD1Y92OM3xqrjH113qjp/OtKOTMYqXNyU1xSsZWOSMU3ejCOH5n0S2yNtF/KQ==",
"dev": true,
"requires": {
"@babel/cli": "^7.23.4",
diff --git a/package.json b/package.json
index 7881a47..6a35a33 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
"orgKey": "@liquid-labs"
},
"devDependencies": {
- "@liquid-labs/sdlc-resource-babel-and-rollup": "^1.0.0-alpha.8",
+ "@liquid-labs/sdlc-resource-babel-and-rollup": "^1.0.0-alpha.9",
"@liquid-labs/sdlc-resource-eslint": "^1.0.0-alpha.10",
"@liquid-labs/sdlc-resource-jest": "^1.0.0-alpha.7"
}
diff --git a/src/contacts.js b/src/contacts.js
index 40e33d3..15941eb 100644
--- a/src/contacts.js
+++ b/src/contacts.js
@@ -14,7 +14,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
+import { fqDomainNameREString } from './web'
import { lockdownRE } from './lib/lockdown-re'
+import { uniNonASCII } from './lib/uni-non-ascii'
export const usPhoneREString = '(\\+?1[._ -]?)?(\\(\\d{3}\\)|\\d{3})[._ -]?\\d{3}[._ -]?\\d{4}'
// Contact info: Matches US phone numbers with optional country code and area code.
@@ -23,3 +25,7 @@ export const usPhoneRE = lockdownRE(usPhoneREString)
export const zipCodeREString = '\\d{5}([._ -]?\\d{4})?'
// Contact info: Matches 5 or 9 digit US zip codes.
export const zipCodeRE = lockdownRE(zipCodeREString)
+
+export const emailREString = `([a-zA-Z0-9${uniNonASCII}!#$%&'*+\\/=?^_\`\\{\\|\\}~\\-]+(?:\\.[a-zA-Z0-9${uniNonASCII}!#$%&'*+\\/=?^_\`\\{\\|\\}~\\-]+)*|"(?:[\\x20-\\x21\\x23-\\x5b\\x5d-\\x7e${uniNonASCII}]|\\\\[\\x20-\\x7e${uniNonASCII}])*")@(${fqDomainNameREString})`
+// Contact info: Match most valid emails. Provides matching groups 1 (user name) and 2 (domain). When using the partial string to create a RE, you must use the 'u' flag.
+export const emailRE = lockdownRE(emailREString, 'u')
diff --git a/src/doc/README.02.md b/src/doc/README.02.md
index 8055eb6..bd38376 100644
--- a/src/doc/README.02.md
+++ b/src/doc/README.02.md
@@ -9,5 +9,3 @@ Unfortunately, there isn't clear consensus on what is allowed in a subdomain vs
* are composed of alpha-numeric characters (any Unicode letter plus 0-9) and hyphens ('-'), except
* the label must begin and end with an alpha-numeric character (any Uniced letter, 0-9; no hyphens), and
* the label must not have consecutive hyphens in the 3rd and 4th position. E.g. 'xy--z' is invalid.
-
-Also note, the base domain label REs do not support International Domain Names (IDNs; also called 'special character domain names').
\ No newline at end of file
diff --git a/src/lib/uni-non-ascii.mjs b/src/lib/uni-non-ascii.mjs
new file mode 100644
index 0000000..ea06cc9
--- /dev/null
+++ b/src/lib/uni-non-ascii.mjs
@@ -0,0 +1 @@
+export const uniNonASCII = '\\u0080-\\u{e007f}'
diff --git a/src/test/contacts.test.js b/src/test/contacts.test.js
index ba62c1c..e714cc3 100644
--- a/src/test/contacts.test.js
+++ b/src/test/contacts.test.js
@@ -16,6 +16,7 @@ limitations under the License.
import { groupTest, groupTestPartial } from './lib/test-lib'
import * as regex from '../contacts'
+import { goodEmails, badEmails } from './data/emails'
import { goodUsPhones, badUsPhones } from './data/usPhones'
import { goodZipCodes, badZipCodes } from './data/zipCodes'
@@ -24,3 +25,6 @@ groupTestPartial(regex.usPhoneREString, goodUsPhones, badUsPhones, 'US phones')
groupTest(regex.zipCodeRE, goodZipCodes, badZipCodes, 'US zip codes')
groupTestPartial(regex.zipCodeREString, goodZipCodes, badZipCodes, 'US zip codes')
+
+groupTest(regex.emailRE, goodEmails, badEmails, 'emails')
+groupTestPartial(regex.emailREString, goodEmails, badEmails, 'emails', undefined, undefined, 'u')
diff --git a/src/test/data/emails.js b/src/test/data/emails.js
index 8a4249a..014a10d 100644
--- a/src/test/data/emails.js
+++ b/src/test/data/emails.js
@@ -22,7 +22,8 @@ export const goodEmails = [
'foo-_18+Z.t%c@Bart-teg38w.co',
'foo@some.reallylongtld',
'foo@subb-sub.sub.com',
- 'foo@some.reallylongtld'
+ 'foo@some.reallylongtld',
+ '"quote@username"@foo.com'
]
export const badEmails = [
@@ -33,3 +34,12 @@ export const badEmails = [
const badDomainChars = ['_', '@', '+', '%']
badDomainChars.forEach((c) => badEmails.push(`foo@bar${c}baz.com`))
+
+export const goodEmailsRFC5322 = [
+ ...goodEmails,
+ '(comment)foo(comment2)@(comment3)[123.123.123.123](comment4)'
+]
+
+export const badEmailsRFC5322 = [
+ ...badEmails
+]
diff --git a/src/test/data/tlds.js b/src/test/data/tlds.js
index 74e830a..b68732a 100644
--- a/src/test/data/tlds.js
+++ b/src/test/data/tlds.js
@@ -1,6 +1,7 @@
export const goodTLDs = [
'com',
'cc',
+ 'a1b',
'域',
'alongtld',
'abcdefghijklmnopqprsuvwxyzabcdefghijklmnopqprsuvwxyzabcdefghijk' // 63 characters OK
@@ -8,7 +9,6 @@ export const goodTLDs = [
export const badTLDs = [
'a',
- 'a1b',
'1a',
'a-z',
'-az',
diff --git a/src/test/web.test.js b/src/test/web.test.js
index 19bee6e..e8c99fb 100644
--- a/src/test/web.test.js
+++ b/src/test/web.test.js
@@ -17,7 +17,6 @@ limitations under the License.
import { groupTest, groupTestPartial } from './lib/test-lib'
import * as regex from '../web'
import { goodDomainNames, badDomainNames } from './data/domains'
-import { goodEmails, badEmails } from './data/emails'
import { goodFQDomainNames, badFQDomainNames } from './data/fq-domains'
import { goodIPs, badIPs } from './data/ips'
import { goodIPFormats, badIPFormats } from './data/ip-formats'
@@ -27,9 +26,6 @@ import { goodUrls, badUrls } from './data/urls'
groupTest(regex.subdomainLabelRE, goodDomainNames, badDomainNames, 'subdomain label')
groupTestPartial(regex.subdomainLabelREString, goodDomainNames, badDomainNames, 'subdomain label', undefined, undefined, 'u')
-groupTest(regex.emailRE, goodEmails, badEmails, 'emails')
-groupTestPartial(regex.emailREString, goodEmails, badEmails, 'emails', undefined, undefined, 'u')
-
groupTest(regex.fqDomainNameRE, goodFQDomainNames, badFQDomainNames, 'FQ domain names')
groupTestPartial(regex.fqDomainNameREString, goodFQDomainNames, badFQDomainNames, 'FQ domain names', undefined, undefined, 'u')
diff --git a/src/web.js b/src/web.js
index ff5fa1e..3d26400 100644
--- a/src/web.js
+++ b/src/web.js
@@ -15,6 +15,7 @@ limitations under the License.
*/
import { lockdownRE } from './lib/lockdown-re'
+import { uniNonASCII } from './lib/uni-non-ascii'
export const ipREString = '(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])' +
'(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}' +
@@ -40,27 +41,23 @@ export const urlREString =
// excludes network & broacast addresses
// (first & last IP address of each class)
'(?:(?:' + ipREString +
- '|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?'
-// Web: Matches a valid URL.
-export const urlRE = lockdownRE(urlREString, 'i')
+ `|(?:(?:[a-z${uniNonASCII}0-9]+-?)*[a-z${uniNonASCII}0-9]+)(?:\\.(?:[a-z${uniNonASCII}0-9]+-?)*[a-z${uniNonASCII}0-9]+)*(?:\\.(?:[a-z${uniNonASCII}]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?`
+// Web: Matches a valid URL. When using the partial string to create a RE, you must use the 'u' or 'v' flag.
+export const urlRE = lockdownRE(urlREString, 'ui')
-// we want to do '[\p{L}--[a-zA-Z]]', but the 'v' flag breaks on Ubunto Node (weird)
-export const tldNameREString = '(?:(?![a-zA-Z])\\p{L}|[a-zA-Z\\p{L}]{2,63})'
+// note the 'v' flag breaks on Ubuntu
+export const tldNameREString = `(?:(?![0-9])(?:[${uniNonASCII}]|[a-zA-Z${uniNonASCII}][a-zA-Z0-9${uniNonASCII}]{1,62}))`
// Web: Matches a Top Level Domain (TLD). See [domain name rules](#domain-name-rules). When using the partial string to create a RE, you must use the 'u' or 'v' flag.
export const tldNameRE = lockdownRE(tldNameREString, 'u')
-export const subdomainLabelREString = '(?:(?![a-zA-Z])\\p{L}|[\\p{L}0-9]' +
- '(?:[\\p{L}0-9]|' + // two letters only
- '[\\p{L}0-9\\-](?!--)[\\p{L}0-9\\-]{0,60}[\\p{L}0-9]))' // otherwise, verify the 3rd and 4th positions are not '-'
+export const subdomainLabelREString = `(?:[${uniNonASCII}]|[a-zA-Z0-9${uniNonASCII}]` + // allow single unicode
+ `(?:[a-zA-Z0-9${uniNonASCII}]|` + // two letters only
+ // otherwise, verify the 3rd and 4th positions are not '-'
+ `[a-zA-Z0-9${uniNonASCII}\\-](?!--)[a-zA-Z0-9${uniNonASCII}\\-]{0,60}[\\p{L}0-9]))`
// Web: Matches a registerable domain name. Partially enforces the 63 byte domain label limit, but this is only valid for non-international (all ASCII) labels because we can only count characters. See [domain name rules](#domain-name-rules). When using the partial string to create a RE, you must use the 'u' or 'v' flag.
export const subdomainLabelRE = lockdownRE(subdomainLabelREString, 'u')
-export const fqDomainNameREString = `(?![0-9\\p{L}.\\-]{256,})(?:${subdomainLabelREString}\\.)+${tldNameREString}`
+// export const fqDomainNameREString = `(?![0-9\\p{L}.\\-]{256,})(?:${subdomainLabelREString}\\.)+${tldNameREString}`
+export const fqDomainNameREString = `(?!.{256,})(?:${subdomainLabelREString}\\.)+${tldNameREString}`
// Web: Matches fully qualified domain name (one or more subdomains + TLD). Partially enforces the 255 byte FQ domain name limit, but this is only valid for non-international (all ASCII) domain names because we can only count characters. When using the partial string to create a RE, you must use the 'u' or 'v' flag.
export const fqDomainNameRE = lockdownRE(fqDomainNameREString, 'u')
-
-// based on https://stackoverflow.com/a/201378/929494; modified to allow uppercase characters and restrict to valid DNS
-// names in the domain portion
-export const emailREString = `([a-zA-Z0-9!#$%&'*+\\/=?^_\`\\{\\|\\}~\\-]+(?:\\.[a-zA-Z0-9!#$%&'*+\\/=?^_\`\\{\\|\\}~\\-]+)*|"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*")@(${fqDomainNameREString})`
-// Contact info: Match a valid email. Provides matching groups 1 (user name) and 2 (domain). When using the partial string to create a RE, you must use the 'u' flag.
-export const emailRE = lockdownRE(emailREString, 'u')