123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654 |
- (function() {
- // CommonJS require()
- function require(p){
- var path = require.resolve(p)
- , mod = require.modules[path];
- if (!mod) throw new Error('failed to require "' + p + '"');
- if (!mod.exports) {
- mod.exports = {};
- mod.call(mod.exports, mod, mod.exports, require.relative(path));
- }
- return mod.exports;
- }
- require.modules = {};
- require.resolve = function (path){
- var orig = path
- , reg = path + '.js'
- , index = path + '/index.js';
- return require.modules[reg] && reg
- || require.modules[index] && index
- || orig;
- };
- require.register = function (path, fn){
- require.modules[path] = fn;
- };
- require.relative = function (parent) {
- return function(p){
- if ('.' != p.charAt(0)) return require(p);
-
- var path = parent.split('/')
- , segs = p.split('/');
- path.pop();
-
- for (var i = 0; i < segs.length; i++) {
- var seg = segs[i];
- if ('..' == seg) path.pop();
- else if ('.' != seg) path.push(seg);
- }
- return require(path.join('/'));
- };
- };
- require.register("compiler.js", function(module, exports, require){
- /*!
- * Jade - Compiler
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var nodes = require('./nodes')
- , filters = require('./filters')
- , doctypes = require('./doctypes')
- , selfClosing = require('./self-closing')
- , runtime = require('./runtime')
- , utils = require('./utils');
- if (!Object.keys) {
- Object.keys = function(obj){
- var arr = [];
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- arr.push(key);
- }
- }
- return arr;
- }
- }
- if (!String.prototype.trimLeft) {
- String.prototype.trimLeft = function(){
- return this.replace(/^\s+/, '');
- }
- }
- /**
- * Initialize `Compiler` with the given `node`.
- *
- * @param {Node} node
- * @param {Object} options
- * @api public
- */
- var Compiler = module.exports = function Compiler(node, options) {
- this.options = options = options || {};
- this.node = node;
- this.hasCompiledDoctype = false;
- this.hasCompiledTag = false;
- this.pp = options.pretty || false;
- this.debug = false !== options.compileDebug;
- this.indents = 0;
- this.parentIndents = 0;
- if (options.doctype) this.setDoctype(options.doctype);
- };
- /**
- * Compiler prototype.
- */
- Compiler.prototype = {
- /**
- * Compile parse tree to JavaScript.
- *
- * @api public
- */
- compile: function(){
- this.buf = ['var interp;'];
- if (this.pp) this.buf.push("var __indent = [];");
- this.lastBufferedIdx = -1;
- this.visit(this.node);
- return this.buf.join('\n');
- },
- /**
- * Sets the default doctype `name`. Sets terse mode to `true` when
- * html 5 is used, causing self-closing tags to end with ">" vs "/>",
- * and boolean attributes are not mirrored.
- *
- * @param {string} name
- * @api public
- */
- setDoctype: function(name){
- name = (name && name.toLowerCase()) || 'default';
- this.doctype = doctypes[name] || '<!DOCTYPE ' + name + '>';
- this.terse = this.doctype.toLowerCase() == '<!doctype html>';
- this.xml = 0 == this.doctype.indexOf('<?xml');
- },
- /**
- * Buffer the given `str` optionally escaped.
- *
- * @param {String} str
- * @param {Boolean} esc
- * @api public
- */
- buffer: function(str, esc){
- if (esc) str = utils.escape(str);
- if (this.lastBufferedIdx == this.buf.length) {
- this.lastBuffered += str;
- this.buf[this.lastBufferedIdx - 1] = "buf.push('" + this.lastBuffered + "');"
- } else {
- this.buf.push("buf.push('" + str + "');");
- this.lastBuffered = str;
- this.lastBufferedIdx = this.buf.length;
- }
- },
- /**
- * Buffer an indent based on the current `indent`
- * property and an additional `offset`.
- *
- * @param {Number} offset
- * @param {Boolean} newline
- * @api public
- */
- prettyIndent: function(offset, newline){
- offset = offset || 0;
- newline = newline ? '\\n' : '';
- this.buffer(newline + Array(this.indents + offset).join(' '));
- if (this.parentIndents)
- this.buf.push("buf.push.apply(buf, __indent);");
- },
- /**
- * Visit `node`.
- *
- * @param {Node} node
- * @api public
- */
- visit: function(node){
- var debug = this.debug;
- if (debug) {
- this.buf.push('__jade.unshift({ lineno: ' + node.line
- + ', filename: ' + (node.filename
- ? JSON.stringify(node.filename)
- : '__jade[0].filename')
- + ' });');
- }
- // Massive hack to fix our context
- // stack for - else[ if] etc
- if (false === node.debug && this.debug) {
- this.buf.pop();
- this.buf.pop();
- }
- this.visitNode(node);
- if (debug) this.buf.push('__jade.shift();');
- },
- /**
- * Visit `node`.
- *
- * @param {Node} node
- * @api public
- */
- visitNode: function(node){
- var name = node.constructor.name
- || node.constructor.toString().match(/function ([^(\s]+)()/)[1];
- return this['visit' + name](node);
- },
- /**
- * Visit case `node`.
- *
- * @param {Literal} node
- * @api public
- */
- visitCase: function(node){
- var _ = this.withinCase;
- this.withinCase = true;
- this.buf.push('switch (' + node.expr + '){');
- this.visit(node.block);
- this.buf.push('}');
- this.withinCase = _;
- },
- /**
- * Visit when `node`.
- *
- * @param {Literal} node
- * @api public
- */
- visitWhen: function(node){
- if ('default' == node.expr) {
- this.buf.push('default:');
- } else {
- this.buf.push('case ' + node.expr + ':');
- }
- this.visit(node.block);
- this.buf.push(' break;');
- },
- /**
- * Visit literal `node`.
- *
- * @param {Literal} node
- * @api public
- */
- visitLiteral: function(node){
- var str = node.str.replace(/\n/g, '\\\\n');
- this.buffer(str);
- },
- /**
- * Visit all nodes in `block`.
- *
- * @param {Block} block
- * @api public
- */
- visitBlock: function(block){
- var len = block.nodes.length
- , escape = this.escape
- , pp = this.pp
- // Block keyword has a special meaning in mixins
- if (this.parentIndents && block.mode) {
- if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');")
- this.buf.push('block && block();');
- if (pp) this.buf.push("__indent.pop();")
- return;
- }
- // Pretty print multi-line text
- if (pp && len > 1 && !escape && block.nodes[0].isText && block.nodes[1].isText)
- this.prettyIndent(1, true);
- for (var i = 0; i < len; ++i) {
- // Pretty print text
- if (pp && i > 0 && !escape && block.nodes[i].isText && block.nodes[i-1].isText)
- this.prettyIndent(1, false);
- this.visit(block.nodes[i]);
- // Multiple text nodes are separated by newlines
- if (block.nodes[i+1] && block.nodes[i].isText && block.nodes[i+1].isText)
- this.buffer('\\n');
- }
- },
- /**
- * Visit `doctype`. Sets terse mode to `true` when html 5
- * is used, causing self-closing tags to end with ">" vs "/>",
- * and boolean attributes are not mirrored.
- *
- * @param {Doctype} doctype
- * @api public
- */
- visitDoctype: function(doctype){
- if (doctype && (doctype.val || !this.doctype)) {
- this.setDoctype(doctype.val || 'default');
- }
- if (this.doctype) this.buffer(this.doctype);
- this.hasCompiledDoctype = true;
- },
- /**
- * Visit `mixin`, generating a function that
- * may be called within the template.
- *
- * @param {Mixin} mixin
- * @api public
- */
- visitMixin: function(mixin){
- var name = mixin.name.replace(/-/g, '_') + '_mixin'
- , args = mixin.args || ''
- , block = mixin.block
- , attrs = mixin.attrs
- , pp = this.pp;
- if (mixin.call) {
- if (pp) this.buf.push("__indent.push('" + Array(this.indents + 1).join(' ') + "');")
- if (block || attrs.length) {
- this.buf.push(name + '.call({');
- if (block) {
- this.buf.push('block: function(){');
- // Render block with no indents, dynamically added when rendered
- this.parentIndents++;
- var _indents = this.indents;
- this.indents = 0;
- this.visit(mixin.block);
- this.indents = _indents;
- this.parentIndents--;
- if (attrs.length) {
- this.buf.push('},');
- } else {
- this.buf.push('}');
- }
- }
- if (attrs.length) {
- var val = this.attrs(attrs);
- if (val.inherits) {
- this.buf.push('attributes: merge({' + val.buf
- + '}, attributes), escaped: merge(' + val.escaped + ', escaped, true)');
- } else {
- this.buf.push('attributes: {' + val.buf + '}, escaped: ' + val.escaped);
- }
- }
- if (args) {
- this.buf.push('}, ' + args + ');');
- } else {
- this.buf.push('});');
- }
- } else {
- this.buf.push(name + '(' + args + ');');
- }
- if (pp) this.buf.push("__indent.pop();")
- } else {
- this.buf.push('var ' + name + ' = function(' + args + '){');
- this.buf.push('var block = this.block, attributes = this.attributes || {}, escaped = this.escaped || {};');
- this.parentIndents++;
- this.visit(block);
- this.parentIndents--;
- this.buf.push('};');
- }
- },
- /**
- * Visit `tag` buffering tag markup, generating
- * attributes, visiting the `tag`'s code and block.
- *
- * @param {Tag} tag
- * @api public
- */
- visitTag: function(tag){
- this.indents++;
- var name = tag.name
- , pp = this.pp;
- if (tag.buffer) name = "' + (" + name + ") + '";
- if (!this.hasCompiledTag) {
- if (!this.hasCompiledDoctype && 'html' == name) {
- this.visitDoctype();
- }
- this.hasCompiledTag = true;
- }
- // pretty print
- if (pp && !tag.isInline())
- this.prettyIndent(0, true);
- if ((~selfClosing.indexOf(name) || tag.selfClosing) && !this.xml) {
- this.buffer('<' + name);
- this.visitAttributes(tag.attrs);
- this.terse
- ? this.buffer('>')
- : this.buffer('/>');
- } else {
- // Optimize attributes buffering
- if (tag.attrs.length) {
- this.buffer('<' + name);
- if (tag.attrs.length) this.visitAttributes(tag.attrs);
- this.buffer('>');
- } else {
- this.buffer('<' + name + '>');
- }
- if (tag.code) this.visitCode(tag.code);
- this.escape = 'pre' == tag.name;
- this.visit(tag.block);
- // pretty print
- if (pp && !tag.isInline() && 'pre' != tag.name && !tag.canInline())
- this.prettyIndent(0, true);
- this.buffer('</' + name + '>');
- }
- this.indents--;
- },
- /**
- * Visit `filter`, throwing when the filter does not exist.
- *
- * @param {Filter} filter
- * @api public
- */
- visitFilter: function(filter){
- var fn = filters[filter.name];
- // unknown filter
- if (!fn) {
- if (filter.isASTFilter) {
- throw new Error('unknown ast filter "' + filter.name + ':"');
- } else {
- throw new Error('unknown filter ":' + filter.name + '"');
- }
- }
- if (filter.isASTFilter) {
- this.buf.push(fn(filter.block, this, filter.attrs));
- } else {
- var text = filter.block.nodes.map(function(node){ return node.val }).join('\n');
- filter.attrs = filter.attrs || {};
- filter.attrs.filename = this.options.filename;
- this.buffer(utils.text(fn(text, filter.attrs)));
- }
- },
- /**
- * Visit `text` node.
- *
- * @param {Text} text
- * @api public
- */
- visitText: function(text){
- text = utils.text(text.val.replace(/\\/g, '_SLASH_'));
- if (this.escape) text = escape(text);
- text = text.replace(/_SLASH_/g, '\\\\');
- this.buffer(text);
- },
- /**
- * Visit a `comment`, only buffering when the buffer flag is set.
- *
- * @param {Comment} comment
- * @api public
- */
- visitComment: function(comment){
- if (!comment.buffer) return;
- if (this.pp) this.prettyIndent(1, true);
- this.buffer('<!--' + utils.escape(comment.val) + '-->');
- },
- /**
- * Visit a `BlockComment`.
- *
- * @param {Comment} comment
- * @api public
- */
- visitBlockComment: function(comment){
- if (!comment.buffer) return;
- if (0 == comment.val.trim().indexOf('if')) {
- this.buffer('<!--[' + comment.val.trim() + ']>');
- this.visit(comment.block);
- this.buffer('<![endif]-->');
- } else {
- this.buffer('<!--' + comment.val);
- this.visit(comment.block);
- this.buffer('-->');
- }
- },
- /**
- * Visit `code`, respecting buffer / escape flags.
- * If the code is followed by a block, wrap it in
- * a self-calling function.
- *
- * @param {Code} code
- * @api public
- */
- visitCode: function(code){
- // Wrap code blocks with {}.
- // we only wrap unbuffered code blocks ATM
- // since they are usually flow control
- // Buffer code
- if (code.buffer) {
- var val = code.val.trimLeft();
- this.buf.push('var __val__ = ' + val);
- val = 'null == __val__ ? "" : __val__';
- if (code.escape) val = 'escape(' + val + ')';
- this.buf.push("buf.push(" + val + ");");
- } else {
- this.buf.push(code.val);
- }
- // Block support
- if (code.block) {
- if (!code.buffer) this.buf.push('{');
- this.visit(code.block);
- if (!code.buffer) this.buf.push('}');
- }
- },
- /**
- * Visit `each` block.
- *
- * @param {Each} each
- * @api public
- */
- visitEach: function(each){
- this.buf.push(''
- + '// iterate ' + each.obj + '\n'
- + ';(function(){\n'
- + ' if (\'number\' == typeof ' + each.obj + '.length) {\n');
- if (each.alternative) {
- this.buf.push(' if (' + each.obj + '.length) {');
- }
- this.buf.push(''
- + ' for (var ' + each.key + ' = 0, $$l = ' + each.obj + '.length; ' + each.key + ' < $$l; ' + each.key + '++) {\n'
- + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n');
- this.visit(each.block);
- this.buf.push(' }\n');
- if (each.alternative) {
- this.buf.push(' } else {');
- this.visit(each.alternative);
- this.buf.push(' }');
- }
- this.buf.push(''
- + ' } else {\n'
- + ' var $$l = 0;\n'
- + ' for (var ' + each.key + ' in ' + each.obj + ') {\n'
- + ' $$l++;'
- + ' if (' + each.obj + '.hasOwnProperty(' + each.key + ')){'
- + ' var ' + each.val + ' = ' + each.obj + '[' + each.key + '];\n');
- this.visit(each.block);
- this.buf.push(' }\n');
- this.buf.push(' }\n');
- if (each.alternative) {
- this.buf.push(' if ($$l === 0) {');
- this.visit(each.alternative);
- this.buf.push(' }');
- }
- this.buf.push(' }\n}).call(this);\n');
- },
- /**
- * Visit `attrs`.
- *
- * @param {Array} attrs
- * @api public
- */
- visitAttributes: function(attrs){
- var val = this.attrs(attrs);
- if (val.inherits) {
- this.buf.push("buf.push(attrs(merge({ " + val.buf +
- " }, attributes), merge(" + val.escaped + ", escaped, true)));");
- } else if (val.constant) {
- eval('var buf={' + val.buf + '};');
- this.buffer(runtime.attrs(buf, JSON.parse(val.escaped)), true);
- } else {
- this.buf.push("buf.push(attrs({ " + val.buf + " }, " + val.escaped + "));");
- }
- },
- /**
- * Compile attributes.
- */
- attrs: function(attrs){
- var buf = []
- , classes = []
- , escaped = {}
- , constant = attrs.every(function(attr){ return isConstant(attr.val) })
- , inherits = false;
- if (this.terse) buf.push('terse: true');
- attrs.forEach(function(attr){
- if (attr.name == 'attributes') return inherits = true;
- escaped[attr.name] = attr.escaped;
- if (attr.name == 'class') {
- classes.push('(' + attr.val + ')');
- } else {
- var pair = "'" + attr.name + "':(" + attr.val + ')';
- buf.push(pair);
- }
- });
- if (classes.length) {
- classes = classes.join(" + ' ' + ");
- buf.push("class: " + classes);
- }
- return {
- buf: buf.join(', ').replace('class:', '"class":'),
- escaped: JSON.stringify(escaped),
- inherits: inherits,
- constant: constant
- };
- }
- };
- /**
- * Check if expression can be evaluated to a constant
- *
- * @param {String} expression
- * @return {Boolean}
- * @api private
- */
- function isConstant(val){
- // Check strings/literals
- if (/^ *("([^"\\]*(\\.[^"\\]*)*)"|'([^'\\]*(\\.[^'\\]*)*)'|true|false|null|undefined) *$/i.test(val))
- return true;
- // Check numbers
- if (!isNaN(Number(val)))
- return true;
- // Check arrays
- var matches;
- if (matches = /^ *\[(.*)\] *$/.exec(val))
- return matches[1].split(',').every(isConstant);
- return false;
- }
- /**
- * Escape the given string of `html`.
- *
- * @param {String} html
- * @return {String}
- * @api private
- */
- function escape(html){
- return String(html)
- .replace(/&(?!\w+;)/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"');
- }
- }); // module: compiler.js
- require.register("doctypes.js", function(module, exports, require){
- /*!
- * Jade - doctypes
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- module.exports = {
- '5': '<!DOCTYPE html>'
- , 'default': '<!DOCTYPE html>'
- , 'xml': '<?xml version="1.0" encoding="utf-8" ?>'
- , 'transitional': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'
- , 'strict': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
- , 'frameset': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'
- , '1.1': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'
- , 'basic': '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">'
- , 'mobile': '<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">'
- };
- }); // module: doctypes.js
- require.register("filters.js", function(module, exports, require){
- /*!
- * Jade - filters
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- module.exports = {
-
- /**
- * Wrap text with CDATA block.
- */
-
- cdata: function(str){
- return '<![CDATA[\\n' + str + '\\n]]>';
- },
-
- /**
- * Transform sass to css, wrapped in style tags.
- */
-
- sass: function(str){
- str = str.replace(/\\n/g, '\n');
- var sass = require('sass').render(str).replace(/\n/g, '\\n');
- return '<style type="text/css">' + sass + '</style>';
- },
-
- /**
- * Transform stylus to css, wrapped in style tags.
- */
-
- stylus: function(str, options){
- var ret;
- str = str.replace(/\\n/g, '\n');
- var stylus = require('stylus');
- stylus(str, options).render(function(err, css){
- if (err) throw err;
- ret = css.replace(/\n/g, '\\n');
- });
- return '<style type="text/css">' + ret + '</style>';
- },
-
- /**
- * Transform less to css, wrapped in style tags.
- */
-
- less: function(str){
- var ret;
- str = str.replace(/\\n/g, '\n');
- require('less').render(str, function(err, css){
- if (err) throw err;
- ret = '<style type="text/css">' + css.replace(/\n/g, '\\n') + '</style>';
- });
- return ret;
- },
-
- /**
- * Transform markdown to html.
- */
-
- markdown: function(str){
- var md;
- // support markdown / discount
- try {
- md = require('markdown');
- } catch (err){
- try {
- md = require('discount');
- } catch (err) {
- try {
- md = require('markdown-js');
- } catch (err) {
- try {
- md = require('marked');
- } catch (err) {
- throw new
- Error('Cannot find markdown library, install markdown, discount, or marked.');
- }
- }
- }
- }
- str = str.replace(/\\n/g, '\n');
- return md.parse(str).replace(/\n/g, '\\n').replace(/'/g,''');
- },
-
- /**
- * Transform coffeescript to javascript.
- */
- coffeescript: function(str){
- var js = require('coffee-script').compile(str).replace(/\\/g, '\\\\').replace(/\n/g, '\\n');
- return '<script type="text/javascript">\\n' + js + '</script>';
- }
- };
- }); // module: filters.js
- require.register("inline-tags.js", function(module, exports, require){
- /*!
- * Jade - inline tags
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- module.exports = [
- 'a'
- , 'abbr'
- , 'acronym'
- , 'b'
- , 'br'
- , 'code'
- , 'em'
- , 'font'
- , 'i'
- , 'img'
- , 'ins'
- , 'kbd'
- , 'map'
- , 'samp'
- , 'small'
- , 'span'
- , 'strong'
- , 'sub'
- , 'sup'
- ];
- }); // module: inline-tags.js
- require.register("jade.js", function(module, exports, require){
- /*!
- * Jade
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Parser = require('./parser')
- , Lexer = require('./lexer')
- , Compiler = require('./compiler')
- , runtime = require('./runtime')
- /**
- * Library version.
- */
- exports.version = '0.27.6';
- /**
- * Expose self closing tags.
- */
- exports.selfClosing = require('./self-closing');
- /**
- * Default supported doctypes.
- */
- exports.doctypes = require('./doctypes');
- /**
- * Text filters.
- */
- exports.filters = require('./filters');
- /**
- * Utilities.
- */
- exports.utils = require('./utils');
- /**
- * Expose `Compiler`.
- */
- exports.Compiler = Compiler;
- /**
- * Expose `Parser`.
- */
- exports.Parser = Parser;
- /**
- * Expose `Lexer`.
- */
- exports.Lexer = Lexer;
- /**
- * Nodes.
- */
- exports.nodes = require('./nodes');
- /**
- * Jade runtime helpers.
- */
- exports.runtime = runtime;
- /**
- * Template function cache.
- */
- exports.cache = {};
- /**
- * Parse the given `str` of jade and return a function body.
- *
- * @param {String} str
- * @param {Object} options
- * @return {String}
- * @api private
- */
- function parse(str, options){
- try {
- // Parse
- var parser = new Parser(str, options.filename, options);
- // Compile
- var compiler = new (options.compiler || Compiler)(parser.parse(), options)
- , js = compiler.compile();
- // Debug compiler
- if (options.debug) {
- console.error('\nCompiled Function:\n\n\033[90m%s\033[0m', js.replace(/^/gm, ' '));
- }
- return ''
- + 'var buf = [];\n'
- + (options.self
- ? 'var self = locals || {};\n' + js
- : 'with (locals || {}) {\n' + js + '\n}\n')
- + 'return buf.join("");';
- } catch (err) {
- parser = parser.context();
- runtime.rethrow(err, parser.filename, parser.lexer.lineno);
- }
- }
- /**
- * Strip any UTF-8 BOM off of the start of `str`, if it exists.
- *
- * @param {String} str
- * @return {String}
- * @api private
- */
- function stripBOM(str){
- return 0xFEFF == str.charCodeAt(0)
- ? str.substring(1)
- : str;
- }
- /**
- * Compile a `Function` representation of the given jade `str`.
- *
- * Options:
- *
- * - `compileDebug` when `false` debugging code is stripped from the compiled template
- * - `client` when `true` the helper functions `escape()` etc will reference `jade.escape()`
- * for use with the Jade client-side runtime.js
- *
- * @param {String} str
- * @param {Options} options
- * @return {Function}
- * @api public
- */
- exports.compile = function(str, options){
- var options = options || {}
- , client = options.client
- , filename = options.filename
- ? JSON.stringify(options.filename)
- : 'undefined'
- , fn;
- str = stripBOM(String(str));
- if (options.compileDebug !== false) {
- fn = [
- 'var __jade = [{ lineno: 1, filename: ' + filename + ' }];'
- , 'try {'
- , parse(str, options)
- , '} catch (err) {'
- , ' rethrow(err, __jade[0].filename, __jade[0].lineno);'
- , '}'
- ].join('\n');
- } else {
- fn = parse(str, options);
- }
- if (client) {
- fn = 'attrs = attrs || jade.attrs; escape = escape || jade.escape; rethrow = rethrow || jade.rethrow; merge = merge || jade.merge;\n' + fn;
- }
- fn = new Function('locals, attrs, escape, rethrow, merge', fn);
- if (client) return fn;
- return function(locals){
- return fn(locals, runtime.attrs, runtime.escape, runtime.rethrow, runtime.merge);
- };
- };
- /**
- * Render the given `str` of jade and invoke
- * the callback `fn(err, str)`.
- *
- * Options:
- *
- * - `cache` enable template caching
- * - `filename` filename required for `include` / `extends` and caching
- *
- * @param {String} str
- * @param {Object|Function} options or fn
- * @param {Function} fn
- * @api public
- */
- exports.render = function(str, options, fn){
- // swap args
- if ('function' == typeof options) {
- fn = options, options = {};
- }
- // cache requires .filename
- if (options.cache && !options.filename) {
- return fn(new Error('the "filename" option is required for caching'));
- }
- try {
- var path = options.filename;
- var tmpl = options.cache
- ? exports.cache[path] || (exports.cache[path] = exports.compile(str, options))
- : exports.compile(str, options);
- fn(null, tmpl(options));
- } catch (err) {
- fn(err);
- }
- };
- /**
- * Render a Jade file at the given `path` and callback `fn(err, str)`.
- *
- * @param {String} path
- * @param {Object|Function} options or callback
- * @param {Function} fn
- * @api public
- */
- exports.renderFile = function(path, options, fn){
- var key = path + ':string';
- if ('function' == typeof options) {
- fn = options, options = {};
- }
- try {
- options.filename = path;
- var str = options.cache
- ? exports.cache[key] || (exports.cache[key] = fs.readFileSync(path, 'utf8'))
- : fs.readFileSync(path, 'utf8');
- exports.render(str, options, fn);
- } catch (err) {
- fn(err);
- }
- };
- /**
- * Express support.
- */
- exports.__express = exports.renderFile;
- }); // module: jade.js
- require.register("lexer.js", function(module, exports, require){
- /*!
- * Jade - Lexer
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- var utils = require('./utils');
- /**
- * Initialize `Lexer` with the given `str`.
- *
- * Options:
- *
- * - `colons` allow colons for attr delimiters
- *
- * @param {String} str
- * @param {Object} options
- * @api private
- */
- var Lexer = module.exports = function Lexer(str, options) {
- options = options || {};
- this.input = str.replace(/\r\n|\r/g, '\n');
- this.colons = options.colons;
- this.deferredTokens = [];
- this.lastIndents = 0;
- this.lineno = 1;
- this.stash = [];
- this.indentStack = [];
- this.indentRe = null;
- this.pipeless = false;
- };
- /**
- * Lexer prototype.
- */
- Lexer.prototype = {
-
- /**
- * Construct a token with the given `type` and `val`.
- *
- * @param {String} type
- * @param {String} val
- * @return {Object}
- * @api private
- */
-
- tok: function(type, val){
- return {
- type: type
- , line: this.lineno
- , val: val
- }
- },
-
- /**
- * Consume the given `len` of input.
- *
- * @param {Number} len
- * @api private
- */
-
- consume: function(len){
- this.input = this.input.substr(len);
- },
-
- /**
- * Scan for `type` with the given `regexp`.
- *
- * @param {String} type
- * @param {RegExp} regexp
- * @return {Object}
- * @api private
- */
-
- scan: function(regexp, type){
- var captures;
- if (captures = regexp.exec(this.input)) {
- this.consume(captures[0].length);
- return this.tok(type, captures[1]);
- }
- },
-
- /**
- * Defer the given `tok`.
- *
- * @param {Object} tok
- * @api private
- */
-
- defer: function(tok){
- this.deferredTokens.push(tok);
- },
-
- /**
- * Lookahead `n` tokens.
- *
- * @param {Number} n
- * @return {Object}
- * @api private
- */
-
- lookahead: function(n){
- var fetch = n - this.stash.length;
- while (fetch-- > 0) this.stash.push(this.next());
- return this.stash[--n];
- },
-
- /**
- * Return the indexOf `start` / `end` delimiters.
- *
- * @param {String} start
- * @param {String} end
- * @return {Number}
- * @api private
- */
-
- indexOfDelimiters: function(start, end){
- var str = this.input
- , nstart = 0
- , nend = 0
- , pos = 0;
- for (var i = 0, len = str.length; i < len; ++i) {
- if (start == str.charAt(i)) {
- ++nstart;
- } else if (end == str.charAt(i)) {
- if (++nend == nstart) {
- pos = i;
- break;
- }
- }
- }
- return pos;
- },
-
- /**
- * Stashed token.
- */
-
- stashed: function() {
- return this.stash.length
- && this.stash.shift();
- },
-
- /**
- * Deferred token.
- */
-
- deferred: function() {
- return this.deferredTokens.length
- && this.deferredTokens.shift();
- },
-
- /**
- * end-of-source.
- */
-
- eos: function() {
- if (this.input.length) return;
- if (this.indentStack.length) {
- this.indentStack.shift();
- return this.tok('outdent');
- } else {
- return this.tok('eos');
- }
- },
- /**
- * Blank line.
- */
-
- blank: function() {
- var captures;
- if (captures = /^\n *\n/.exec(this.input)) {
- this.consume(captures[0].length - 1);
- ++this.lineno;
- if (this.pipeless) return this.tok('text', '');
- return this.next();
- }
- },
- /**
- * Comment.
- */
-
- comment: function() {
- var captures;
- if (captures = /^ *\/\/(-)?([^\n]*)/.exec(this.input)) {
- this.consume(captures[0].length);
- var tok = this.tok('comment', captures[2]);
- tok.buffer = '-' != captures[1];
- return tok;
- }
- },
- /**
- * Interpolated tag.
- */
- interpolation: function() {
- var captures;
- if (captures = /^#\{(.*?)\}/.exec(this.input)) {
- this.consume(captures[0].length);
- return this.tok('interpolation', captures[1]);
- }
- },
- /**
- * Tag.
- */
-
- tag: function() {
- var captures;
- if (captures = /^(\w[-:\w]*)(\/?)/.exec(this.input)) {
- this.consume(captures[0].length);
- var tok, name = captures[1];
- if (':' == name[name.length - 1]) {
- name = name.slice(0, -1);
- tok = this.tok('tag', name);
- this.defer(this.tok(':'));
- while (' ' == this.input[0]) this.input = this.input.substr(1);
- } else {
- tok = this.tok('tag', name);
- }
- tok.selfClosing = !! captures[2];
- return tok;
- }
- },
-
- /**
- * Filter.
- */
-
- filter: function() {
- return this.scan(/^:(\w+)/, 'filter');
- },
-
- /**
- * Doctype.
- */
-
- doctype: function() {
- return this.scan(/^(?:!!!|doctype) *([^\n]+)?/, 'doctype');
- },
- /**
- * Id.
- */
-
- id: function() {
- return this.scan(/^#([\w-]+)/, 'id');
- },
-
- /**
- * Class.
- */
-
- className: function() {
- return this.scan(/^\.([\w-]+)/, 'class');
- },
-
- /**
- * Text.
- */
-
- text: function() {
- return this.scan(/^(?:\| ?| ?)?([^\n]+)/, 'text');
- },
- /**
- * Extends.
- */
-
- "extends": function() {
- return this.scan(/^extends? +([^\n]+)/, 'extends');
- },
- /**
- * Block prepend.
- */
-
- prepend: function() {
- var captures;
- if (captures = /^prepend +([^\n]+)/.exec(this.input)) {
- this.consume(captures[0].length);
- var mode = 'prepend'
- , name = captures[1]
- , tok = this.tok('block', name);
- tok.mode = mode;
- return tok;
- }
- },
-
- /**
- * Block append.
- */
-
- append: function() {
- var captures;
- if (captures = /^append +([^\n]+)/.exec(this.input)) {
- this.consume(captures[0].length);
- var mode = 'append'
- , name = captures[1]
- , tok = this.tok('block', name);
- tok.mode = mode;
- return tok;
- }
- },
- /**
- * Block.
- */
-
- block: function() {
- var captures;
- if (captures = /^block\b *(?:(prepend|append) +)?([^\n]*)/.exec(this.input)) {
- this.consume(captures[0].length);
- var mode = captures[1] || 'replace'
- , name = captures[2]
- , tok = this.tok('block', name);
- tok.mode = mode;
- return tok;
- }
- },
- /**
- * Yield.
- */
-
- yield: function() {
- return this.scan(/^yield */, 'yield');
- },
- /**
- * Include.
- */
-
- include: function() {
- return this.scan(/^include +([^\n]+)/, 'include');
- },
- /**
- * Case.
- */
-
- "case": function() {
- return this.scan(/^case +([^\n]+)/, 'case');
- },
- /**
- * When.
- */
-
- when: function() {
- return this.scan(/^when +([^:\n]+)/, 'when');
- },
- /**
- * Default.
- */
-
- "default": function() {
- return this.scan(/^default */, 'default');
- },
- /**
- * Assignment.
- */
-
- assignment: function() {
- var captures;
- if (captures = /^(\w+) += *([^;\n]+)( *;? *)/.exec(this.input)) {
- this.consume(captures[0].length);
- var name = captures[1]
- , val = captures[2];
- return this.tok('code', 'var ' + name + ' = (' + val + ');');
- }
- },
- /**
- * Call mixin.
- */
-
- call: function(){
- var captures;
- if (captures = /^\+([-\w]+)/.exec(this.input)) {
- this.consume(captures[0].length);
- var tok = this.tok('call', captures[1]);
-
- // Check for args (not attributes)
- if (captures = /^ *\((.*?)\)/.exec(this.input)) {
- if (!/^ *[-\w]+ *=/.test(captures[1])) {
- this.consume(captures[0].length);
- tok.args = captures[1];
- }
- }
-
- return tok;
- }
- },
- /**
- * Mixin.
- */
- mixin: function(){
- var captures;
- if (captures = /^mixin +([-\w]+)(?: *\((.*)\))?/.exec(this.input)) {
- this.consume(captures[0].length);
- var tok = this.tok('mixin', captures[1]);
- tok.args = captures[2];
- return tok;
- }
- },
- /**
- * Conditional.
- */
-
- conditional: function() {
- var captures;
- if (captures = /^(if|unless|else if|else)\b([^\n]*)/.exec(this.input)) {
- this.consume(captures[0].length);
- var type = captures[1]
- , js = captures[2];
- switch (type) {
- case 'if': js = 'if (' + js + ')'; break;
- case 'unless': js = 'if (!(' + js + '))'; break;
- case 'else if': js = 'else if (' + js + ')'; break;
- case 'else': js = 'else'; break;
- }
- return this.tok('code', js);
- }
- },
- /**
- * While.
- */
-
- "while": function() {
- var captures;
- if (captures = /^while +([^\n]+)/.exec(this.input)) {
- this.consume(captures[0].length);
- return this.tok('code', 'while (' + captures[1] + ')');
- }
- },
- /**
- * Each.
- */
-
- each: function() {
- var captures;
- if (captures = /^(?:- *)?(?:each|for) +(\w+)(?: *, *(\w+))? * in *([^\n]+)/.exec(this.input)) {
- this.consume(captures[0].length);
- var tok = this.tok('each', captures[1]);
- tok.key = captures[2] || '$index';
- tok.code = captures[3];
- return tok;
- }
- },
-
- /**
- * Code.
- */
-
- code: function() {
- var captures;
- if (captures = /^(!?=|-)([^\n]+)/.exec(this.input)) {
- this.consume(captures[0].length);
- var flags = captures[1];
- captures[1] = captures[2];
- var tok = this.tok('code', captures[1]);
- tok.escape = flags.charAt(0) === '=';
- tok.buffer = flags.charAt(0) === '=' || flags.charAt(1) === '=';
- return tok;
- }
- },
-
- /**
- * Attributes.
- */
-
- attrs: function() {
- if ('(' == this.input.charAt(0)) {
- var index = this.indexOfDelimiters('(', ')')
- , str = this.input.substr(1, index-1)
- , tok = this.tok('attrs')
- , len = str.length
- , colons = this.colons
- , states = ['key']
- , escapedAttr
- , key = ''
- , val = ''
- , quote
- , c
- , p;
- function state(){
- return states[states.length - 1];
- }
- function interpolate(attr) {
- return attr.replace(/(\\)?#\{([^}]+)\}/g, function(_, escape, expr){
- return escape
- ? _
- : quote + " + (" + expr + ") + " + quote;
- });
- }
- this.consume(index + 1);
- tok.attrs = {};
- tok.escaped = {};
- function parse(c) {
- var real = c;
- // TODO: remove when people fix ":"
- if (colons && ':' == c) c = '=';
- switch (c) {
- case ',':
- case '\n':
- switch (state()) {
- case 'expr':
- case 'array':
- case 'string':
- case 'object':
- val += c;
- break;
- default:
- states.push('key');
- val = val.trim();
- key = key.trim();
- if ('' == key) return;
- key = key.replace(/^['"]|['"]$/g, '').replace('!', '');
- tok.escaped[key] = escapedAttr;
- tok.attrs[key] = '' == val
- ? true
- : interpolate(val);
- key = val = '';
- }
- break;
- case '=':
- switch (state()) {
- case 'key char':
- key += real;
- break;
- case 'val':
- case 'expr':
- case 'array':
- case 'string':
- case 'object':
- val += real;
- break;
- default:
- escapedAttr = '!' != p;
- states.push('val');
- }
- break;
- case '(':
- if ('val' == state()
- || 'expr' == state()) states.push('expr');
- val += c;
- break;
- case ')':
- if ('expr' == state()
- || 'val' == state()) states.pop();
- val += c;
- break;
- case '{':
- if ('val' == state()) states.push('object');
- val += c;
- break;
- case '}':
- if ('object' == state()) states.pop();
- val += c;
- break;
- case '[':
- if ('val' == state()) states.push('array');
- val += c;
- break;
- case ']':
- if ('array' == state()) states.pop();
- val += c;
- break;
- case '"':
- case "'":
- switch (state()) {
- case 'key':
- states.push('key char');
- break;
- case 'key char':
- states.pop();
- break;
- case 'string':
- if (c == quote) states.pop();
- val += c;
- break;
- default:
- states.push('string');
- val += c;
- quote = c;
- }
- break;
- case '':
- break;
- default:
- switch (state()) {
- case 'key':
- case 'key char':
- key += c;
- break;
- default:
- val += c;
- }
- }
- p = c;
- }
- for (var i = 0; i < len; ++i) {
- parse(str.charAt(i));
- }
- parse(',');
- if ('/' == this.input.charAt(0)) {
- this.consume(1);
- tok.selfClosing = true;
- }
- return tok;
- }
- },
-
- /**
- * Indent | Outdent | Newline.
- */
-
- indent: function() {
- var captures, re;
- // established regexp
- if (this.indentRe) {
- captures = this.indentRe.exec(this.input);
- // determine regexp
- } else {
- // tabs
- re = /^\n(\t*) */;
- captures = re.exec(this.input);
- // spaces
- if (captures && !captures[1].length) {
- re = /^\n( *)/;
- captures = re.exec(this.input);
- }
- // established
- if (captures && captures[1].length) this.indentRe = re;
- }
- if (captures) {
- var tok
- , indents = captures[1].length;
- ++this.lineno;
- this.consume(indents + 1);
- if (' ' == this.input[0] || '\t' == this.input[0]) {
- throw new Error('Invalid indentation, you can use tabs or spaces but not both');
- }
- // blank line
- if ('\n' == this.input[0]) return this.tok('newline');
- // outdent
- if (this.indentStack.length && indents < this.indentStack[0]) {
- while (this.indentStack.length && this.indentStack[0] > indents) {
- this.stash.push(this.tok('outdent'));
- this.indentStack.shift();
- }
- tok = this.stash.pop();
- // indent
- } else if (indents && indents != this.indentStack[0]) {
- this.indentStack.unshift(indents);
- tok = this.tok('indent', indents);
- // newline
- } else {
- tok = this.tok('newline');
- }
- return tok;
- }
- },
- /**
- * Pipe-less text consumed only when
- * pipeless is true;
- */
- pipelessText: function() {
- if (this.pipeless) {
- if ('\n' == this.input[0]) return;
- var i = this.input.indexOf('\n');
- if (-1 == i) i = this.input.length;
- var str = this.input.substr(0, i);
- this.consume(str.length);
- return this.tok('text', str);
- }
- },
- /**
- * ':'
- */
- colon: function() {
- return this.scan(/^: */, ':');
- },
- /**
- * Return the next token object, or those
- * previously stashed by lookahead.
- *
- * @return {Object}
- * @api private
- */
-
- advance: function(){
- return this.stashed()
- || this.next();
- },
-
- /**
- * Return the next token object.
- *
- * @return {Object}
- * @api private
- */
-
- next: function() {
- return this.deferred()
- || this.blank()
- || this.eos()
- || this.pipelessText()
- || this.yield()
- || this.doctype()
- || this.interpolation()
- || this["case"]()
- || this.when()
- || this["default"]()
- || this["extends"]()
- || this.append()
- || this.prepend()
- || this.block()
- || this.include()
- || this.mixin()
- || this.call()
- || this.conditional()
- || this.each()
- || this["while"]()
- || this.assignment()
- || this.tag()
- || this.filter()
- || this.code()
- || this.id()
- || this.className()
- || this.attrs()
- || this.indent()
- || this.comment()
- || this.colon()
- || this.text();
- }
- };
- }); // module: lexer.js
- require.register("nodes/attrs.js", function(module, exports, require){
- /*!
- * Jade - nodes - Attrs
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node'),
- Block = require('./block');
- /**
- * Initialize a `Attrs` node.
- *
- * @api public
- */
- var Attrs = module.exports = function Attrs() {
- this.attrs = [];
- };
- /**
- * Inherit from `Node`.
- */
- Attrs.prototype = new Node;
- Attrs.prototype.constructor = Attrs;
- /**
- * Set attribute `name` to `val`, keep in mind these become
- * part of a raw js object literal, so to quote a value you must
- * '"quote me"', otherwise or example 'user.name' is literal JavaScript.
- *
- * @param {String} name
- * @param {String} val
- * @param {Boolean} escaped
- * @return {Tag} for chaining
- * @api public
- */
- Attrs.prototype.setAttribute = function(name, val, escaped){
- this.attrs.push({ name: name, val: val, escaped: escaped });
- return this;
- };
- /**
- * Remove attribute `name` when present.
- *
- * @param {String} name
- * @api public
- */
- Attrs.prototype.removeAttribute = function(name){
- for (var i = 0, len = this.attrs.length; i < len; ++i) {
- if (this.attrs[i] && this.attrs[i].name == name) {
- delete this.attrs[i];
- }
- }
- };
- /**
- * Get attribute value by `name`.
- *
- * @param {String} name
- * @return {String}
- * @api public
- */
- Attrs.prototype.getAttribute = function(name){
- for (var i = 0, len = this.attrs.length; i < len; ++i) {
- if (this.attrs[i] && this.attrs[i].name == name) {
- return this.attrs[i].val;
- }
- }
- };
- }); // module: nodes/attrs.js
- require.register("nodes/block-comment.js", function(module, exports, require){
- /*!
- * Jade - nodes - BlockComment
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a `BlockComment` with the given `block`.
- *
- * @param {String} val
- * @param {Block} block
- * @param {Boolean} buffer
- * @api public
- */
- var BlockComment = module.exports = function BlockComment(val, block, buffer) {
- this.block = block;
- this.val = val;
- this.buffer = buffer;
- };
- /**
- * Inherit from `Node`.
- */
- BlockComment.prototype = new Node;
- BlockComment.prototype.constructor = BlockComment;
- }); // module: nodes/block-comment.js
- require.register("nodes/block.js", function(module, exports, require){
- /*!
- * Jade - nodes - Block
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a new `Block` with an optional `node`.
- *
- * @param {Node} node
- * @api public
- */
- var Block = module.exports = function Block(node){
- this.nodes = [];
- if (node) this.push(node);
- };
- /**
- * Inherit from `Node`.
- */
- Block.prototype = new Node;
- Block.prototype.constructor = Block;
- /**
- * Block flag.
- */
- Block.prototype.isBlock = true;
- /**
- * Replace the nodes in `other` with the nodes
- * in `this` block.
- *
- * @param {Block} other
- * @api private
- */
- Block.prototype.replace = function(other){
- other.nodes = this.nodes;
- };
- /**
- * Pust the given `node`.
- *
- * @param {Node} node
- * @return {Number}
- * @api public
- */
- Block.prototype.push = function(node){
- return this.nodes.push(node);
- };
- /**
- * Check if this block is empty.
- *
- * @return {Boolean}
- * @api public
- */
- Block.prototype.isEmpty = function(){
- return 0 == this.nodes.length;
- };
- /**
- * Unshift the given `node`.
- *
- * @param {Node} node
- * @return {Number}
- * @api public
- */
- Block.prototype.unshift = function(node){
- return this.nodes.unshift(node);
- };
- /**
- * Return the "last" block, or the first `yield` node.
- *
- * @return {Block}
- * @api private
- */
- Block.prototype.includeBlock = function(){
- var ret = this
- , node;
- for (var i = 0, len = this.nodes.length; i < len; ++i) {
- node = this.nodes[i];
- if (node.yield) return node;
- else if (node.textOnly) continue;
- else if (node.includeBlock) ret = node.includeBlock();
- else if (node.block && !node.block.isEmpty()) ret = node.block.includeBlock();
- if (ret.yield) return ret;
- }
- return ret;
- };
- /**
- * Return a clone of this block.
- *
- * @return {Block}
- * @api private
- */
- Block.prototype.clone = function(){
- var clone = new Block;
- for (var i = 0, len = this.nodes.length; i < len; ++i) {
- clone.push(this.nodes[i].clone());
- }
- return clone;
- };
- }); // module: nodes/block.js
- require.register("nodes/case.js", function(module, exports, require){
- /*!
- * Jade - nodes - Case
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a new `Case` with `expr`.
- *
- * @param {String} expr
- * @api public
- */
- var Case = exports = module.exports = function Case(expr, block){
- this.expr = expr;
- this.block = block;
- };
- /**
- * Inherit from `Node`.
- */
- Case.prototype = new Node;
- Case.prototype.constructor = Case;
- var When = exports.When = function When(expr, block){
- this.expr = expr;
- this.block = block;
- this.debug = false;
- };
- /**
- * Inherit from `Node`.
- */
- When.prototype = new Node;
- When.prototype.constructor = When;
- }); // module: nodes/case.js
- require.register("nodes/code.js", function(module, exports, require){
- /*!
- * Jade - nodes - Code
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a `Code` node with the given code `val`.
- * Code may also be optionally buffered and escaped.
- *
- * @param {String} val
- * @param {Boolean} buffer
- * @param {Boolean} escape
- * @api public
- */
- var Code = module.exports = function Code(val, buffer, escape) {
- this.val = val;
- this.buffer = buffer;
- this.escape = escape;
- if (val.match(/^ *else/)) this.debug = false;
- };
- /**
- * Inherit from `Node`.
- */
- Code.prototype = new Node;
- Code.prototype.constructor = Code;
- }); // module: nodes/code.js
- require.register("nodes/comment.js", function(module, exports, require){
- /*!
- * Jade - nodes - Comment
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a `Comment` with the given `val`, optionally `buffer`,
- * otherwise the comment may render in the output.
- *
- * @param {String} val
- * @param {Boolean} buffer
- * @api public
- */
- var Comment = module.exports = function Comment(val, buffer) {
- this.val = val;
- this.buffer = buffer;
- };
- /**
- * Inherit from `Node`.
- */
- Comment.prototype = new Node;
- Comment.prototype.constructor = Comment;
- }); // module: nodes/comment.js
- require.register("nodes/doctype.js", function(module, exports, require){
- /*!
- * Jade - nodes - Doctype
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a `Doctype` with the given `val`.
- *
- * @param {String} val
- * @api public
- */
- var Doctype = module.exports = function Doctype(val) {
- this.val = val;
- };
- /**
- * Inherit from `Node`.
- */
- Doctype.prototype = new Node;
- Doctype.prototype.constructor = Doctype;
- }); // module: nodes/doctype.js
- require.register("nodes/each.js", function(module, exports, require){
- /*!
- * Jade - nodes - Each
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize an `Each` node, representing iteration
- *
- * @param {String} obj
- * @param {String} val
- * @param {String} key
- * @param {Block} block
- * @api public
- */
- var Each = module.exports = function Each(obj, val, key, block) {
- this.obj = obj;
- this.val = val;
- this.key = key;
- this.block = block;
- };
- /**
- * Inherit from `Node`.
- */
- Each.prototype = new Node;
- Each.prototype.constructor = Each;
- }); // module: nodes/each.js
- require.register("nodes/filter.js", function(module, exports, require){
- /*!
- * Jade - nodes - Filter
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node')
- , Block = require('./block');
- /**
- * Initialize a `Filter` node with the given
- * filter `name` and `block`.
- *
- * @param {String} name
- * @param {Block|Node} block
- * @api public
- */
- var Filter = module.exports = function Filter(name, block, attrs) {
- this.name = name;
- this.block = block;
- this.attrs = attrs;
- this.isASTFilter = !block.nodes.every(function(node){ return node.isText });
- };
- /**
- * Inherit from `Node`.
- */
- Filter.prototype = new Node;
- Filter.prototype.constructor = Filter;
- }); // module: nodes/filter.js
- require.register("nodes/index.js", function(module, exports, require){
- /*!
- * Jade - nodes
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- exports.Node = require('./node');
- exports.Tag = require('./tag');
- exports.Code = require('./code');
- exports.Each = require('./each');
- exports.Case = require('./case');
- exports.Text = require('./text');
- exports.Block = require('./block');
- exports.Mixin = require('./mixin');
- exports.Filter = require('./filter');
- exports.Comment = require('./comment');
- exports.Literal = require('./literal');
- exports.BlockComment = require('./block-comment');
- exports.Doctype = require('./doctype');
- }); // module: nodes/index.js
- require.register("nodes/literal.js", function(module, exports, require){
- /*!
- * Jade - nodes - Literal
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a `Literal` node with the given `str.
- *
- * @param {String} str
- * @api public
- */
- var Literal = module.exports = function Literal(str) {
- this.str = str
- .replace(/\\/g, "\\\\")
- .replace(/\n|\r\n/g, "\\n")
- .replace(/'/g, "\\'");
- };
- /**
- * Inherit from `Node`.
- */
- Literal.prototype = new Node;
- Literal.prototype.constructor = Literal;
- }); // module: nodes/literal.js
- require.register("nodes/mixin.js", function(module, exports, require){
- /*!
- * Jade - nodes - Mixin
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Attrs = require('./attrs');
- /**
- * Initialize a new `Mixin` with `name` and `block`.
- *
- * @param {String} name
- * @param {String} args
- * @param {Block} block
- * @api public
- */
- var Mixin = module.exports = function Mixin(name, args, block, call){
- this.name = name;
- this.args = args;
- this.block = block;
- this.attrs = [];
- this.call = call;
- };
- /**
- * Inherit from `Attrs`.
- */
- Mixin.prototype = new Attrs;
- Mixin.prototype.constructor = Mixin;
- }); // module: nodes/mixin.js
- require.register("nodes/node.js", function(module, exports, require){
- /*!
- * Jade - nodes - Node
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Initialize a `Node`.
- *
- * @api public
- */
- var Node = module.exports = function Node(){};
- /**
- * Clone this node (return itself)
- *
- * @return {Node}
- * @api private
- */
- Node.prototype.clone = function(){
- return this;
- };
- }); // module: nodes/node.js
- require.register("nodes/tag.js", function(module, exports, require){
- /*!
- * Jade - nodes - Tag
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Attrs = require('./attrs'),
- Block = require('./block'),
- inlineTags = require('../inline-tags');
- /**
- * Initialize a `Tag` node with the given tag `name` and optional `block`.
- *
- * @param {String} name
- * @param {Block} block
- * @api public
- */
- var Tag = module.exports = function Tag(name, block) {
- this.name = name;
- this.attrs = [];
- this.block = block || new Block;
- };
- /**
- * Inherit from `Attrs`.
- */
- Tag.prototype = new Attrs;
- Tag.prototype.constructor = Tag;
- /**
- * Clone this tag.
- *
- * @return {Tag}
- * @api private
- */
- Tag.prototype.clone = function(){
- var clone = new Tag(this.name, this.block.clone());
- clone.line = this.line;
- clone.attrs = this.attrs;
- clone.textOnly = this.textOnly;
- return clone;
- };
- /**
- * Check if this tag is an inline tag.
- *
- * @return {Boolean}
- * @api private
- */
- Tag.prototype.isInline = function(){
- return ~inlineTags.indexOf(this.name);
- };
- /**
- * Check if this tag's contents can be inlined. Used for pretty printing.
- *
- * @return {Boolean}
- * @api private
- */
- Tag.prototype.canInline = function(){
- var nodes = this.block.nodes;
- function isInline(node){
- // Recurse if the node is a block
- if (node.isBlock) return node.nodes.every(isInline);
- return node.isText || (node.isInline && node.isInline());
- }
-
- // Empty tag
- if (!nodes.length) return true;
-
- // Text-only or inline-only tag
- if (1 == nodes.length) return isInline(nodes[0]);
-
- // Multi-line inline-only tag
- if (this.block.nodes.every(isInline)) {
- for (var i = 1, len = nodes.length; i < len; ++i) {
- if (nodes[i-1].isText && nodes[i].isText)
- return false;
- }
- return true;
- }
-
- // Mixed tag
- return false;
- };
- }); // module: nodes/tag.js
- require.register("nodes/text.js", function(module, exports, require){
- /*!
- * Jade - nodes - Text
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Node = require('./node');
- /**
- * Initialize a `Text` node with optional `line`.
- *
- * @param {String} line
- * @api public
- */
- var Text = module.exports = function Text(line) {
- this.val = '';
- if ('string' == typeof line) this.val = line;
- };
- /**
- * Inherit from `Node`.
- */
- Text.prototype = new Node;
- Text.prototype.constructor = Text;
- /**
- * Flag as text.
- */
- Text.prototype.isText = true;
- }); // module: nodes/text.js
- require.register("parser.js", function(module, exports, require){
- /*!
- * Jade - Parser
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Module dependencies.
- */
- var Lexer = require('./lexer')
- , nodes = require('./nodes')
- , utils = require('./utils');
- /**
- * Initialize `Parser` with the given input `str` and `filename`.
- *
- * @param {String} str
- * @param {String} filename
- * @param {Object} options
- * @api public
- */
- var Parser = exports = module.exports = function Parser(str, filename, options){
- this.input = str;
- this.lexer = new Lexer(str, options);
- this.filename = filename;
- this.blocks = {};
- this.mixins = {};
- this.options = options;
- this.contexts = [this];
- };
- /**
- * Tags that may not contain tags.
- */
- var textOnly = exports.textOnly = ['script', 'style'];
- /**
- * Parser prototype.
- */
- Parser.prototype = {
- /**
- * Push `parser` onto the context stack,
- * or pop and return a `Parser`.
- */
- context: function(parser){
- if (parser) {
- this.contexts.push(parser);
- } else {
- return this.contexts.pop();
- }
- },
- /**
- * Return the next token object.
- *
- * @return {Object}
- * @api private
- */
- advance: function(){
- return this.lexer.advance();
- },
- /**
- * Skip `n` tokens.
- *
- * @param {Number} n
- * @api private
- */
- skip: function(n){
- while (n--) this.advance();
- },
-
- /**
- * Single token lookahead.
- *
- * @return {Object}
- * @api private
- */
-
- peek: function() {
- return this.lookahead(1);
- },
-
- /**
- * Return lexer lineno.
- *
- * @return {Number}
- * @api private
- */
-
- line: function() {
- return this.lexer.lineno;
- },
-
- /**
- * `n` token lookahead.
- *
- * @param {Number} n
- * @return {Object}
- * @api private
- */
-
- lookahead: function(n){
- return this.lexer.lookahead(n);
- },
-
- /**
- * Parse input returning a string of js for evaluation.
- *
- * @return {String}
- * @api public
- */
-
- parse: function(){
- var block = new nodes.Block, parser;
- block.line = this.line();
- while ('eos' != this.peek().type) {
- if ('newline' == this.peek().type) {
- this.advance();
- } else {
- block.push(this.parseExpr());
- }
- }
- if (parser = this.extending) {
- this.context(parser);
- var ast = parser.parse();
- this.context();
- // hoist mixins
- for (var name in this.mixins)
- ast.unshift(this.mixins[name]);
- return ast;
- }
- return block;
- },
-
- /**
- * Expect the given type, or throw an exception.
- *
- * @param {String} type
- * @api private
- */
-
- expect: function(type){
- if (this.peek().type === type) {
- return this.advance();
- } else {
- throw new Error('expected "' + type + '", but got "' + this.peek().type + '"');
- }
- },
-
- /**
- * Accept the given `type`.
- *
- * @param {String} type
- * @api private
- */
-
- accept: function(type){
- if (this.peek().type === type) {
- return this.advance();
- }
- },
-
- /**
- * tag
- * | doctype
- * | mixin
- * | include
- * | filter
- * | comment
- * | text
- * | each
- * | code
- * | yield
- * | id
- * | class
- * | interpolation
- */
-
- parseExpr: function(){
- switch (this.peek().type) {
- case 'tag':
- return this.parseTag();
- case 'mixin':
- return this.parseMixin();
- case 'block':
- return this.parseBlock();
- case 'case':
- return this.parseCase();
- case 'when':
- return this.parseWhen();
- case 'default':
- return this.parseDefault();
- case 'extends':
- return this.parseExtends();
- case 'include':
- return this.parseInclude();
- case 'doctype':
- return this.parseDoctype();
- case 'filter':
- return this.parseFilter();
- case 'comment':
- return this.parseComment();
- case 'text':
- return this.parseText();
- case 'each':
- return this.parseEach();
- case 'code':
- return this.parseCode();
- case 'call':
- return this.parseCall();
- case 'interpolation':
- return this.parseInterpolation();
- case 'yield':
- this.advance();
- var block = new nodes.Block;
- block.yield = true;
- return block;
- case 'id':
- case 'class':
- var tok = this.advance();
- this.lexer.defer(this.lexer.tok('tag', 'div'));
- this.lexer.defer(tok);
- return this.parseExpr();
- default:
- throw new Error('unexpected token "' + this.peek().type + '"');
- }
- },
-
- /**
- * Text
- */
-
- parseText: function(){
- var tok = this.expect('text')
- , node = new nodes.Text(tok.val);
- node.line = this.line();
- return node;
- },
- /**
- * ':' expr
- * | block
- */
- parseBlockExpansion: function(){
- if (':' == this.peek().type) {
- this.advance();
- return new nodes.Block(this.parseExpr());
- } else {
- return this.block();
- }
- },
- /**
- * case
- */
- parseCase: function(){
- var val = this.expect('case').val
- , node = new nodes.Case(val);
- node.line = this.line();
- node.block = this.block();
- return node;
- },
- /**
- * when
- */
- parseWhen: function(){
- var val = this.expect('when').val
- return new nodes.Case.When(val, this.parseBlockExpansion());
- },
-
- /**
- * default
- */
- parseDefault: function(){
- this.expect('default');
- return new nodes.Case.When('default', this.parseBlockExpansion());
- },
- /**
- * code
- */
-
- parseCode: function(){
- var tok = this.expect('code')
- , node = new nodes.Code(tok.val, tok.buffer, tok.escape)
- , block
- , i = 1;
- node.line = this.line();
- while (this.lookahead(i) && 'newline' == this.lookahead(i).type) ++i;
- block = 'indent' == this.lookahead(i).type;
- if (block) {
- this.skip(i-1);
- node.block = this.block();
- }
- return node;
- },
-
- /**
- * comment
- */
-
- parseComment: function(){
- var tok = this.expect('comment')
- , node;
- if ('indent' == this.peek().type) {
- node = new nodes.BlockComment(tok.val, this.block(), tok.buffer);
- } else {
- node = new nodes.Comment(tok.val, tok.buffer);
- }
- node.line = this.line();
- return node;
- },
-
- /**
- * doctype
- */
-
- parseDoctype: function(){
- var tok = this.expect('doctype')
- , node = new nodes.Doctype(tok.val);
- node.line = this.line();
- return node;
- },
-
- /**
- * filter attrs? text-block
- */
-
- parseFilter: function(){
- var block
- , tok = this.expect('filter')
- , attrs = this.accept('attrs');
- this.lexer.pipeless = true;
- block = this.parseTextBlock();
- this.lexer.pipeless = false;
- var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs);
- node.line = this.line();
- return node;
- },
-
- /**
- * tag ':' attrs? block
- */
-
- parseASTFilter: function(){
- var block
- , tok = this.expect('tag')
- , attrs = this.accept('attrs');
- this.expect(':');
- block = this.block();
- var node = new nodes.Filter(tok.val, block, attrs && attrs.attrs);
- node.line = this.line();
- return node;
- },
-
- /**
- * each block
- */
-
- parseEach: function(){
- var tok = this.expect('each')
- , node = new nodes.Each(tok.code, tok.val, tok.key);
- node.line = this.line();
- node.block = this.block();
- if (this.peek().type == 'code' && this.peek().val == 'else') {
- this.advance();
- node.alternative = this.block();
- }
- return node;
- },
- /**
- * 'extends' name
- */
- parseExtends: function(){
- var path = require('path')
- , fs = require('fs')
- , dirname = path.dirname
- , basename = path.basename
- , join = path.join;
- if (!this.filename)
- throw new Error('the "filename" option is required to extend templates');
- var path = this.expect('extends').val.trim()
- , dir = dirname(this.filename);
- var path = join(dir, path + '.jade')
- , str = fs.readFileSync(path, 'utf8')
- , parser = new Parser(str, path, this.options);
- parser.blocks = this.blocks;
- parser.contexts = this.contexts;
- this.extending = parser;
- // TODO: null node
- return new nodes.Literal('');
- },
- /**
- * 'block' name block
- */
- parseBlock: function(){
- var block = this.expect('block')
- , mode = block.mode
- , name = block.val.trim();
- block = 'indent' == this.peek().type
- ? this.block()
- : new nodes.Block(new nodes.Literal(''));
- var prev = this.blocks[name];
- if (prev) {
- switch (prev.mode) {
- case 'append':
- block.nodes = block.nodes.concat(prev.nodes);
- prev = block;
- break;
- case 'prepend':
- block.nodes = prev.nodes.concat(block.nodes);
- prev = block;
- break;
- }
- }
- block.mode = mode;
- return this.blocks[name] = prev || block;
- },
- /**
- * include block?
- */
- parseInclude: function(){
- var path = require('path')
- , fs = require('fs')
- , dirname = path.dirname
- , basename = path.basename
- , join = path.join;
- var path = this.expect('include').val.trim()
- , dir = dirname(this.filename);
- if (!this.filename)
- throw new Error('the "filename" option is required to use includes');
- // no extension
- if (!~basename(path).indexOf('.')) {
- path += '.jade';
- }
- // non-jade
- if ('.jade' != path.substr(-5)) {
- var path = join(dir, path)
- , str = fs.readFileSync(path, 'utf8');
- return new nodes.Literal(str);
- }
- var path = join(dir, path)
- , str = fs.readFileSync(path, 'utf8')
- , parser = new Parser(str, path, this.options);
- parser.blocks = utils.merge({}, this.blocks);
- parser.mixins = this.mixins;
- this.context(parser);
- var ast = parser.parse();
- this.context();
- ast.filename = path;
- if ('indent' == this.peek().type) {
- ast.includeBlock().push(this.block());
- }
- return ast;
- },
- /**
- * call ident block
- */
- parseCall: function(){
- var tok = this.expect('call')
- , name = tok.val
- , args = tok.args
- , mixin = new nodes.Mixin(name, args, new nodes.Block, true);
- this.tag(mixin);
- if (mixin.block.isEmpty()) mixin.block = null;
- return mixin;
- },
- /**
- * mixin block
- */
- parseMixin: function(){
- var tok = this.expect('mixin')
- , name = tok.val
- , args = tok.args
- , mixin;
- // definition
- if ('indent' == this.peek().type) {
- mixin = new nodes.Mixin(name, args, this.block(), false);
- this.mixins[name] = mixin;
- return mixin;
- // call
- } else {
- return new nodes.Mixin(name, args, null, true);
- }
- },
- /**
- * indent (text | newline)* outdent
- */
- parseTextBlock: function(){
- var block = new nodes.Block;
- block.line = this.line();
- var spaces = this.expect('indent').val;
- if (null == this._spaces) this._spaces = spaces;
- var indent = Array(spaces - this._spaces + 1).join(' ');
- while ('outdent' != this.peek().type) {
- switch (this.peek().type) {
- case 'newline':
- this.advance();
- break;
- case 'indent':
- this.parseTextBlock().nodes.forEach(function(node){
- block.push(node);
- });
- break;
- default:
- var text = new nodes.Text(indent + this.advance().val);
- text.line = this.line();
- block.push(text);
- }
- }
- if (spaces == this._spaces) this._spaces = null;
- this.expect('outdent');
- return block;
- },
- /**
- * indent expr* outdent
- */
-
- block: function(){
- var block = new nodes.Block;
- block.line = this.line();
- this.expect('indent');
- while ('outdent' != this.peek().type) {
- if ('newline' == this.peek().type) {
- this.advance();
- } else {
- block.push(this.parseExpr());
- }
- }
- this.expect('outdent');
- return block;
- },
- /**
- * interpolation (attrs | class | id)* (text | code | ':')? newline* block?
- */
-
- parseInterpolation: function(){
- var tok = this.advance();
- var tag = new nodes.Tag(tok.val);
- tag.buffer = true;
- return this.tag(tag);
- },
- /**
- * tag (attrs | class | id)* (text | code | ':')? newline* block?
- */
-
- parseTag: function(){
- // ast-filter look-ahead
- var i = 2;
- if ('attrs' == this.lookahead(i).type) ++i;
- if (':' == this.lookahead(i).type) {
- if ('indent' == this.lookahead(++i).type) {
- return this.parseASTFilter();
- }
- }
- var tok = this.advance()
- , tag = new nodes.Tag(tok.val);
- tag.selfClosing = tok.selfClosing;
- return this.tag(tag);
- },
- /**
- * Parse tag.
- */
- tag: function(tag){
- var dot;
- tag.line = this.line();
- // (attrs | class | id)*
- out:
- while (true) {
- switch (this.peek().type) {
- case 'id':
- case 'class':
- var tok = this.advance();
- tag.setAttribute(tok.type, "'" + tok.val + "'");
- continue;
- case 'attrs':
- var tok = this.advance()
- , obj = tok.attrs
- , escaped = tok.escaped
- , names = Object.keys(obj);
- if (tok.selfClosing) tag.selfClosing = true;
- for (var i = 0, len = names.length; i < len; ++i) {
- var name = names[i]
- , val = obj[name];
- tag.setAttribute(name, val, escaped[name]);
- }
- continue;
- default:
- break out;
- }
- }
- // check immediate '.'
- if ('.' == this.peek().val) {
- dot = tag.textOnly = true;
- this.advance();
- }
- // (text | code | ':')?
- switch (this.peek().type) {
- case 'text':
- tag.block.push(this.parseText());
- break;
- case 'code':
- tag.code = this.parseCode();
- break;
- case ':':
- this.advance();
- tag.block = new nodes.Block;
- tag.block.push(this.parseExpr());
- break;
- }
- // newline*
- while ('newline' == this.peek().type) this.advance();
- tag.textOnly = tag.textOnly || ~textOnly.indexOf(tag.name);
- // script special-case
- if ('script' == tag.name) {
- var type = tag.getAttribute('type');
- if (!dot && type && 'text/javascript' != type.replace(/^['"]|['"]$/g, '')) {
- tag.textOnly = false;
- }
- }
- // block?
- if ('indent' == this.peek().type) {
- if (tag.textOnly) {
- this.lexer.pipeless = true;
- tag.block = this.parseTextBlock();
- this.lexer.pipeless = false;
- } else {
- var block = this.block();
- if (tag.block) {
- for (var i = 0, len = block.nodes.length; i < len; ++i) {
- tag.block.push(block.nodes[i]);
- }
- } else {
- tag.block = block;
- }
- }
- }
-
- return tag;
- }
- };
- }); // module: parser.js
- require.register("runtime.js", function(module, exports, require){
- /*!
- * Jade - runtime
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Lame Array.isArray() polyfill for now.
- */
- if (!Array.isArray) {
- Array.isArray = function(arr){
- return '[object Array]' == Object.prototype.toString.call(arr);
- };
- }
- /**
- * Lame Object.keys() polyfill for now.
- */
- if (!Object.keys) {
- Object.keys = function(obj){
- var arr = [];
- for (var key in obj) {
- if (obj.hasOwnProperty(key)) {
- arr.push(key);
- }
- }
- return arr;
- }
- }
- /**
- * Merge two attribute objects giving precedence
- * to values in object `b`. Classes are special-cased
- * allowing for arrays and merging/joining appropriately
- * resulting in a string.
- *
- * @param {Object} a
- * @param {Object} b
- * @return {Object} a
- * @api private
- */
- exports.merge = function merge(a, b) {
- var ac = a['class'];
- var bc = b['class'];
- if (ac || bc) {
- ac = ac || [];
- bc = bc || [];
- if (!Array.isArray(ac)) ac = [ac];
- if (!Array.isArray(bc)) bc = [bc];
- ac = ac.filter(nulls);
- bc = bc.filter(nulls);
- a['class'] = ac.concat(bc).join(' ');
- }
- for (var key in b) {
- if (key != 'class') {
- a[key] = b[key];
- }
- }
- return a;
- };
- /**
- * Filter null `val`s.
- *
- * @param {Mixed} val
- * @return {Mixed}
- * @api private
- */
- function nulls(val) {
- return val != null;
- }
- /**
- * Render the given attributes object.
- *
- * @param {Object} obj
- * @param {Object} escaped
- * @return {String}
- * @api private
- */
- exports.attrs = function attrs(obj, escaped){
- var buf = []
- , terse = obj.terse;
- delete obj.terse;
- var keys = Object.keys(obj)
- , len = keys.length;
- if (len) {
- buf.push('');
- for (var i = 0; i < len; ++i) {
- var key = keys[i]
- , val = obj[key];
- if ('boolean' == typeof val || null == val) {
- if (val) {
- terse
- ? buf.push(key)
- : buf.push(key + '="' + key + '"');
- }
- } else if (0 == key.indexOf('data') && 'string' != typeof val) {
- buf.push(key + "='" + JSON.stringify(val) + "'");
- } else if ('class' == key && Array.isArray(val)) {
- buf.push(key + '="' + exports.escape(val.join(' ')) + '"');
- } else if (escaped && escaped[key]) {
- buf.push(key + '="' + exports.escape(val) + '"');
- } else {
- buf.push(key + '="' + val + '"');
- }
- }
- }
- return buf.join(' ');
- };
- /**
- * Escape the given string of `html`.
- *
- * @param {String} html
- * @return {String}
- * @api private
- */
- exports.escape = function escape(html){
- return String(html)
- .replace(/&(?!(\w+|\#\d+);)/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>')
- .replace(/"/g, '"');
- };
- /**
- * Re-throw the given `err` in context to the
- * the jade in `filename` at the given `lineno`.
- *
- * @param {Error} err
- * @param {String} filename
- * @param {String} lineno
- * @api private
- */
- exports.rethrow = function rethrow(err, filename, lineno){
- if (!filename) throw err;
- var context = 3
- , str = require('fs').readFileSync(filename, 'utf8')
- , lines = str.split('\n')
- , start = Math.max(lineno - context, 0)
- , end = Math.min(lines.length, lineno + context);
- // Error context
- var context = lines.slice(start, end).map(function(line, i){
- var curr = i + start + 1;
- return (curr == lineno ? ' > ' : ' ')
- + curr
- + '| '
- + line;
- }).join('\n');
- // Alter exception message
- err.path = filename;
- err.message = (filename || 'Jade') + ':' + lineno
- + '\n' + context + '\n\n' + err.message;
- throw err;
- };
- }); // module: runtime.js
- require.register("self-closing.js", function(module, exports, require){
- /*!
- * Jade - self closing tags
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- module.exports = [
- 'meta'
- , 'img'
- , 'link'
- , 'input'
- , 'source'
- , 'area'
- , 'base'
- , 'col'
- , 'br'
- , 'hr'
- ];
- }); // module: self-closing.js
- require.register("utils.js", function(module, exports, require){
- /*!
- * Jade - utils
- * Copyright(c) 2010 TJ Holowaychuk <tj@vision-media.ca>
- * MIT Licensed
- */
- /**
- * Convert interpolation in the given string to JavaScript.
- *
- * @param {String} str
- * @return {String}
- * @api private
- */
- var interpolate = exports.interpolate = function(str){
- return str.replace(/(_SLASH_)?([#!]){(.*?)}/g, function(str, escape, flag, code){
- code = code
- .replace(/\\'/g, "'")
- .replace(/_SLASH_/g, '\\');
- return escape
- ? str.slice(7)
- : "' + "
- + ('!' == flag ? '' : 'escape')
- + "((interp = " + code
- + ") == null ? '' : interp) + '";
- });
- };
- /**
- * Escape single quotes in `str`.
- *
- * @param {String} str
- * @return {String}
- * @api private
- */
- var escape = exports.escape = function(str) {
- return str.replace(/'/g, "\\'");
- };
- /**
- * Interpolate, and escape the given `str`.
- *
- * @param {String} str
- * @return {String}
- * @api private
- */
- exports.text = function(str){
- return interpolate(escape(str));
- };
- /**
- * Merge `b` into `a`.
- *
- * @param {Object} a
- * @param {Object} b
- * @return {Object}
- * @api public
- */
- exports.merge = function(a, b) {
- for (var key in b) a[key] = b[key];
- return a;
- };
- }); // module: utils.js
- window.jade = require("jade");
- })();
|