define([ "dojo/_base/declare", "dojo/_base/lang" ], function(declare, lang) { let cls = declare(null, { type : null, subtype : null, parameters: null, constructor: function(media,parameters) { if (!media) throw "A media must be specified"; media = media.toString(); let parts = media.match(/^([a-zA-Z-]+)\/([a-zA-Z\-+]+)$/); if(!parts) throw "An invalid media type supplied"; this.type = parts[1]; this.subtype = parts[2]; this.parameters = parameters || {}; }, toString : function() { let res = [this.type,'/',this.subtype]; for(var p in this.parameters) { res.push('; '); res.push(p); res.push('='); res.push(this._escapeValue(this.parameters[p])); } return res.join(''); }, _escapeValue : function(value) { if (value) { value = value.toString(); if(value.match(/[()<>@,:;\\".[\]]/)) return '"' + value.replace(/[()<>@,:;\\".[\]]/g, function(x) { return "\\"+ x; } ) + '"'; } return value; } }); let parseSpace = function(text,start) { for(var i = start; i < text.length; i++) { if(!text[i].match(/\s/)) break; } return { pos: i }; }; let parseToken = function(text,start,required) { let token = []; for(var i=start; i< text.length; i++) { let char = text[i]; if (!char.match(/[\w-]/)) break; token.push(char); } if (required && token.length == 0) { if (i == text.length) throw new Error("Unexpected end of line"); else throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[i], pos: i}); } return { value : token.join(''), pos : i }; }; let parseMedia = function(text,start) { let type, subtype; let t = parseToken(text,start,true); type = t.value; start = t.pos; if (text[start] != '/') throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[start], pos: start}); start++; t = parseToken(text,start,true); subtype = t.value; start = t.pos; return { value: { type : type, subtype: subtype }, pos : start }; }; let parseLiteral = function(text,pos,required) { let data = []; let escape, stop; for(var i=pos; (i < text.length) && !stop; i++) { if (escape) { data.push(text[i]); escape = false; } else { switch(text[i]) { case '"': if (pos != i) stop = true; break; case '\\': escape = true; break; default: if (pos == i) { stop = true; i--; } else { data.push(text[i]); } } } } if(required && data.length == 0) new lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[i], pos: i}); return { value : data.join(''), pos : i }; }; let parseParam = function(text,pos) { let t,name,value; t = parseToken(text,pos,true); name = t.value; pos = t.pos; t = parseSpace(text,pos); pos = t.pos; if (text[pos] != '=') throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[pos], pos: pos}); pos++; t = parseSpace(text,pos); pos = t.pos; t = parseToken(text,pos,false); if (t.pos != pos) { value = t.value; pos = t.pos; } else { t = parseLiteral(text,pos,false); if (t.pos == pos) throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[pos], pos: pos}); pos = t.pos; value = t.value; } return { value : { name : name, value : value }, pos : pos }; }; cls.parse = function(text) { let t,pos = 0, media, params = {}; t = parseMedia(text,pos); media = t.value; pos = t.pos; while(pos < text.length) { t = parseSpace(text,pos); pos = t.pos; if (pos < text.length) { if(text[pos] == ';') { pos ++; t = parseSpace(text,pos); pos = t.pos; t = parseParam(text,pos); params[t.value.name] = t.value.value; pos = t.pos; } else { throw lang.replace("Unexpected char '{char}' at '{pos}'", { char: text[pos], pos: pos}); } } } return new cls( media.type + '/' + media.subtype, params ); }; return cls; });