12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087 |
- /*
- Copyright (c) 2010 Jeremy Faivre
- 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 above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
- 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.
- */
- (function(){
- /**
- * Exception class thrown when an error occurs during parsing.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- *
- * @api
- */
-
- /**
- * Constructor.
- *
- * @param string message The error message
- * @param integer parsedLine The line where the error occurred
- * @param integer snippet The snippet of code near the problem
- * @param string parsedFile The file name where the error occurred
- */
- var YamlParseException = function(message, parsedLine, snippet, parsedFile){
- this.rawMessage = message;
- this.parsedLine = (parsedLine !== undefined) ? parsedLine : -1;
- this.snippet = (snippet !== undefined) ? snippet : null;
- this.parsedFile = (parsedFile !== undefined) ? parsedFile : null;
- this.updateRepr();
-
- this.message = message;
- };
- YamlParseException.prototype =
- {
- name: 'YamlParseException',
- message: null,
-
- parsedFile: null,
- parsedLine: -1,
- snippet: null,
- rawMessage: null,
- isDefined: function(input)
- {
- return input != undefined && input != null;
- },
- /**
- * Gets the snippet of code near the error.
- *
- * @return string The snippet of code
- */
- getSnippet: function()
- {
- return this.snippet;
- },
- /**
- * Sets the snippet of code near the error.
- *
- * @param string snippet The code snippet
- */
- setSnippet: function(snippet)
- {
- this.snippet = snippet;
- this.updateRepr();
- },
- /**
- * Gets the filename where the error occurred.
- *
- * This method returns null if a string is parsed.
- *
- * @return string The filename
- */
- getParsedFile: function()
- {
- return this.parsedFile;
- },
- /**
- * Sets the filename where the error occurred.
- *
- * @param string parsedFile The filename
- */
- setParsedFile: function(parsedFile)
- {
- this.parsedFile = parsedFile;
- this.updateRepr();
- },
- /**
- * Gets the line where the error occurred.
- *
- * @return integer The file line
- */
- getParsedLine: function()
- {
- return this.parsedLine;
- },
- /**
- * Sets the line where the error occurred.
- *
- * @param integer parsedLine The file line
- */
- setParsedLine: function(parsedLine)
- {
- this.parsedLine = parsedLine;
- this.updateRepr();
- },
- updateRepr: function()
- {
- this.message = this.rawMessage;
- var dot = false;
- if ('.' === this.message.charAt(this.message.length - 1)) {
- this.message = this.message.substring(0, this.message.length - 1);
- dot = true;
- }
- if (null !== this.parsedFile) {
- this.message += ' in ' + JSON.stringify(this.parsedFile);
- }
- if (this.parsedLine >= 0) {
- this.message += ' at line ' + this.parsedLine;
- }
- if (this.snippet) {
- this.message += ' (near "' + this.snippet + '")';
- }
- if (dot) {
- this.message += '.';
- }
- }
- }
- /**
- * Yaml offers convenience methods to parse and dump YAML.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- *
- * @api
- */
- var YamlRunningUnderNode = false;
- var Yaml = function(){};
- Yaml.prototype =
- {
- /**
- * Parses YAML into a JS representation.
- *
- * The parse method, when supplied with a YAML stream (file),
- * will do its best to convert YAML in a file into a JS representation.
- *
- * Usage:
- * <code>
- * obj = yaml.parseFile('config.yml');
- * </code>
- *
- * @param string input Path of YAML file
- *
- * @return array The YAML converted to a JS representation
- *
- * @throws YamlParseException If the YAML is not valid
- */
- parseFile: function(file /* String */, callback /* Function */)
- {
- if ( callback == null )
- {
- var input = this.getFileContents(file);
- var ret = null;
- try
- {
- ret = this.parse(input);
- }
- catch ( e )
- {
- if ( e instanceof YamlParseException ) {
- e.setParsedFile(file);
- }
- throw e;
- }
- return ret;
- }
-
- this.getFileContents(file, function(data)
- {
- callback(new Yaml().parse(data));
- });
- },
- /**
- * Parses YAML into a JS representation.
- *
- * The parse method, when supplied with a YAML stream (string),
- * will do its best to convert YAML into a JS representation.
- *
- * Usage:
- * <code>
- * obj = yaml.parse(...);
- * </code>
- *
- * @param string input string containing YAML
- *
- * @return array The YAML converted to a JS representation
- *
- * @throws YamlParseException If the YAML is not valid
- */
- parse: function(input /* String */)
- {
- var yaml = new YamlParser();
- return yaml.parse(input);
- },
- /**
- * Dumps a JS representation to a YAML string.
- *
- * The dump method, when supplied with an array, will do its best
- * to convert the array into friendly YAML.
- *
- * @param array array JS representation
- * @param integer inline The level where you switch to inline YAML
- *
- * @return string A YAML string representing the original JS representation
- *
- * @api
- */
- dump: function(array, inline, spaces)
- {
- if ( inline == null ) inline = 2;
- var yaml = new YamlDumper();
- if (spaces) {
- yaml.numSpacesForIndentation = spaces;
- }
- return yaml.dump(array, inline);
- },
-
- getXHR: function()
- {
- if ( window.XMLHttpRequest )
- return new XMLHttpRequest();
-
- if ( window.ActiveXObject )
- {
- var names = [
- "Msxml2.XMLHTTP.6.0",
- "Msxml2.XMLHTTP.3.0",
- "Msxml2.XMLHTTP",
- "Microsoft.XMLHTTP"
- ];
-
- for ( var i = 0; i < 4; i++ )
- {
- try{ return new ActiveXObject(names[i]); }
- catch(e){}
- }
- }
- return null;
- },
-
- getFileContents: function(file, callback)
- {
- if ( YamlRunningUnderNode )
- {
- var fs = require('fs');
- if ( callback == null )
- {
- var data = fs.readFileSync(file);
- if (data == null) return null;
- return ''+data;
- }
- else
- {
- fs.readFile(file, function(err, data)
- {
- if (err)
- callback(null);
- else
- callback(data);
- });
- }
- }
- else
- {
- var request = this.getXHR();
-
- // Sync
- if ( callback == null )
- {
- request.open('GET', file, false);
- request.send(null);
- if ( request.status == 200 || request.status == 0 )
- return request.responseText;
-
- return null;
- }
-
- // Async
- request.onreadystatechange = function()
- {
- if ( request.readyState == 4 )
- if ( request.status == 200 || request.status == 0 )
- callback(request.responseText);
- else
- callback(null);
- };
- request.open('GET', file, true);
- request.send(null);
- }
- }
- };
- var YAML =
- {
- /*
- * @param integer inline The level where you switch to inline YAML
- */
-
- stringify: function(input, inline, spaces)
- {
- return new Yaml().dump(input, inline, spaces);
- },
-
- parse: function(input)
- {
- return new Yaml().parse(input);
- },
-
- load: function(file, callback)
- {
- return new Yaml().parseFile(file, callback);
- }
- };
- // Handle node.js case
- if (typeof exports !== 'undefined') {
- if (typeof module !== 'undefined' && module.exports) {
- exports = module.exports = YAML;
- YamlRunningUnderNode = true;
-
- // Add require handler
- (function () {
- var require_handler = function (module, filename) {
- // fill in result
- module.exports = YAML.load(filename);
- };
- // register require extensions only if we're on node.js
- // hack for browserify
- if ( undefined !== require.extensions ) {
- require.extensions['.yml'] = require_handler;
- require.extensions['.yaml'] = require_handler;
- }
- }());
- }
- }
- // Handle browser case
- if ( typeof(window) != "undefined" )
- {
- window.YAML = YAML;
- }
- /**
- * YamlInline implements a YAML parser/dumper for the YAML inline syntax.
- */
- var YamlInline = function(){};
- YamlInline.prototype =
- {
- i: null,
-
- /**
- * Convert a YAML string to a JS object.
- *
- * @param string value A YAML string
- *
- * @return object A JS object representing the YAML string
- */
- parse: function(value)
- {
- var result = null;
- value = this.trim(value);
- if ( 0 == value.length )
- {
- return '';
- }
- switch ( value.charAt(0) )
- {
- case '[':
- result = this.parseSequence(value);
- break;
- case '{':
- result = this.parseMapping(value);
- break;
- default:
- result = this.parseScalar(value);
- }
- // some comment can end the scalar
- if ( value.substr(this.i+1).replace(/^\s*#.*$/, '') != '' ) {
- console.log("oups "+value.substr(this.i+1));
- throw new YamlParseException('Unexpected characters near "'+value.substr(this.i)+'".');
- }
- return result;
- },
- /**
- * Dumps a given JS variable to a YAML string.
- *
- * @param mixed value The JS variable to convert
- *
- * @return string The YAML string representing the JS object
- */
- dump: function(value)
- {
- if ( undefined == value || null == value )
- return 'null';
- if ( value instanceof Date)
- return value.toISOString();
- if ( typeof(value) == 'object')
- return this.dumpObject(value);
- if ( typeof(value) == 'boolean' )
- return value ? 'true' : 'false';
- if ( /^\d+$/.test(value) )
- return typeof(value) == 'string' ? "'"+value+"'" : parseInt(value);
- if ( this.isNumeric(value) )
- return typeof(value) == 'string' ? "'"+value+"'" : parseFloat(value);
- if ( typeof(value) == 'number' )
- return value == Infinity ? '.Inf' : ( value == -Infinity ? '-.Inf' : ( isNaN(value) ? '.NAN' : value ) );
- var yaml = new YamlEscaper();
- if ( yaml.requiresDoubleQuoting(value) )
- return yaml.escapeWithDoubleQuotes(value);
- if ( yaml.requiresSingleQuoting(value) )
- return yaml.escapeWithSingleQuotes(value);
- if ( '' == value )
- return '""';
- if ( this.getTimestampRegex().test(value) )
- return "'"+value+"'";
- if ( this.inArray(value.toLowerCase(), ['null','~','true','false']) )
- return "'"+value+"'";
- // default
- return value;
- },
- /**
- * Dumps a JS object to a YAML string.
- *
- * @param object value The JS array to dump
- *
- * @return string The YAML string representing the JS object
- */
- dumpObject: function(value)
- {
- var keys = this.getKeys(value);
- var output = null;
- var i;
- var len = keys.length;
- // array
- if ( value instanceof Array )
- /*( 1 == len && '0' == keys[0] )
- ||
- ( len > 1 && this.reduceArray(keys, function(v,w){return Math.floor(v+w);}, 0) == len * (len - 1) / 2) )*/
- {
- output = [];
- for ( i = 0; i < len; i++ )
- {
- output.push(this.dump(value[keys[i]]));
- }
- return '['+output.join(', ')+']';
- }
- // mapping
- output = [];
- for ( i = 0; i < len; i++ )
- {
- output.push(this.dump(keys[i])+': '+this.dump(value[keys[i]]));
- }
- return '{ '+output.join(', ')+' }';
- },
- /**
- * Parses a scalar to a YAML string.
- *
- * @param scalar scalar
- * @param string delimiters
- * @param object stringDelimiters
- * @param integer i
- * @param boolean evaluate
- *
- * @return string A YAML string
- *
- * @throws YamlParseException When malformed inline YAML string is parsed
- */
- parseScalar: function(scalar, delimiters, stringDelimiters, i, evaluate)
- {
- if ( delimiters == undefined ) delimiters = null;
- if ( stringDelimiters == undefined ) stringDelimiters = ['"', "'"];
- if ( i == undefined ) i = 0;
- if ( evaluate == undefined ) evaluate = true;
-
- var output = null;
- var pos = null;
- var matches = null;
-
- if ( this.inArray(scalar[i], stringDelimiters) )
- {
- // quoted scalar
- output = this.parseQuotedScalar(scalar, i);
- i = this.i;
- if (null !== delimiters) {
- var tmp = scalar.substr(i).replace(/^\s+/, '');
- if (!this.inArray(tmp.charAt(0), delimiters)) {
- throw new YamlParseException('Unexpected characters ('+scalar.substr(i)+').');
- }
- }
- }
- else
- {
- // "normal" string
- if ( !delimiters )
- {
- output = (scalar+'').substring(i);
-
- i += output.length;
- // remove comments
- pos = output.indexOf(' #');
- if ( pos != -1 )
- {
- output = output.substr(0, pos).replace(/\s+$/g,'');
- }
- }
- else if ( matches = new RegExp('^(.+?)('+delimiters.join('|')+')').exec((scalar+'').substring(i)) )
- {
- output = matches[1];
- i += output.length;
- }
- else
- {
- throw new YamlParseException('Malformed inline YAML string ('+scalar+').');
- }
- output = evaluate ? this.evaluateScalar(output) : output;
- }
- this.i = i;
-
- return output;
- },
- /**
- * Parses a quoted scalar to YAML.
- *
- * @param string scalar
- * @param integer i
- *
- * @return string A YAML string
- *
- * @throws YamlParseException When malformed inline YAML string is parsed
- */
- parseQuotedScalar: function(scalar, i)
- {
- var matches = null;
- //var item = /^(.*?)['"]\s*(?:[,:]|[}\]]\s*,)/.exec((scalar+'').substring(i))[1];
-
- if ( !(matches = new RegExp('^'+YamlInline.REGEX_QUOTED_STRING).exec((scalar+'').substring(i))) )
- {
- throw new YamlParseException('Malformed inline YAML string ('+(scalar+'').substring(i)+').');
- }
- var output = matches[0].substr(1, matches[0].length - 2);
-
- var unescaper = new YamlUnescaper();
- if ( '"' == (scalar+'').charAt(i) )
- {
- output = unescaper.unescapeDoubleQuotedString(output);
- }
- else
- {
- output = unescaper.unescapeSingleQuotedString(output);
- }
- i += matches[0].length;
- this.i = i;
- return output;
- },
- /**
- * Parses a sequence to a YAML string.
- *
- * @param string sequence
- * @param integer i
- *
- * @return string A YAML string
- *
- * @throws YamlParseException When malformed inline YAML string is parsed
- */
- parseSequence: function(sequence, i)
- {
- if ( i == undefined ) i = 0;
-
- var output = [];
- var len = sequence.length;
- i += 1;
- // [foo, bar, ...]
- while ( i < len )
- {
- switch ( sequence.charAt(i) )
- {
- case '[':
- // nested sequence
- output.push(this.parseSequence(sequence, i));
- i = this.i;
- break;
- case '{':
- // nested mapping
- output.push(this.parseMapping(sequence, i));
- i = this.i;
- break;
- case ']':
- this.i = i;
- return output;
- case ',':
- case ' ':
- break;
- default:
- var isQuoted = this.inArray(sequence.charAt(i), ['"', "'"]);
- var value = this.parseScalar(sequence, [',', ']'], ['"', "'"], i);
- i = this.i;
-
- if ( !isQuoted && (value+'').indexOf(': ') != -1 )
- {
- // embedded mapping?
- try
- {
- value = this.parseMapping('{'+value+'}');
- }
- catch ( e )
- {
- if ( !(e instanceof YamlParseException ) ) throw e;
- // no, it's not
- }
- }
- output.push(value);
- i--;
- }
- i++;
- }
- throw new YamlParseException('Malformed inline YAML string "'+sequence+'"');
- },
- /**
- * Parses a mapping to a YAML string.
- *
- * @param string mapping
- * @param integer i
- *
- * @return string A YAML string
- *
- * @throws YamlParseException When malformed inline YAML string is parsed
- */
- parseMapping: function(mapping, i)
- {
- if ( i == undefined ) i = 0;
- var output = {};
- var len = mapping.length;
- i += 1;
- var done = false;
- var doContinue = false;
- // {foo: bar, bar:foo, ...}
- while ( i < len )
- {
- doContinue = false;
-
- switch ( mapping.charAt(i) )
- {
- case ' ':
- case ',':
- i++;
- doContinue = true;
- break;
- case '}':
- this.i = i;
- return output;
- }
-
- if ( doContinue ) continue;
- // key
- var key = this.parseScalar(mapping, [':', ' '], ['"', "'"], i, false);
- i = this.i;
- // value
- done = false;
- while ( i < len )
- {
- switch ( mapping.charAt(i) )
- {
- case '[':
- // nested sequence
- output[key] = this.parseSequence(mapping, i);
- i = this.i;
- done = true;
- break;
- case '{':
- // nested mapping
- output[key] = this.parseMapping(mapping, i);
- i = this.i;
- done = true;
- break;
- case ':':
- case ' ':
- break;
- default:
- output[key] = this.parseScalar(mapping, [',', '}'], ['"', "'"], i);
- i = this.i;
- done = true;
- i--;
- }
- ++i;
- if ( done )
- {
- doContinue = true;
- break;
- }
- }
-
- if ( doContinue ) continue;
- }
- throw new YamlParseException('Malformed inline YAML string "'+mapping+'"');
- },
- /**
- * Evaluates scalars and replaces magic values.
- *
- * @param string scalar
- *
- * @return string A YAML string
- */
- evaluateScalar: function(scalar)
- {
- scalar = this.trim(scalar);
-
- var raw = null;
- var cast = null;
- if ( ( 'null' == scalar.toLowerCase() ) ||
- ( '' == scalar ) ||
- ( '~' == scalar ) )
- return null;
- if ( (scalar+'').indexOf('!str ') == 0 )
- return (''+scalar).substring(5);
- if ( (scalar+'').indexOf('! ') == 0 )
- return parseInt(this.parseScalar((scalar+'').substr(2)));
- if ( /^\d+$/.test(scalar) )
- {
- raw = scalar;
- cast = parseInt(scalar);
- return '0' == scalar.charAt(0) ? this.octdec(scalar) : (( ''+raw == ''+cast ) ? cast : raw);
- }
- if ( 'true' == (scalar+'').toLowerCase() )
- return true;
- if ( 'false' == (scalar+'').toLowerCase() )
- return false;
- if ( this.isNumeric(scalar) )
- return '0x' == (scalar+'').substr(0, 2) ? this.hexdec(scalar) : parseFloat(scalar);
- if ( scalar.toLowerCase() == '.inf' )
- return Infinity;
- if ( scalar.toLowerCase() == '.nan' )
- return NaN;
- if ( scalar.toLowerCase() == '-.inf' )
- return -Infinity;
- if ( /^(-|\+)?[0-9,]+(\.[0-9]+)?$/.test(scalar) )
- return parseFloat(scalar.split(',').join(''));
- if ( this.getTimestampRegex().test(scalar) )
- return new Date(this.strtotime(scalar));
- //else
- return ''+scalar;
- },
- /**
- * Gets a regex that matches an unix timestamp
- *
- * @return string The regular expression
- */
- getTimestampRegex: function()
- {
- return new RegExp('^'+
- '([0-9][0-9][0-9][0-9])'+
- '-([0-9][0-9]?)'+
- '-([0-9][0-9]?)'+
- '(?:(?:[Tt]|[ \t]+)'+
- '([0-9][0-9]?)'+
- ':([0-9][0-9])'+
- ':([0-9][0-9])'+
- '(?:\.([0-9]*))?'+
- '(?:[ \t]*(Z|([-+])([0-9][0-9]?)'+
- '(?::([0-9][0-9]))?))?)?'+
- '$','gi');
- },
-
- trim: function(str /* String */)
- {
- return (str+'').replace(/^\s+/,'').replace(/\s+$/,'');
- },
-
- isNumeric: function(input)
- {
- return (input - 0) == input && input.length > 0 && input.replace(/\s+/g,'') != '';
- },
-
- inArray: function(key, tab)
- {
- var i;
- var len = tab.length;
- for ( i = 0; i < len; i++ )
- {
- if ( key == tab[i] ) return true;
- }
- return false;
- },
-
- getKeys: function(tab)
- {
- var ret = [];
-
- for ( var name in tab )
- {
- if ( tab.hasOwnProperty(name) )
- {
- ret.push(name);
- }
- }
-
- return ret;
- },
-
- /*reduceArray: function(tab, fun)
- {
- var len = tab.length;
- if (typeof fun != "function")
- throw new YamlParseException("fun is not a function");
-
- // no value to return if no initial value and an empty array
- if (len == 0 && arguments.length == 1)
- throw new YamlParseException("empty array");
-
- var i = 0;
- if (arguments.length >= 2)
- {
- var rv = arguments[1];
- }
- else
- {
- do
- {
- if (i in tab)
- {
- rv = tab[i++];
- break;
- }
-
- // if array contains no values, no initial value to return
- if (++i >= len)
- throw new YamlParseException("no initial value to return");
- }
- while (true);
- }
- for (; i < len; i++)
- {
- if (i in tab)
- rv = fun.call(null, rv, tab[i], i, tab);
- }
- return rv;
- },*/
-
- octdec: function(input)
- {
- return parseInt((input+'').replace(/[^0-7]/gi, ''), 8);
- },
-
- hexdec: function(input)
- {
- input = this.trim(input);
- if ( (input+'').substr(0, 2) == '0x' ) input = (input+'').substring(2);
- return parseInt((input+'').replace(/[^a-f0-9]/gi, ''), 16);
- },
-
- /**
- * @see http://phpjs.org/functions/strtotime
- * @note we need timestamp with msecs so /1000 removed
- * @note original contained binary | 0 (wtf?!) everywhere, which messes everything up
- */
- strtotime: function (h,b){var f,c,g,k,d="";h=(h+"").replace(/\s{2,}|^\s|\s$/g," ").replace(/[\t\r\n]/g,"");if(h==="now"){return b===null||isNaN(b)?new Date().getTime()||0:b||0}else{if(!isNaN(d=Date.parse(h))){return d||0}else{if(b){b=new Date(b)}else{b=new Date()}}}h=h.toLowerCase();var e={day:{sun:0,mon:1,tue:2,wed:3,thu:4,fri:5,sat:6},mon:["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"]};var a=function(i){var o=(i[2]&&i[2]==="ago");var n=(n=i[0]==="last"?-1:1)*(o?-1:1);switch(i[0]){case"last":case"next":switch(i[1].substring(0,3)){case"yea":b.setFullYear(b.getFullYear()+n);break;case"wee":b.setDate(b.getDate()+(n*7));break;case"day":b.setDate(b.getDate()+n);break;case"hou":b.setHours(b.getHours()+n);break;case"min":b.setMinutes(b.getMinutes()+n);break;case"sec":b.setSeconds(b.getSeconds()+n);break;case"mon":if(i[1]==="month"){b.setMonth(b.getMonth()+n);break}default:var l=e.day[i[1].substring(0,3)];if(typeof l!=="undefined"){var p=l-b.getDay();if(p===0){p=7*n}else{if(p>0){if(i[0]==="last"){p-=7}}else{if(i[0]==="next"){p+=7}}}b.setDate(b.getDate()+p);b.setHours(0,0,0,0)}}break;default:if(/\d+/.test(i[0])){n*=parseInt(i[0],10);switch(i[1].substring(0,3)){case"yea":b.setFullYear(b.getFullYear()+n);break;case"mon":b.setMonth(b.getMonth()+n);break;case"wee":b.setDate(b.getDate()+(n*7));break;case"day":b.setDate(b.getDate()+n);break;case"hou":b.setHours(b.getHours()+n);break;case"min":b.setMinutes(b.getMinutes()+n);break;case"sec":b.setSeconds(b.getSeconds()+n);break}}else{return false}break}return true};g=h.match(/^(\d{2,4}-\d{2}-\d{2})(?:\s(\d{1,2}:\d{2}(:\d{2})?)?(?:\.(\d+))?)?$/);if(g!==null){if(!g[2]){g[2]="00:00:00"}else{if(!g[3]){g[2]+=":00"}}k=g[1].split(/-/g);k[1]=e.mon[k[1]-1]||k[1];k[0]=+k[0];k[0]=(k[0]>=0&&k[0]<=69)?"20"+(k[0]<10?"0"+k[0]:k[0]+""):(k[0]>=70&&k[0]<=99)?"19"+k[0]:k[0]+"";return parseInt(this.strtotime(k[2]+" "+k[1]+" "+k[0]+" "+g[2])+(g[4]?g[4]:""),10)}var j="([+-]?\\d+\\s(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday)|(last|next)\\s(years?|months?|weeks?|days?|hours?|min|minutes?|sec|seconds?|sun\\.?|sunday|mon\\.?|monday|tue\\.?|tuesday|wed\\.?|wednesday|thu\\.?|thursday|fri\\.?|friday|sat\\.?|saturday))(\\sago)?";g=h.match(new RegExp(j,"gi"));if(g===null){return false}for(f=0,c=g.length;f<c;f++){if(!a(g[f].split(" "))){return false}}return b.getTime()||0}
-
- };
- /*
- * @note uses only non-capturing sub-patterns (unlike PHP original)
- */
- YamlInline.REGEX_QUOTED_STRING = '(?:"(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\']*(?:\'\'[^\']*)*)\')';
- /**
- * YamlParser parses YAML strings to convert them to JS objects
- * (port of Yaml Symfony Component)
- */
- var YamlParser = function(offset /* Integer */)
- {
- this.offset = (offset !== undefined) ? offset : 0;
- };
- YamlParser.prototype =
- {
- offset: 0,
- lines: [],
- currentLineNb: -1,
- currentLine: '',
- refs: {},
-
- /**
- * Parses a YAML string to a JS value.
- *
- * @param String value A YAML string
- *
- * @return mixed A JS value
- */
- parse: function(value /* String */)
- {
- this.currentLineNb = -1;
- this.currentLine = '';
- this.lines = this.cleanup(value).split("\n");
-
- var data = null;
- var context = null;
-
- while ( this.moveToNextLine() )
- {
- if ( this.isCurrentLineEmpty() )
- {
- continue;
- }
-
- // tab?
- if ( this.currentLine.charAt(0) == '\t' )
- {
- throw new YamlParseException('A YAML file cannot contain tabs as indentation.', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
-
- var isRef = false;
- var isInPlace = false;
- var isProcessed = false;
- var values = null;
- var matches = null;
- var c = null;
- var parser = null;
- var block = null;
- var key = null;
- var parsed = null;
- var len = null;
- var reverse = null;
-
- if ( values = /^\-((\s+)(.+?))?\s*$/.exec(this.currentLine) )
- {
- if (context && 'mapping' == context) {
- throw new YamlParseException('You cannot define a sequence item when in a mapping', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- context = 'sequence';
- if ( !this.isDefined(data) ) data = [];
- //if ( !(data instanceof Array) ) throw new YamlParseException("Non array entry", this.getRealCurrentLineNb() + 1, this.currentLine);
-
- values = {leadspaces: values[2], value: values[3]};
-
- if ( this.isDefined(values.value) && ( matches = /^&([^ ]+) *(.*)/.exec(values.value) ) )
- {
- matches = {ref: matches[1], value: matches[2]};
- isRef = matches.ref;
- values.value = matches.value;
- }
-
- // array
- if ( !this.isDefined(values.value) || '' == this.trim(values.value) || values.value.replace(/^ +/,'').charAt(0) == '#' )
- {
- c = this.getRealCurrentLineNb() + 1;
- parser = new YamlParser(c);
- parser.refs = this.refs;
- data.push(parser.parse(this.getNextEmbedBlock()));
- this.refs = parser.refs;
- }
- else
- {
- if ( this.isDefined(values.leadspaces) &&
- ' ' == values.leadspaces &&
- ( matches = new RegExp('^('+YamlInline.REGEX_QUOTED_STRING+'|[^ \'"\{\[].*?) *\:(\\s+(.+?))?\\s*$').exec(values.value) )
- ) {
- matches = {key: matches[1], value: matches[3]};
- // this is a compact notation element, add to next block and parse
- c = this.getRealCurrentLineNb();
- parser = new YamlParser(c);
- parser.refs = this.refs;
- block = values.value;
-
- if ( !this.isNextLineIndented() )
- {
- block += "\n"+this.getNextEmbedBlock(this.getCurrentLineIndentation() + 2);
- }
- data.push(parser.parse(block));
- this.refs = parser.refs;
- }
- else
- {
- data.push(this.parseValue(values.value));
- }
- }
- }
- else if ( values = new RegExp('^('+YamlInline.REGEX_QUOTED_STRING+'|[^ \'"\[\{].*?) *\:(\\s+(.+?))?\\s*$').exec(this.currentLine) )
- {
- if ( !this.isDefined(data) ) data = {};
- if (context && 'sequence' == context) {
- throw new YamlParseException('You cannot define a mapping item when in a sequence', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- context = 'mapping';
- //if ( data instanceof Array ) throw new YamlParseException("Non mapped entry", this.getRealCurrentLineNb() + 1, this.currentLine);
-
- values = {key: values[1], value: values[3]};
-
- try {
- key = new YamlInline().parseScalar(values.key);
- } catch (e) {
- if ( e instanceof YamlParseException ) {
- e.setParsedLine(this.getRealCurrentLineNb() + 1);
- e.setSnippet(this.currentLine);
- }
- throw e;
- }
-
-
- if ( '<<' == key )
- {
- if ( this.isDefined(values.value) && '*' == (values.value+'').charAt(0) )
- {
- isInPlace = values.value.substr(1);
- if ( this.refs[isInPlace] == undefined )
- {
- throw new YamlParseException('Reference "'+value+'" does not exist', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- }
- else
- {
- if ( this.isDefined(values.value) && values.value != '' )
- {
- value = values.value;
- }
- else
- {
- value = this.getNextEmbedBlock();
- }
-
- c = this.getRealCurrentLineNb() + 1;
- parser = new YamlParser(c);
- parser.refs = this.refs;
- parsed = parser.parse(value);
- this.refs = parser.refs;
-
- var merged = [];
- if ( !this.isObject(parsed) )
- {
- throw new YamlParseException("YAML merge keys used with a scalar value instead of an array", this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- else if ( this.isDefined(parsed[0]) )
- {
- // Numeric array, merge individual elements
- reverse = this.reverseArray(parsed);
- len = reverse.length;
- for ( var i = 0; i < len; i++ )
- {
- var parsedItem = reverse[i];
- if ( !this.isObject(reverse[i]) )
- {
- throw new YamlParseException("Merge items must be arrays", this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- merged = this.mergeObject(reverse[i], merged);
- }
- }
- else
- {
- // Associative array, merge
- merged = this.mergeObject(merged, parsed);
- }
-
- isProcessed = merged;
- }
- }
- else if ( this.isDefined(values.value) && (matches = /^&([^ ]+) *(.*)/.exec(values.value) ) )
- {
- matches = {ref: matches[1], value: matches[2]};
- isRef = matches.ref;
- values.value = matches.value;
- }
-
- if ( isProcessed )
- {
- // Merge keys
- data = isProcessed;
- }
- // hash
- else if ( !this.isDefined(values.value) || '' == this.trim(values.value) || this.trim(values.value).charAt(0) == '#' )
- {
- // if next line is less indented or equal, then it means that the current value is null
- if ( this.isNextLineIndented() && !this.isNextLineUnIndentedCollection() )
- {
- data[key] = null;
- }
- else
- {
- c = this.getRealCurrentLineNb() + 1;
- parser = new YamlParser(c);
- parser.refs = this.refs;
- data[key] = parser.parse(this.getNextEmbedBlock());
- this.refs = parser.refs;
- }
- }
- else
- {
- if ( isInPlace )
- {
- data = this.refs[isInPlace];
- }
- else
- {
- data[key] = this.parseValue(values.value);
- }
- }
- }
- else
- {
- // 1-liner followed by newline
- if ( 2 == this.lines.length && this.isEmpty(this.lines[1]) )
- {
- try {
- value = new YamlInline().parse(this.lines[0]);
- } catch (e) {
- if ( e instanceof YamlParseException ) {
- e.setParsedLine(this.getRealCurrentLineNb() + 1);
- e.setSnippet(this.currentLine);
- }
- throw e;
- }
-
- if ( this.isObject(value) )
- {
- var first = value[0];
- if ( typeof(value) == 'string' && '*' == first.charAt(0) )
- {
- data = [];
- len = value.length;
- for ( var i = 0; i < len; i++ )
- {
- data.push(this.refs[value[i].substr(1)]);
- }
- value = data;
- }
- }
-
- return value;
- }
-
- throw new YamlParseException('Unable to parse.', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
-
- if ( isRef )
- {
- if ( data instanceof Array )
- this.refs[isRef] = data[data.length-1];
- else
- {
- var lastKey = null;
- for ( var k in data )
- {
- if ( data.hasOwnProperty(k) ) lastKey = k;
- }
- this.refs[isRef] = data[k];
- }
- }
- }
-
- return this.isEmpty(data) ? null : data;
- },
- /**
- * Returns the current line number (takes the offset into account).
- *
- * @return integer The current line number
- */
- getRealCurrentLineNb: function()
- {
- return this.currentLineNb + this.offset;
- },
- /**
- * Returns the current line indentation.
- *
- * @return integer The current line indentation
- */
- getCurrentLineIndentation: function()
- {
- return this.currentLine.length - this.currentLine.replace(/^ +/g, '').length;
- },
- /**
- * Returns the next embed block of YAML.
- *
- * @param integer indentation The indent level at which the block is to be read, or null for default
- *
- * @return string A YAML string
- *
- * @throws YamlParseException When indentation problem are detected
- */
- getNextEmbedBlock: function(indentation)
- {
- this.moveToNextLine();
- var newIndent = null;
- var indent = null;
- if ( !this.isDefined(indentation) )
- {
- newIndent = this.getCurrentLineIndentation();
-
- var unindentedEmbedBlock = this.isStringUnIndentedCollectionItem(this.currentLine);
- if ( !this.isCurrentLineEmpty() && 0 == newIndent && !unindentedEmbedBlock )
- {
- throw new YamlParseException('Indentation problem A', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- }
- else
- {
- newIndent = indentation;
- }
- var data = [this.currentLine.substr(newIndent)];
- var isUnindentedCollection = this.isStringUnIndentedCollectionItem(this.currentLine);
- var continuationIndent = -1;
- if (isUnindentedCollection === true) {
- continuationIndent = 1 + /^\-((\s+)(.+?))?\s*$/.exec(this.currentLine)[2].length;
- }
- while ( this.moveToNextLine() )
- {
- if (isUnindentedCollection && !this.isStringUnIndentedCollectionItem(this.currentLine) && this.getCurrentLineIndentation() != continuationIndent) {
- this.moveToPreviousLine();
- break;
- }
- if ( this.isCurrentLineEmpty() )
- {
- if ( this.isCurrentLineBlank() )
- {
- data.push(this.currentLine.substr(newIndent));
- }
- continue;
- }
- indent = this.getCurrentLineIndentation();
- var matches;
- if ( matches = /^( *)$/.exec(this.currentLine) )
- {
- // empty line
- data.push(matches[1]);
- }
- else if ( indent >= newIndent )
- {
- data.push(this.currentLine.substr(newIndent));
- }
- else if ( 0 == indent )
- {
- this.moveToPreviousLine();
- break;
- }
- else
- {
- throw new YamlParseException('Indentation problem B', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- }
- return data.join("\n");
- },
- /**
- * Moves the parser to the next line.
- *
- * @return Boolean
- */
- moveToNextLine: function()
- {
- if ( this.currentLineNb >= this.lines.length - 1 )
- {
- return false;
- }
- this.currentLineNb++;
- this.currentLine = this.lines[this.currentLineNb];
- return true;
- },
- /**
- * Moves the parser to the previous line.
- */
- moveToPreviousLine: function()
- {
- this.currentLineNb--;
- this.currentLine = this.lines[this.currentLineNb];
- },
- /**
- * Parses a YAML value.
- *
- * @param string value A YAML value
- *
- * @return mixed A JS value
- *
- * @throws YamlParseException When reference does not exist
- */
- parseValue: function(value)
- {
- if ( '*' == (value+'').charAt(0) )
- {
- if ( this.trim(value).charAt(0) == '#' )
- {
- value = (value+'').substr(1, value.indexOf('#') - 2);
- }
- else
- {
- value = (value+'').substr(1);
- }
- if ( this.refs[value] == undefined )
- {
- throw new YamlParseException('Reference "'+value+'" does not exist', this.getRealCurrentLineNb() + 1, this.currentLine);
- }
- return this.refs[value];
- }
- var matches = null;
- if ( matches = /^(\||>)(\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?( +#.*)?$/.exec(value) )
- {
- matches = {separator: matches[1], modifiers: matches[2], comments: matches[3]};
- var modifiers = this.isDefined(matches.modifiers) ? matches.modifiers : '';
- return this.parseFoldedScalar(matches.separator, modifiers.replace(/\d+/g, ''), Math.abs(parseInt(modifiers)));
- }
- try {
- return new YamlInline().parse(value);
- } catch (e) {
- if ( e instanceof YamlParseException ) {
- e.setParsedLine(this.getRealCurrentLineNb() + 1);
- e.setSnippet(this.currentLine);
- }
- throw e;
- }
- },
- /**
- * Parses a folded scalar.
- *
- * @param string separator The separator that was used to begin this folded scalar (| or >)
- * @param string indicator The indicator that was used to begin this folded scalar (+ or -)
- * @param integer indentation The indentation that was used to begin this folded scalar
- *
- * @return string The text value
- */
- parseFoldedScalar: function(separator, indicator, indentation)
- {
- if ( indicator == undefined ) indicator = '';
- if ( indentation == undefined ) indentation = 0;
-
- separator = '|' == separator ? "\n" : ' ';
- var text = '';
- var diff = null;
- var notEOF = this.moveToNextLine();
- while ( notEOF && this.isCurrentLineBlank() )
- {
- text += "\n";
- notEOF = this.moveToNextLine();
- }
- if ( !notEOF )
- {
- return '';
- }
- var matches = null;
- if ( !(matches = new RegExp('^('+(indentation ? this.strRepeat(' ', indentation) : ' +')+')(.*)$').exec(this.currentLine)) )
- {
- this.moveToPreviousLine();
- return '';
- }
-
- matches = {indent: matches[1], text: matches[2]};
-
- var textIndent = matches.indent;
- var previousIndent = 0;
- text += matches.text + separator;
- while ( this.currentLineNb + 1 < this.lines.length )
- {
- this.moveToNextLine();
-
- if ( matches = new RegExp('^( {'+textIndent.length+',})(.+)$').exec(this.currentLine) )
- {
- matches = {indent: matches[1], text: matches[2]};
-
- if ( ' ' == separator && previousIndent != matches.indent )
- {
- text = text.substr(0, text.length - 1)+"\n";
- }
-
- previousIndent = matches.indent;
- diff = matches.indent.length - textIndent.length;
- text += this.strRepeat(' ', diff) + matches.text + (diff != 0 ? "\n" : separator);
- }
- else if ( matches = /^( *)$/.exec(this.currentLine) )
- {
- text += matches[1].replace(new RegExp('^ {1,'+textIndent.length+'}','g'), '')+"\n";
- }
- else
- {
- this.moveToPreviousLine();
- break;
- }
- }
- if ( ' ' == separator )
- {
- // replace last separator by a newline
- text = text.replace(/ (\n*)$/g, "\n$1");
- }
- switch ( indicator )
- {
- case '':
- text = text.replace(/\n+$/g, "\n");
- break;
- case '+':
- break;
- case '-':
- text = text.replace(/\n+$/g, '');
- break;
- }
- return text;
- },
- /**
- * Returns true if the next line is indented.
- *
- * @return Boolean Returns true if the next line is indented, false otherwise
- */
- isNextLineIndented: function()
- {
- var currentIndentation = this.getCurrentLineIndentation();
- var notEOF = this.moveToNextLine();
- while ( notEOF && this.isCurrentLineEmpty() )
- {
- notEOF = this.moveToNextLine();
- }
- if ( false == notEOF )
- {
- return false;
- }
- var ret = false;
- if ( this.getCurrentLineIndentation() <= currentIndentation )
- {
- ret = true;
- }
- this.moveToPreviousLine();
- return ret;
- },
- /**
- * Returns true if the current line is blank or if it is a comment line.
- *
- * @return Boolean Returns true if the current line is empty or if it is a comment line, false otherwise
- */
- isCurrentLineEmpty: function()
- {
- return this.isCurrentLineBlank() || this.isCurrentLineComment();
- },
- /**
- * Returns true if the current line is blank.
- *
- * @return Boolean Returns true if the current line is blank, false otherwise
- */
- isCurrentLineBlank: function()
- {
- return '' == this.trim(this.currentLine);
- },
- /**
- * Returns true if the current line is a comment line.
- *
- * @return Boolean Returns true if the current line is a comment line, false otherwise
- */
- isCurrentLineComment: function()
- {
- //checking explicitly the first char of the trim is faster than loops or strpos
- var ltrimmedLine = this.currentLine.replace(/^ +/g, '');
- return ltrimmedLine.charAt(0) == '#';
- },
- /**
- * Cleanups a YAML string to be parsed.
- *
- * @param string value The input YAML string
- *
- * @return string A cleaned up YAML string
- */
- cleanup: function(value)
- {
- value = value.split("\r\n").join("\n").split("\r").join("\n");
- if ( !/\n$/.test(value) )
- {
- value += "\n";
- }
- // strip YAML header
- var count = 0;
- var regex = /^\%YAML[: ][\d\.]+.*\n/;
- while ( regex.test(value) )
- {
- value = value.replace(regex, '');
- count++;
- }
- this.offset += count;
- // remove leading comments
- regex = /^(#.*?\n)+/;
- if ( regex.test(value) )
- {
- var trimmedValue = value.replace(regex, '');
-
- // items have been removed, update the offset
- this.offset += this.subStrCount(value, "\n") - this.subStrCount(trimmedValue, "\n");
- value = trimmedValue;
- }
- // remove start of the document marker (---)
- regex = /^\-\-\-.*?\n/;
- if ( regex.test(value) )
- {
- trimmedValue = value.replace(regex, '');
-
- // items have been removed, update the offset
- this.offset += this.subStrCount(value, "\n") - this.subStrCount(trimmedValue, "\n");
- value = trimmedValue;
- // remove end of the document marker (...)
- value = value.replace(/\.\.\.\s*$/g, '');
- }
- return value;
- },
- /**
- * Returns true if the next line starts unindented collection
- *
- * @return Boolean Returns true if the next line starts unindented collection, false otherwise
- */
- isNextLineUnIndentedCollection: function()
- {
- var currentIndentation = this.getCurrentLineIndentation();
- var notEOF = this.moveToNextLine();
- while (notEOF && this.isCurrentLineEmpty()) {
- notEOF = this.moveToNextLine();
- }
- if (false === notEOF) {
- return false;
- }
- var ret = false;
- if (
- this.getCurrentLineIndentation() == currentIndentation
- &&
- this.isStringUnIndentedCollectionItem(this.currentLine)
- ) {
- ret = true;
- }
- this.moveToPreviousLine();
- return ret;
- },
- /**
- * Returns true if the string is unindented collection item
- *
- * @return Boolean Returns true if the string is unindented collection item, false otherwise
- */
- isStringUnIndentedCollectionItem: function(string)
- {
- return (0 === this.currentLine.indexOf('- '));
- },
-
- isObject: function(input)
- {
- return typeof(input) == 'object' && this.isDefined(input);
- },
-
- isEmpty: function(input)
- {
- return input == undefined || input == null || input == '' || input == 0 || input == "0" || input == false;
- },
-
- isDefined: function(input)
- {
- return input != undefined && input != null;
- },
-
- reverseArray: function(input /* Array */)
- {
- var result = [];
- var len = input.length;
- for ( var i = len-1; i >= 0; i-- )
- {
- result.push(input[i]);
- }
-
- return result;
- },
-
- merge: function(a /* Object */, b /* Object */)
- {
- var c = {};
- var i;
-
- for ( i in a )
- {
- if ( a.hasOwnProperty(i) )
- if ( /^\d+$/.test(i) ) c.push(a);
- else c[i] = a[i];
- }
- for ( i in b )
- {
- if ( b.hasOwnProperty(i) )
- if ( /^\d+$/.test(i) ) c.push(b);
- else c[i] = b[i];
- }
-
- return c;
- },
-
- strRepeat: function(str /* String */, count /* Integer */)
- {
- var i;
- var result = '';
- for ( i = 0; i < count; i++ ) result += str;
- return result;
- },
-
- subStrCount: function(string, subString, start, length)
- {
- var c = 0;
-
- string = '' + string;
- subString = '' + subString;
-
- if ( start != undefined ) string = string.substr(start);
- if ( length != undefined ) string = string.substr(0, length);
-
- var len = string.length;
- var sublen = subString.length;
- for ( var i = 0; i < len; i++ )
- {
- if ( subString == string.substr(i, sublen) )
- c++;
- i += sublen - 1;
- }
-
- return c;
- },
-
- trim: function(str /* String */)
- {
- return (str+'').replace(/^ +/,'').replace(/ +$/,'');
- }
- };
- /**
- * YamlEscaper encapsulates escaping rules for single and double-quoted
- * YAML strings.
- *
- * @author Matthew Lewinski <matthew@lewinski.org>
- */
- YamlEscaper = function(){};
- YamlEscaper.prototype =
- {
- /**
- * Determines if a JS value would require double quoting in YAML.
- *
- * @param string value A JS value
- *
- * @return Boolean True if the value would require double quotes.
- */
- requiresDoubleQuoting: function(value)
- {
- return new RegExp(YamlEscaper.REGEX_CHARACTER_TO_ESCAPE).test(value);
- },
- /**
- * Escapes and surrounds a JS value with double quotes.
- *
- * @param string value A JS value
- *
- * @return string The quoted, escaped string
- */
- escapeWithDoubleQuotes: function(value)
- {
- value = value + '';
- var len = YamlEscaper.escapees.length;
- var maxlen = YamlEscaper.escaped.length;
- var esc = YamlEscaper.escaped;
- for (var i = 0; i < len; ++i)
- if ( i >= maxlen ) esc.push('');
- var ret = '';
- ret = value.replace(new RegExp(YamlEscaper.escapees.join('|'),'g'), function(str){
- for(var i = 0; i < len; ++i){
- if( str == YamlEscaper.escapees[i] )
- return esc[i];
- }
- });
- return '"' + ret + '"';
- },
- /**
- * Determines if a JS value would require single quoting in YAML.
- *
- * @param string value A JS value
- *
- * @return Boolean True if the value would require single quotes.
- */
- requiresSingleQuoting: function(value)
- {
- return /[\s'":{}[\],&*#?]|^[-?|<>=!%@`]/.test(value);
- },
- /**
- * Escapes and surrounds a JS value with single quotes.
- *
- * @param string value A JS value
- *
- * @return string The quoted, escaped string
- */
- escapeWithSingleQuotes : function(value)
- {
- return "'" + value.replace(/'/g, "''") + "'";
- }
- };
- // Characters that would cause a dumped string to require double quoting.
- YamlEscaper.REGEX_CHARACTER_TO_ESCAPE = "[\\x00-\\x1f]|\xc2\x85|\xc2\xa0|\xe2\x80\xa8|\xe2\x80\xa9";
- // Mapping arrays for escaping a double quoted string. The backslash is
- // first to ensure proper escaping.
- YamlEscaper.escapees = ['\\\\', '\\"', '"',
- "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\x07",
- "\x08", "\x09", "\x0a", "\x0b", "\x0c", "\x0d", "\x0e", "\x0f",
- "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17",
- "\x18", "\x19", "\x1a", "\x1b", "\x1c", "\x1d", "\x1e", "\x1f",
- "\xc2\x85", "\xc2\xa0", "\xe2\x80\xa8", "\xe2\x80\xa9"];
- YamlEscaper.escaped = ['\\"', '\\\\', '\\"',
- "\\0", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\a",
- "\\b", "\\t", "\\n", "\\v", "\\f", "\\r", "\\x0e", "\\x0f",
- "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17",
- "\\x18", "\\x19", "\\x1a", "\\e", "\\x1c", "\\x1d", "\\x1e", "\\x1f",
- "\\N", "\\_", "\\L", "\\P"];
- /**
- * YamlUnescaper encapsulates unescaping rules for single and double-quoted
- * YAML strings.
- *
- * @author Matthew Lewinski <matthew@lewinski.org>
- */
- var YamlUnescaper = function(){};
- YamlUnescaper.prototype =
- {
- /**
- * Unescapes a single quoted string.
- *
- * @param string value A single quoted string.
- *
- * @return string The unescaped string.
- */
- unescapeSingleQuotedString: function(value)
- {
- return value.replace(/''/g, "'");
- },
- /**
- * Unescapes a double quoted string.
- *
- * @param string value A double quoted string.
- *
- * @return string The unescaped string.
- */
- unescapeDoubleQuotedString: function(value)
- {
- var callback = function(m) {
- return new YamlUnescaper().unescapeCharacter(m);
- };
- // evaluate the string
- return value.replace(new RegExp(YamlUnescaper.REGEX_ESCAPED_CHARACTER, 'g'), callback);
- },
- /**
- * Unescapes a character that was found in a double-quoted string
- *
- * @param string value An escaped character
- *
- * @return string The unescaped character
- */
- unescapeCharacter: function(value)
- {
- switch (value.charAt(1)) {
- case '0':
- return String.fromCharCode(0);
- case 'a':
- return String.fromCharCode(7);
- case 'b':
- return String.fromCharCode(8);
- case 't':
- return "\t";
- case "\t":
- return "\t";
- case 'n':
- return "\n";
- case 'v':
- return String.fromCharCode(11);
- case 'f':
- return String.fromCharCode(12);
- case 'r':
- return String.fromCharCode(13);
- case 'e':
- return "\x1b";
- case ' ':
- return ' ';
- case '"':
- return '"';
- case '/':
- return '/';
- case '\\':
- return '\\';
- case 'N':
- // U+0085 NEXT LINE
- return "\x00\x85";
- case '_':
- // U+00A0 NO-BREAK SPACE
- return "\x00\xA0";
- case 'L':
- // U+2028 LINE SEPARATOR
- return "\x20\x28";
- case 'P':
- // U+2029 PARAGRAPH SEPARATOR
- return "\x20\x29";
- case 'x':
- return this.pack('n', new YamlInline().hexdec(value.substr(2, 2)));
- case 'u':
- return this.pack('n', new YamlInline().hexdec(value.substr(2, 4)));
- case 'U':
- return this.pack('N', new YamlInline().hexdec(value.substr(2, 8)));
- }
- },
-
- /**
- * @see http://phpjs.org/functions/pack
- * @warning only modes used above copied
- */
- pack: function(B){var g=0,o=1,m="",l="",z=0,p=[],E,s,C,I,h,c;var d,b,x,H,u,e,A,q,D,t,w,a,G,F,y,v,f;while(g<B.length){E=B.charAt(g);s="";g++;while((g<B.length)&&(B.charAt(g).match(/[\d\*]/)!==null)){s+=B.charAt(g);g++}if(s===""){s="1"}switch(E){case"n":if(s==="*"){s=arguments.length-o}if(s>(arguments.length-o)){throw new Error("Warning: pack() Type "+E+": too few arguments")}for(z=0;z<s;z++){m+=String.fromCharCode(arguments[o]>>8&255);m+=String.fromCharCode(arguments[o]&255);o++}break;case"N":if(s==="*"){s=arguments.length-o}if(s>(arguments.length-o)){throw new Error("Warning: pack() Type "+E+": too few arguments")}for(z=0;z<s;z++){m+=String.fromCharCode(arguments[o]>>24&255);m+=String.fromCharCode(arguments[o]>>16&255);m+=String.fromCharCode(arguments[o]>>8&255);m+=String.fromCharCode(arguments[o]&255);o++}break;default:throw new Error("Warning: pack() Type "+E+": unknown format code")}}if(o<arguments.length){throw new Error("Warning: pack(): "+(arguments.length-o)+" arguments unused")}return m}
- }
- // Regex fragment that matches an escaped character in a double quoted
- // string.
- // why escape quotes, ffs!
- YamlUnescaper.REGEX_ESCAPED_CHARACTER = '\\\\([0abt\tnvfre "\\/\\\\N_LP]|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|U[0-9a-fA-F]{8})';
- /**
- * YamlDumper dumps JS variables to YAML strings.
- *
- * @author Fabien Potencier <fabien@symfony.com>
- */
- var YamlDumper = function(){};
- YamlDumper.prototype =
- {
- /**
- * Dumps a JS value to YAML.
- *
- * @param mixed input The JS value
- * @param integer inline The level where you switch to inline YAML
- * @param integer indent The level o indentation indentation (used internally)
- *
- * @return string The YAML representation of the JS value
- */
- dump: function(input, inline, indent)
- {
- if ( inline == null ) inline = 0;
- if ( indent == null ) indent = 0;
- var output = '';
- var prefix = indent ? this.strRepeat(' ', indent) : '';
- var yaml;
- if (!this.numSpacesForIndentation) this.numSpacesForIndentation = 2;
- if ( inline <= 0 || !this.isObject(input) || this.isEmpty(input) )
- {
- yaml = new YamlInline();
- output += prefix + yaml.dump(input);
- }
- else
- {
- var isAHash = !this.arrayEquals(this.getKeys(input), this.range(0,input.length - 1));
- var willBeInlined;
-
- for ( var key in input )
- {
- if ( input.hasOwnProperty(key) )
- {
- willBeInlined = inline - 1 <= 0 || !this.isObject(input[key]) || this.isEmpty(input[key]);
-
- if ( isAHash ) yaml = new YamlInline();
-
- output +=
- prefix + '' +
- (isAHash ? yaml.dump(key)+':' : '-') + '' +
- (willBeInlined ? ' ' : "\n") + '' +
- this.dump(input[key], inline - 1, (willBeInlined ? 0 : indent + this.numSpacesForIndentation)) + '' +
- (willBeInlined ? "\n" : '');
- }
- }
- }
- return output;
- },
-
- strRepeat: function(str /* String */, count /* Integer */)
- {
- var i;
- var result = '';
- for ( i = 0; i < count; i++ ) result += str;
- return result;
- },
-
- isObject: function(input)
- {
- return this.isDefined(input) && typeof(input) == 'object';
- },
-
- isEmpty: function(input)
- {
- var ret = input == undefined || input == null || input == '' || input == 0 || input == "0" || input == false;
- if ( !ret && typeof(input) == "object" && !(input instanceof Array)){
- var propCount = 0;
- for ( var key in input )
- if ( input.hasOwnProperty(key) ) propCount++;
- ret = !propCount;
- }
- return ret;
- },
-
- isDefined: function(input)
- {
- return input != undefined && input != null;
- },
-
- getKeys: function(tab)
- {
- var ret = [];
-
- for ( var name in tab )
- {
- if ( tab.hasOwnProperty(name) )
- {
- ret.push(name);
- }
- }
-
- return ret;
- },
-
- range: function(start, end)
- {
- if ( start > end ) return [];
-
- var ret = [];
-
- for ( var i = start; i <= end; i++ )
- {
- ret.push(i);
- }
-
- return ret;
- },
-
- arrayEquals: function(a,b)
- {
- if ( a.length != b.length ) return false;
-
- var len = a.length;
-
- for ( var i = 0; i < len; i++ )
- {
- if ( a[i] != b[i] ) return false;
- }
-
- return true;
- }
- };
- })();
|