193 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			193 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								(function (root, factory) {
							 | 
						||
| 
								 | 
							
								    if (typeof exports === 'object') {
							 | 
						||
| 
								 | 
							
								        module.exports = factory();
							 | 
						||
| 
								 | 
							
								    } else if (typeof define === 'function' && define.amd) {
							 | 
						||
| 
								 | 
							
								        define([], factory);
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								        root.urltemplate = factory();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								}(this, function () {
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @constructor
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  function UrlTemplate() {
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   * @param {string} str
							 | 
						||
| 
								 | 
							
								   * @return {string}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  UrlTemplate.prototype.encodeReserved = function (str) {
							 | 
						||
| 
								 | 
							
								    return str.split(/(%[0-9A-Fa-f]{2})/g).map(function (part) {
							 | 
						||
| 
								 | 
							
								      if (!/%[0-9A-Fa-f]/.test(part)) {
							 | 
						||
| 
								 | 
							
								        part = encodeURI(part).replace(/%5B/g, '[').replace(/%5D/g, ']');
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      return part;
							 | 
						||
| 
								 | 
							
								    }).join('');
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   * @param {string} str
							 | 
						||
| 
								 | 
							
								   * @return {string}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  UrlTemplate.prototype.encodeUnreserved = function (str) {
							 | 
						||
| 
								 | 
							
								    return encodeURIComponent(str).replace(/[!'()*]/g, function (c) {
							 | 
						||
| 
								 | 
							
								      return '%' + c.charCodeAt(0).toString(16).toUpperCase();
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   * @param {string} operator
							 | 
						||
| 
								 | 
							
								   * @param {string} value
							 | 
						||
| 
								 | 
							
								   * @param {string} key
							 | 
						||
| 
								 | 
							
								   * @return {string}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  UrlTemplate.prototype.encodeValue = function (operator, value, key) {
							 | 
						||
| 
								 | 
							
								    value = (operator === '+' || operator === '#') ? this.encodeReserved(value) : this.encodeUnreserved(value);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (key) {
							 | 
						||
| 
								 | 
							
								      return this.encodeUnreserved(key) + '=' + value;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return value;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   * @param {*} value
							 | 
						||
| 
								 | 
							
								   * @return {boolean}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  UrlTemplate.prototype.isDefined = function (value) {
							 | 
						||
| 
								 | 
							
								    return value !== undefined && value !== null;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   * @param {string}
							 | 
						||
| 
								 | 
							
								   * @return {boolean}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  UrlTemplate.prototype.isKeyOperator = function (operator) {
							 | 
						||
| 
								 | 
							
								    return operator === ';' || operator === '&' || operator === '?';
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @private
							 | 
						||
| 
								 | 
							
								   * @param {Object} context
							 | 
						||
| 
								 | 
							
								   * @param {string} operator
							 | 
						||
| 
								 | 
							
								   * @param {string} key
							 | 
						||
| 
								 | 
							
								   * @param {string} modifier
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  UrlTemplate.prototype.getValues = function (context, operator, key, modifier) {
							 | 
						||
| 
								 | 
							
								    var value = context[key],
							 | 
						||
| 
								 | 
							
								        result = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (this.isDefined(value) && value !== '') {
							 | 
						||
| 
								 | 
							
								      if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
							 | 
						||
| 
								 | 
							
								        value = value.toString();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (modifier && modifier !== '*') {
							 | 
						||
| 
								 | 
							
								          value = value.substring(0, parseInt(modifier, 10));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null));
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        if (modifier === '*') {
							 | 
						||
| 
								 | 
							
								          if (Array.isArray(value)) {
							 | 
						||
| 
								 | 
							
								            value.filter(this.isDefined).forEach(function (value) {
							 | 
						||
| 
								 | 
							
								              result.push(this.encodeValue(operator, value, this.isKeyOperator(operator) ? key : null));
							 | 
						||
| 
								 | 
							
								            }, this);
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            Object.keys(value).forEach(function (k) {
							 | 
						||
| 
								 | 
							
								              if (this.isDefined(value[k])) {
							 | 
						||
| 
								 | 
							
								                result.push(this.encodeValue(operator, value[k], k));
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }, this);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								          var tmp = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (Array.isArray(value)) {
							 | 
						||
| 
								 | 
							
								            value.filter(this.isDefined).forEach(function (value) {
							 | 
						||
| 
								 | 
							
								              tmp.push(this.encodeValue(operator, value));
							 | 
						||
| 
								 | 
							
								            }, this);
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            Object.keys(value).forEach(function (k) {
							 | 
						||
| 
								 | 
							
								              if (this.isDefined(value[k])) {
							 | 
						||
| 
								 | 
							
								                tmp.push(this.encodeUnreserved(k));
							 | 
						||
| 
								 | 
							
								                tmp.push(this.encodeValue(operator, value[k].toString()));
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								            }, this);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								          if (this.isKeyOperator(operator)) {
							 | 
						||
| 
								 | 
							
								            result.push(this.encodeUnreserved(key) + '=' + tmp.join(','));
							 | 
						||
| 
								 | 
							
								          } else if (tmp.length !== 0) {
							 | 
						||
| 
								 | 
							
								            result.push(tmp.join(','));
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      if (operator === ';') {
							 | 
						||
| 
								 | 
							
								        if (this.isDefined(value)) {
							 | 
						||
| 
								 | 
							
								          result.push(this.encodeUnreserved(key));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      } else if (value === '' && (operator === '&' || operator === '?')) {
							 | 
						||
| 
								 | 
							
								        result.push(this.encodeUnreserved(key) + '=');
							 | 
						||
| 
								 | 
							
								      } else if (value === '') {
							 | 
						||
| 
								 | 
							
								        result.push('');
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * @param {string} template
							 | 
						||
| 
								 | 
							
								   * @return {function(Object):string}
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  UrlTemplate.prototype.parse = function (template) {
							 | 
						||
| 
								 | 
							
								    var that = this;
							 | 
						||
| 
								 | 
							
								    var operators = ['+', '#', '.', '/', ';', '?', '&'];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return {
							 | 
						||
| 
								 | 
							
								      expand: function (context) {
							 | 
						||
| 
								 | 
							
								        return template.replace(/\{([^\{\}]+)\}|([^\{\}]+)/g, function (_, expression, literal) {
							 | 
						||
| 
								 | 
							
								          if (expression) {
							 | 
						||
| 
								 | 
							
								            var operator = null,
							 | 
						||
| 
								 | 
							
								                values = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (operators.indexOf(expression.charAt(0)) !== -1) {
							 | 
						||
| 
								 | 
							
								              operator = expression.charAt(0);
							 | 
						||
| 
								 | 
							
								              expression = expression.substr(1);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            expression.split(/,/g).forEach(function (variable) {
							 | 
						||
| 
								 | 
							
								              var tmp = /([^:\*]*)(?::(\d+)|(\*))?/.exec(variable);
							 | 
						||
| 
								 | 
							
								              values.push.apply(values, that.getValues(context, operator, tmp[1], tmp[2] || tmp[3]));
							 | 
						||
| 
								 | 
							
								            });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            if (operator && operator !== '+') {
							 | 
						||
| 
								 | 
							
								              var separator = ',';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								              if (operator === '?') {
							 | 
						||
| 
								 | 
							
								                separator = '&';
							 | 
						||
| 
								 | 
							
								              } else if (operator !== '#') {
							 | 
						||
| 
								 | 
							
								                separator = operator;
							 | 
						||
| 
								 | 
							
								              }
							 | 
						||
| 
								 | 
							
								              return (values.length !== 0 ? operator : '') + values.join(separator);
							 | 
						||
| 
								 | 
							
								            } else {
							 | 
						||
| 
								 | 
							
								              return values.join(',');
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          } else {
							 | 
						||
| 
								 | 
							
								            return that.encodeReserved(literal);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    };
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return new UrlTemplate();
							 | 
						||
| 
								 | 
							
								}));
							 |