[Pkg-javascript-commits] [node-addressparser] 01/02: Imported Upstream version 1.0.1
Thorsten Alteholz
alteholz at moszumanska.debian.org
Sun Apr 3 14:43:22 UTC 2016
This is an automated email from the git hooks/post-receive script.
alteholz pushed a commit to branch master
in repository node-addressparser.
commit ff5892878c54147764e1f94b7dbb53c21ccc82be
Author: Thorsten Alteholz <debian at alteholz.de>
Date: Sun Apr 3 16:43:18 2016 +0200
Imported Upstream version 1.0.1
---
.npmignore | 4 +
CHANGELOG.md | 16 +++
LICENSE | 16 +++
README.md | 64 +++++++++++
lib/addressparser.js | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++
package.json | 22 ++++
6 files changed, 413 insertions(+)
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..774a0ac
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,4 @@
+.travis.yml
+.eslintrc.js
+test
+Gruntfile.js
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..73c4880
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,16 @@
+# Changelog
+
+## v1.0.1 2016-02-06
+
+ * If the input string includes an unexpected < which messes up address part, then truncate unexpected data (similar to OSX Mail)
+
+## v1.0.0 2016-01-11
+
+ * Start using semver compatible versioning scheme, starting from v1.0.0
+ * Replaced jshint with eslint
+ * Dropped node 0.8 from the test targets. Should still work though
+
+## v0.3.2 2015-01-07
+
+ * Added changelog
+ * Allow semicolon (;) as address separator in addition to comma (,). Backport from https://github.com/whiteout-io/addressparser/pull/5
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..a89e4ff
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,16 @@
+Copyright (c) 2014-2016 Andris Reinman
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..71cdf9e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,64 @@
+# addressparser
+
+Parse e-mail address fields. Input can be a single address (`"andris at kreata.ee"`), a formatted address (`"Andris Reinman <andris at kreata.ee>"`), comma separated list of addresses (`"andris at kreata.ee, andris.reinman at kreata.ee"`), an address group (`"disclosed-recipients:andris at kreata.ee;"`) or a mix of all the formats.
+
+In addition to comma the semicolon is treated as the list delimiter as well (except when used in the group syntax), so a value `"andris at kreata.ee; andris.reinman at kreata.ee"` is identical to `"andris at kreata.ee, andris.reinman at kreata.ee"`.
+
+## Installation
+
+Install with npm
+
+```
+npm install addressparser
+```
+
+## Usage
+
+Include the module
+
+```javascript
+var addressparser = require('addressparser');
+```
+
+Parse some address strings with `addressparser(field)`
+
+```javascript
+var addresses = addressparser('andris <andris at tr.ee>');
+console.log(addresses); // [{name: "andris", address:"andris at tr.ee"}]
+```
+
+And when using groups
+
+```javascript
+addressparser('Composers:"Bach, Sebastian" <sebu at example.com>, mozart at example.com (Mozzie);');
+```
+
+the result would be
+
+```
+[
+ {
+ name: "Composers",
+ group: [
+ {
+ address: "sebu at example.com",
+ name: "Bach, Sebastian"
+ },
+ {
+ address: "mozart at example.com",
+ name: "Mozzie"
+ }
+ ]
+ }
+]
+```
+
+> Be prepared though that groups might be nested.
+
+## Notes
+
+This module does not decode any mime-word or punycode encoded strings, it is only a basic parser for parsing the base data, you need to decode the encoded parts later by yourself
+
+## License
+
+**MIT**
\ No newline at end of file
diff --git a/lib/addressparser.js b/lib/addressparser.js
new file mode 100644
index 0000000..a6d5db9
--- /dev/null
+++ b/lib/addressparser.js
@@ -0,0 +1,291 @@
+'use strict';
+
+// expose to the world
+module.exports = addressparser;
+
+/**
+ * Parses structured e-mail addresses from an address field
+ *
+ * Example:
+ *
+ * 'Name <address at domain>'
+ *
+ * will be converted to
+ *
+ * [{name: 'Name', address: 'address at domain'}]
+ *
+ * @param {String} str Address field
+ * @return {Array} An array of address objects
+ */
+function addressparser(str) {
+ var tokenizer = new Tokenizer(str);
+ var tokens = tokenizer.tokenize();
+
+ var addresses = [];
+ var address = [];
+ var parsedAddresses = [];
+
+ tokens.forEach(function (token) {
+ if (token.type === 'operator' && (token.value === ',' || token.value === ';')) {
+ if (address.length) {
+ addresses.push(address);
+ }
+ address = [];
+ } else {
+ address.push(token);
+ }
+ });
+
+ if (address.length) {
+ addresses.push(address);
+ }
+
+ addresses.forEach(function (address) {
+ address = _handleAddress(address);
+ if (address.length) {
+ parsedAddresses = parsedAddresses.concat(address);
+ }
+ });
+
+ return parsedAddresses;
+}
+
+/**
+ * Converts tokens for a single address into an address object
+ *
+ * @param {Array} tokens Tokens object
+ * @return {Object} Address object
+ */
+function _handleAddress(tokens) {
+ var token;
+ var isGroup = false;
+ var state = 'text';
+ var address;
+ var addresses = [];
+ var data = {
+ address: [],
+ comment: [],
+ group: [],
+ text: []
+ };
+ var i;
+ var len;
+
+ // Filter out <addresses>, (comments) and regular text
+ for (i = 0, len = tokens.length; i < len; i++) {
+ token = tokens[i];
+ if (token.type === 'operator') {
+ switch (token.value) {
+ case '<':
+ state = 'address';
+ break;
+ case '(':
+ state = 'comment';
+ break;
+ case ':':
+ state = 'group';
+ isGroup = true;
+ break;
+ default:
+ state = 'text';
+ }
+ } else if (token.value) {
+ if (state === 'address') {
+ // handle use case where unquoted name includes a "<"
+ // Apple Mail truncates everything between an unexpected < and an address
+ // and so will we
+ token.value = token.value.replace(/^[^<]*<\s*/, '');
+ }
+ data[state].push(token.value);
+ }
+ }
+
+ // If there is no text but a comment, replace the two
+ if (!data.text.length && data.comment.length) {
+ data.text = data.comment;
+ data.comment = [];
+ }
+
+ if (isGroup) {
+ // http://tools.ietf.org/html/rfc2822#appendix-A.1.3
+ data.text = data.text.join(' ');
+ addresses.push({
+ name: data.text || (address && address.name),
+ group: data.group.length ? addressparser(data.group.join(',')) : []
+ });
+ } else {
+ // If no address was found, try to detect one from regular text
+ if (!data.address.length && data.text.length) {
+ for (i = data.text.length - 1; i >= 0; i--) {
+ if (data.text[i].match(/^[^@\s]+@[^@\s]+$/)) {
+ data.address = data.text.splice(i, 1);
+ break;
+ }
+ }
+
+ var _regexHandler = function (address) {
+ if (!data.address.length) {
+ data.address = [address.trim()];
+ return ' ';
+ } else {
+ return address;
+ }
+ };
+
+ // still no address
+ if (!data.address.length) {
+ for (i = data.text.length - 1; i >= 0; i--) {
+ // fixed the regex to parse email address correctly when email address has more than one @
+ data.text[i] = data.text[i].replace(/\s*\b[^@\s]+@[^\s]+\b\s*/, _regexHandler).trim();
+ if (data.address.length) {
+ break;
+ }
+ }
+ }
+ }
+
+ // If there's still is no text but a comment exixts, replace the two
+ if (!data.text.length && data.comment.length) {
+ data.text = data.comment;
+ data.comment = [];
+ }
+
+ // Keep only the first address occurence, push others to regular text
+ if (data.address.length > 1) {
+ data.text = data.text.concat(data.address.splice(1));
+ }
+
+ // Join values with spaces
+ data.text = data.text.join(' ');
+ data.address = data.address.join(' ');
+
+ if (!data.address && isGroup) {
+ return [];
+ } else {
+ address = {
+ address: data.address || data.text || '',
+ name: data.text || data.address || ''
+ };
+
+ if (address.address === address.name) {
+ if ((address.address || '').match(/@/)) {
+ address.name = '';
+ } else {
+ address.address = '';
+ }
+
+ }
+
+ addresses.push(address);
+ }
+ }
+
+ return addresses;
+}
+
+/**
+ * Creates a Tokenizer object for tokenizing address field strings
+ *
+ * @constructor
+ * @param {String} str Address field string
+ */
+function Tokenizer(str) {
+ this.str = (str || '').toString();
+ this.operatorCurrent = '';
+ this.operatorExpecting = '';
+ this.node = null;
+ this.escaped = false;
+
+ this.list = [];
+}
+
+/**
+ * Operator tokens and which tokens are expected to end the sequence
+ */
+Tokenizer.prototype.operators = {
+ '"': '"',
+ '(': ')',
+ '<': '>',
+ ',': '',
+ ':': ';',
+ // Semicolons are not a legal delimiter per the RFC2822 grammar other
+ // than for terminating a group, but they are also not valid for any
+ // other use in this context. Given that some mail clients have
+ // historically allowed the semicolon as a delimiter equivalent to the
+ // comma in their UI, it makes sense to treat them the same as a comma
+ // when used outside of a group.
+ ';': ''
+};
+
+/**
+ * Tokenizes the original input string
+ *
+ * @return {Array} An array of operator|text tokens
+ */
+Tokenizer.prototype.tokenize = function () {
+ var chr, list = [];
+ for (var i = 0, len = this.str.length; i < len; i++) {
+ chr = this.str.charAt(i);
+ this.checkChar(chr);
+ }
+
+ this.list.forEach(function (node) {
+ node.value = (node.value || '').toString().trim();
+ if (node.value) {
+ list.push(node);
+ }
+ });
+
+ return list;
+};
+
+/**
+ * Checks if a character is an operator or text and acts accordingly
+ *
+ * @param {String} chr Character from the address field
+ */
+Tokenizer.prototype.checkChar = function (chr) {
+ if ((chr in this.operators || chr === '\\') && this.escaped) {
+ this.escaped = false;
+ } else if (this.operatorExpecting && chr === this.operatorExpecting) {
+ this.node = {
+ type: 'operator',
+ value: chr
+ };
+ this.list.push(this.node);
+ this.node = null;
+ this.operatorExpecting = '';
+ this.escaped = false;
+ return;
+ } else if (!this.operatorExpecting && chr in this.operators) {
+ this.node = {
+ type: 'operator',
+ value: chr
+ };
+ this.list.push(this.node);
+ this.node = null;
+ this.operatorExpecting = this.operators[chr];
+ this.escaped = false;
+ return;
+ }
+
+ if (!this.escaped && chr === '\\') {
+ this.escaped = true;
+ return;
+ }
+
+ if (!this.node) {
+ this.node = {
+ type: 'text',
+ value: ''
+ };
+ this.list.push(this.node);
+ }
+
+ if (this.escaped && chr !== '\\') {
+ this.node.value += '\\';
+ }
+
+ this.node.value += chr;
+ this.escaped = false;
+};
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..dd06faa
--- /dev/null
+++ b/package.json
@@ -0,0 +1,22 @@
+{
+ "name": "addressparser",
+ "version": "1.0.1",
+ "description": "Parse e-mail addresses",
+ "main": "lib/addressparser.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/andris9/addressparser.git"
+ },
+ "author": "Andris Reinman",
+ "license": "MIT",
+ "scripts": {
+ "test": "grunt"
+ },
+ "devDependencies": {
+ "chai": "^3.5.0",
+ "grunt": "^0.4.5",
+ "grunt-eslint": "^17.3.1",
+ "grunt-mocha-test": "^0.12.7",
+ "mocha": "^2.4.5"
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-addressparser.git
More information about the Pkg-javascript-commits
mailing list