Skip to content
This repository
Browse code

Add support for more formats (‘date’, ‘time’, ‘date-time’, ...)

  • Loading branch information...
commit a653c014662c826b399c5ae9b4bdccaa11ab83a6 1 parent 83f0dd1
František Hába authored

Showing 1 changed file with 111 additions and 82 deletions. Show diff stats Hide diff stats

  1. +111 82 src/engines/json/attributes/format.js
193 src/engines/json/attributes/format.js
@@ -19,18 +19,23 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
19 19 */
20 20 'date-time': {
21 21 type: 'string',
22   - pattern: /asd/
  22 + pattern: /^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/
23 23 },
24 24
25 25 /**
26 26 * date
27 27 *
28   - * This should be a date in the format of YYYY-MM-DD. It is recommended that you
  28 + * This should be a date in the format of YYYY-MM-DD. It is recommended that you
29 29 * use the "date-time" format instead of "date" unless you need to transfer only the date part.
30 30 */
31   - 'date': {
32   - type: 'string',
33   - pattern: /a/
  31 + date: function(input) {
  32 + if (isString(input)) {
  33 + return input.match(/^\d{4}-(?:0[0-9]{1}|1[0-2]{1})-[0-9]{2}$/);
  34 + }
  35 + if (isObject(input)) {
  36 + return Object.prototype.toString.call(input) === '[object Date]';
  37 + }
  38 + return false;
34 39 },
35 40
36 41 /**
@@ -40,17 +45,18 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
40 45 */
41 46 'time': {
42 47 type: 'string',
43   - pattern: /a/
  48 + pattern: /^\d{2}:\d{2}:\d{2}$/
44 49 },
45 50
46 51 /**
47 52 * utc-milisec
48 53 *
49   - * This should be a time in the format of hh:mm:ss.
  54 + * This should be the difference, measured in milliseconds, between the specified
  55 + * time and midnight, 00:00 of January 1, 1970 UTC. The value
  56 + * should be a number (integer or float).
50 57 */
51 58 'utc-milisec': {
52   - type: 'string',
53   - pattern: /a/
  59 + type: 'number'
54 60 },
55 61
56 62 /**
@@ -65,47 +71,44 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
65 71 /**
66 72 * color
67 73 *
68   - * This should be a time in the format of hh:mm:ss.
  74 + * This is a CSS color (like "#FF0000" or "red"), based on CSS 2.1.
69 75 */
70 76 'color': {
71   - type: 'string',
72   - pattern: /a/
  77 + type: 'string'
73 78 },
74 79
75 80 /**
76 81 * style
77 82 *
78   - * This should be a time in the format of hh:mm:ss.
  83 + * This is a CSS style definition (like "color: red; background-color:#FFF"), based on CSS 2.1.
79 84 */
80 85 'style': {
81   - type: 'string',
82   - pattern: /a/
  86 + type: 'string'
83 87 },
84 88
85 89 /**
86 90 * phone
87 91 *
88   - * This should be a time in the format of hh:mm:ss.
  92 + * This should be a phone number.
89 93 */
90 94 'phone': {
91   - type: 'string',
92   - pattern: /a/
  95 + type: 'number'
93 96 },
94 97
95 98 /**
96 99 * uri
97 100 *
98   - * This should be a time in the format of hh:mm:ss.
  101 + * This value should be a URI.
99 102 */
100 103 'uri': {
101 104 type: 'string',
102   - pattern: /a/
  105 + pattern: /^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/
103 106 },
104 107
105 108 /**
106 109 * email
107 110 *
108   - * This should be a time in the format of hh:mm:ss.
  111 + * This should be an email address.
109 112 */
110 113 'email': {
111 114 type: 'string',
@@ -115,17 +118,17 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
115 118 /**
116 119 * ip-address
117 120 *
118   - * This should be a time in the format of hh:mm:ss.
  121 + * This should be an ip version 4 address.
119 122 */
120 123 'ip-address': {
121 124 type: 'string',
122   - pattern: /a/
  125 + pattern: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
123 126 },
124 127
125 128 /**
126 129 * ipv6
127 130 *
128   - * This should be a time in the format of hh:mm:ss.
  131 + * This should be an ip version 6 address.
129 132 */
130 133 'ipv6': {
131 134 type: 'string',
@@ -135,89 +138,115 @@ Validation.prototype.addAttributeConstructor('format', function formatConstructo
135 138 /**
136 139 * host-name
137 140 *
138   - * This should be a time in the format of hh:mm:ss.
  141 + * This should be a host-name.
139 142 */
140 143 'host-name': {
141   - type: 'string',
142   - pattern: /a/
  144 + type: 'string'
143 145 }
144 146
145 147 };
146 148
147 149 /**
148 150 * CustomFormats
  151 + * --------------------
149 152 */
150   - var customFormats = {
151   -
152   - 'alpha': {
153   - type: 'string',
154   - pattern: /^[a-zA-Z]+$/
155   - },
156   -
157   - 'alphanumeric': {
158   - type: ['string', 'number'],
159   - pattern: /^[a-zA-Z0-9]+$/
160   - },
161   -
162   - 'decimal': {
163   - type: 'string',
164   - pattern: /^[0-9]+(\.[0-9]{1,2})?$/
165   - },
  153 + formats.alpha = {
  154 + required: true,
  155 + type: 'string',
  156 + pattern: /^[a-zA-Z]+$/
  157 + };
166 158
167   - 'percentage': {
168   - type: ['string', 'number'],
169   - pattern: /^-?[0-9]{0,2}(\.[0-9]{1,2})?$|^-?(100)(\.[0]{1,2})?$/,
170   - minimum: -100,
171   - maximum: 100
172   - },
  159 + formats.alphanumeric = {
  160 + required: true,
  161 + type: ['string', 'number'],
  162 + pattern: /^[a-zA-Z0-9]+$/
  163 + };
173 164
174   - 'port': {
175   - type: ['string', 'number'],
176   - pattern: /\:\d+/
177   - }
  165 + formats.decimal = function(input) {
  166 + if (!isNumber(input)) return false;
  167 + return (input + '').match(/^[0-9]+(\.[0-9]{1,2})?$/);
  168 + };
178 169
  170 + formats.percentage = {
  171 + required: true,
  172 + type: ['string', 'number'],
  173 + pattern: /^-?[0-9]{0,2}(\.[0-9]{1,2})?$|^-?(100)(\.[0]{1,2})?$/,
  174 + minimum: -100,
  175 + maximum: 100
179 176 };
180 177
181   - /*
182   - var aliases = {
183   - 'ip': formats.ip,
184   -
185   - 'hostName': formats['host-name'],
186   - 'host': formats['host-name'],
  178 + formats.port = {
  179 + required: true,
  180 + type: ['string', 'number'],
  181 + pattern: /\:\d+/
  182 + };
187 183
188   - };
189   - */
  184 + /**
  185 + * Aliases
  186 + * --------------------
  187 + */
  188 + var aliases = {
  189 + url: 'uri',
  190 + ip: 'ip-address',
  191 + ipv4: 'ip-address',
  192 + host: 'host-name',
  193 + hostName: 'host-name'
  194 + };
190 195
191   - /*
192   - 'ipv4': function(input) {
193   - return typeof input === 'string' && input.match(/^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/);
194   - },
195   - 'ip': function(input) {
196   - return formats.ipv4(input) || formats.ipv6;
197   - },
198   - 'url': function(input) {
199   - return typeof input === 'string' && input.match(/^(?:(?:ht|f)tp(?:s?)\:\/\/|~\/|\/)?(?:\w+:\w+@)?((?:(?:[-\w\d{1-3}]+\.)+(?:com|org|cat|coop|int|pro|tel|xxx|net|gov|mil|biz|info|mobi|name|aero|jobs|edu|co\.uk|ac\.uk|it|fr|tv|museum|asia|local|travel|[a-z]{2})?)|((\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)(\.(\b25[0-5]\b|\b[2][0-4][0-9]\b|\b[0-1]?[0-9]?[0-9]\b)){3}))(?::[\d]{1,5})?(?:(?:(?:\/(?:[-\w~!$+|.,=]|%[a-f\d]{2})+)+|\/)+|\?|#)?(?:(?:\?(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)(?:&(?:[-\w~!$+|.,*:]|%[a-f\d{2}])+=?(?:[-\w~!$+|.,*:=]|%[a-f\d]{2})*)*)*(?:#(?:[-\w~!$ |\/.,*:;=]|%[a-f\d]{2})*)?$/);
200   - },
201   - */
  196 + // Apply aliases
  197 + each(aliases, function(alias, format) {
  198 + formats[alias] = formats[format];
  199 + });
202 200
  201 + // Export
203 202 return function format(property, propertyValue, attributeValue, propertyAttributes, callback) {
204 203
205   - if (!hasProperty(formats, attributeValue)) {
  204 + /**
  205 + * {
  206 + * format: {
  207 + * type: 'string',
  208 + * pattern: /abc/
  209 + * ...
  210 + * }
  211 + * ...
  212 + * }
  213 + */
  214 + if (isObject(attributeValue)) {
  215 + return this.validateProperty(property, propertyValue, attributeValue, callback);
  216 + }
  217 +
  218 + /**
  219 + * {
  220 + * format: 'lorem ipsum dolor',
  221 + * ...
  222 + * }
  223 + */
  224 + if (isString(attributeValue) && !hasProperty(formats, attributeValue)) {
206 225 throw new Error('The format ‘' + attributeValue + '’ is not supported.');
207 226 }
208 227
209   - var format = formats[attributeValue];
  228 + /**
  229 + * {
  230 + * format: 'phone',
  231 + * ...
  232 + * }
  233 + */
  234 + if (isString(attributeValue)) {
  235 +
  236 + var fn = formats[attributeValue];
210 237
211   - if (isFunction(format)) {
212   - var noError = format(propertyValue);
213   - if (!noError) {
214   - this.addError();
  238 + if (isFunction(fn)) {
  239 + var noError = fn(propertyValue);
  240 + if (!noError) {
  241 + this.addError();
  242 + }
  243 + return callback();
  244 + }
  245 +
  246 + if (isObject(fn)) {
  247 + return this.validateProperty(property, propertyValue, fn, callback);
215 248 }
216   - return callback();
217   - }
218 249
219   - if (isObject(format)) {
220   - return this.validateProperty(property, propertyValue, format, callback);
221 250 }
222 251
223 252 };

0 comments on commit a653c01

Please sign in to comment.
Something went wrong with that request. Please try again.