spreadsheet
typeScript/javascript spreadsheet parser, with formulas.
git clone https://git.vogt.world/spreadsheet.git
Log | Files | README.md
← Commit log
commit
message
[ISURL] formula added and tested
author
Ben Vogt <[email protected]>
date
2017-06-30 15:59:47
stats
8 file(s) changed, 131 insertions(+), 9 deletions(-)
files
DOCS.md
TODO.md
dist/Formulas/AllFormulas.js
dist/Formulas/Info.js
src/Formulas/AllFormulas.ts
src/Formulas/Info.ts
tests/Formulas/InfoTest.ts
tests/SheetFormulaTest.ts
  1diff --git a/DOCS.md b/DOCS.md
  2index 26296ba..204a770 100644
  3--- a/DOCS.md
  4+++ b/DOCS.md
  5@@ -589,11 +589,20 @@
  6 ### ISEMAIL 
  7 
  8 ```
  9-  Returns true if input is a valid email. Valid domains are Original top-level domains and Country code top-level domains, 
 10+  Returns true if input is a valid email. Valid domains are Original top-level domains and Country code top-level domains. 
 11 @param value - Value to check whether it is an email or not. 
 12 @returns {boolean} 
 13 @constructor
 14 ```
 15+
 16+### ISURL 
 17+
 18+```
 19+  Returns true if the input is a valid URL. 
 20+@param value - Value to check 
 21+@returns {boolean} 
 22+@constructor
 23+```
 24 ## Logical
 25 
 26 
 27diff --git a/TODO.md b/TODO.md
 28index f6e3e20..fc591c6 100644
 29--- a/TODO.md
 30+++ b/TODO.md
 31@@ -32,7 +32,6 @@ For example 64 tbs to a qt.
 32 * ISFORMULA - Requires changes to parser.js
 33 * ISNA - Requires changes to parser.js
 34 * ISREF - Requires changes to parser.js
 35-* ISURL
 36 * N
 37 * TYPE - Requires changes to parser.js
 38 * CELL - Requires changes to parser.js
 39diff --git a/dist/Formulas/AllFormulas.js b/dist/Formulas/AllFormulas.js
 40index b1c1cfd..5916e90 100644
 41--- a/dist/Formulas/AllFormulas.js
 42+++ b/dist/Formulas/AllFormulas.js
 43@@ -83,6 +83,7 @@ exports.ISLOGICAL = Info_1.ISLOGICAL;
 44 exports.ISNUMBER = Info_1.ISNUMBER;
 45 exports.ISNONTEXT = Info_1.ISNONTEXT;
 46 exports.ISEMAIL = Info_1.ISEMAIL;
 47+exports.ISURL = Info_1.ISURL;
 48 var Lookup_1 = require("./Lookup");
 49 exports.CHOOSE = Lookup_1.CHOOSE;
 50 var Logical_1 = require("./Logical");
 51diff --git a/dist/Formulas/Info.js b/dist/Formulas/Info.js
 52index a9c027b..148fe8e 100644
 53--- a/dist/Formulas/Info.js
 54+++ b/dist/Formulas/Info.js
 55@@ -58,7 +58,7 @@ var ISNUMBER = function (value) {
 56 exports.ISNUMBER = ISNUMBER;
 57 /**
 58  * Returns true if input is a valid email. Valid domains are Original top-level domains and Country code top-level
 59- * domains,
 60+ * domains.
 61  * @param value - Value to check whether it is an email or not.
 62  * @returns {boolean}
 63  * @constructor
 64@@ -68,7 +68,44 @@ var ISEMAIL = function (value) {
 65     if (typeof value !== "string") {
 66         return false;
 67     }
 68-    var EMAIL_REGEX = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil||edu||int|biz|info|mobi|name|aero|jobs|museum|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bl|bm|bn|bo|bq|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mf|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/;
 69-    return EMAIL_REGEX.test(value);
 70+    var EMAIL_REGEX = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil|edu|int|biz|info|mobi|name|aero|jobs|museum|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bl|bm|bn|bo|bq|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mf|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/;
 71+    return EMAIL_REGEX.test(TypeConverter_1.TypeConverter.firstValueAsString(value));
 72 };
 73 exports.ISEMAIL = ISEMAIL;
 74+/**
 75+ * Returns true if the input is a valid URL.
 76+ * @param value - Value to check
 77+ * @returns {boolean}
 78+ * @constructor
 79+ */
 80+var ISURL = function (value) {
 81+    ArgsChecker_1.ArgsChecker.checkLength(arguments, 1, "ISURL");
 82+    value = TypeConverter_1.TypeConverter.firstValueAsString(value);
 83+    var matches = value.match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/);
 84+    if (/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(value)) {
 85+        return false;
 86+    }
 87+    if (/%[^0-9a-f]/i.test(value)) {
 88+        return false;
 89+    }
 90+    if (/%[0-9a-f](:?[^0-9a-f]|$)/i.test(value)) {
 91+        return false;
 92+    }
 93+    var authority = matches[2];
 94+    var path = matches[3];
 95+    if (!(path.length >= 0)) {
 96+        return false;
 97+    }
 98+    if (authority && authority.length) {
 99+        if (!(path.length === 0 || /^\//.test(path))) {
100+            return false;
101+        }
102+    }
103+    else {
104+        if (/^\/\//.test(path)) {
105+            return false;
106+        }
107+    }
108+    return true;
109+};
110+exports.ISURL = ISURL;
111diff --git a/src/Formulas/AllFormulas.ts b/src/Formulas/AllFormulas.ts
112index 610867b..0bf1855 100644
113--- a/src/Formulas/AllFormulas.ts
114+++ b/src/Formulas/AllFormulas.ts
115@@ -82,7 +82,8 @@ import {
116   ISLOGICAL,
117   ISNUMBER,
118   ISNONTEXT,
119-  ISEMAIL
120+  ISEMAIL,
121+  ISURL
122 } from "./Info";
123 import {
124   CHOOSE
125@@ -385,5 +386,6 @@ export {
126   IRR,
127   IPMT,
128   FV,
129-  ISEMAIL
130+  ISEMAIL,
131+  ISURL
132 }
133\ No newline at end of file
134diff --git a/src/Formulas/Info.ts b/src/Formulas/Info.ts
135index 7243245..706efb6 100644
136--- a/src/Formulas/Info.ts
137+++ b/src/Formulas/Info.ts
138@@ -69,7 +69,7 @@ var ISNUMBER = function (value) {
139 
140 /**
141  * Returns true if input is a valid email. Valid domains are Original top-level domains and Country code top-level
142- * domains,
143+ * domains.
144  * @param value - Value to check whether it is an email or not.
145  * @returns {boolean}
146  * @constructor
147@@ -79,8 +79,45 @@ var ISEMAIL = function (value) {
148   if (typeof value !== "string") {
149     return false;
150   }
151-  const EMAIL_REGEX = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil||edu||int|biz|info|mobi|name|aero|jobs|museum|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bl|bm|bn|bo|bq|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mf|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/;
152-  return EMAIL_REGEX.test(value);
153+  const EMAIL_REGEX = /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|gov|mil|edu|int|biz|info|mobi|name|aero|jobs|museum|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bl|bm|bn|bo|bq|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cu|cv|cw|cx|cy|cz|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mf|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|um|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|za|zm|zw)\b/;
154+  return EMAIL_REGEX.test(TypeConverter.firstValueAsString(value));
155+};
156+
157+
158+/**
159+ * Returns true if the input is a valid URL.
160+ * @param value - Value to check
161+ * @returns {boolean}
162+ * @constructor
163+ */
164+var ISURL = function (value) {
165+  ArgsChecker.checkLength(arguments, 1, "ISURL");
166+  value = TypeConverter.firstValueAsString(value);
167+  var matches = value.match(/(?:([^:\/?#]+):)?(?:\/\/([^\/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?/);
168+  if (/[^a-z0-9\:\/\?\#\[\]\@\!\$\&\'\(\)\*\+\,\;\=\.\-\_\~\%]/i.test(value)) {
169+    return false;
170+  }
171+  if (/%[^0-9a-f]/i.test(value)) {
172+    return false;
173+  }
174+  if (/%[0-9a-f](:?[^0-9a-f]|$)/i.test(value)) {
175+    return false;
176+  }
177+  var authority = matches[2];
178+  var path = matches[3];
179+  if (!(path.length >= 0)) {
180+    return false;
181+  }
182+  if (authority && authority.length) {
183+    if (!(path.length === 0 || /^\//.test(path))) {
184+      return false;
185+    }
186+  } else {
187+    if (/^\/\//.test(path)) {
188+      return false;
189+    }
190+  }
191+  return true;
192 };
193 
194 
195@@ -90,5 +127,6 @@ export {
196   ISLOGICAL,
197   ISNUMBER,
198   ISNONTEXT,
199-  ISEMAIL
200+  ISEMAIL,
201+  ISURL
202 }
203\ No newline at end of file
204diff --git a/tests/Formulas/InfoTest.ts b/tests/Formulas/InfoTest.ts
205index de88146..4b67de7 100644
206--- a/tests/Formulas/InfoTest.ts
207+++ b/tests/Formulas/InfoTest.ts
208@@ -4,7 +4,8 @@ import {
209   ISLOGICAL,
210   ISNUMBER,
211   ISNONTEXT,
212-  ISEMAIL
213+  ISEMAIL,
214+  ISURL
215 } from "../../src/Formulas/Info";
216 import * as ERRORS from "../../src/Errors";
217 import {
218@@ -71,3 +72,26 @@ test("ISEMAIL", function(){
219     ISEMAIL.apply(this, []);
220   }, ERRORS.NA_ERROR);
221 });
222+
223+test("ISURL", function(){
224+  assertEquals(ISURL("http://google.com"), true);
225+  assertEquals(ISURL("google.com"), true);
226+  assertEquals(ISURL("www.google.com"), true);
227+  assertEquals(ISURL("http://localhost"), true);
228+  assertEquals(ISURL("http://localhost/"), true);
229+  assertEquals(ISURL("https://10.1.1.255:8080"), true);
230+  assertEquals(ISURL("http://example.w3.org/path%20with%20spaces.html"), true);
231+  assertEquals(ISURL("http://example.w3.org/%20"), true);
232+  assertEquals(ISURL("ftp://ftp.is.co.za/rfc/rfc1808.txt"), true);
233+  assertEquals(ISURL("ftp://ftp.is.co.za/../../../rfc/rfc1808.txt"), true);
234+  assertEquals(ISURL("http://www.ietf.org/rfc/rfc2396.txt"), true);
235+  assertEquals(ISURL("ldap://[2001:db8::7]/c=GB?objectClass?one"), true);
236+  assertEquals(ISURL("mailto:[email protected]"), true);
237+  assertEquals(ISURL("news:comp.infosystems.www.servers.unix"), true);
238+  assertEquals(ISURL("tel:+1-816-555-1212"), true);
239+  assertEquals(ISURL("telnet://192.0.2.16:80/"), true);
240+  assertEquals(ISURL("urn:oasis:names:specification:docbook:dtd:xml:4.1.2"), true);
241+  catchAndAssertEquals(function() {
242+    ISURL.apply(this, []);
243+  }, ERRORS.NA_ERROR);
244+});
245diff --git a/tests/SheetFormulaTest.ts b/tests/SheetFormulaTest.ts
246index c1d2efa..2336543 100644
247--- a/tests/SheetFormulaTest.ts
248+++ b/tests/SheetFormulaTest.ts
249@@ -755,6 +755,14 @@ test("Sheet FV", function(){
250   assertFormulaEquals('=FV(0.05, 1, 66, 25000)', -26316);
251 });
252 
253+test("Sheet ISEMAIL", function(){
254+  assertFormulaEquals('=ISEMAIL("[email protected]")', true);
255+});
256+
257+test("Sheet ISURL", function(){
258+  assertFormulaEquals('=ISURL("example.com")', true);
259+});
260+
261 test("Sheet *", function(){
262   assertFormulaEquals('= 10 * 10', 100);
263   assertFormulaEquals('= 10 * 0', 0);