diff options
Diffstat (limited to 'node_modules/twig/docs')
15 files changed, 0 insertions, 15907 deletions
diff --git a/node_modules/twig/docs/docco.css b/node_modules/twig/docs/docco.css deleted file mode 100644 index b60f6fa..0000000 --- a/node_modules/twig/docs/docco.css +++ /dev/null @@ -1,518 +0,0 @@ -/*--------------------- Typography ----------------------------*/ - -@font-face { - font-family: 'aller-light'; - src: url('public/fonts/aller-light.eot'); - src: url('public/fonts/aller-light.eot?#iefix') format('embedded-opentype'), - url('public/fonts/aller-light.woff') format('woff'), - url('public/fonts/aller-light.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'aller-bold'; - src: url('public/fonts/aller-bold.eot'); - src: url('public/fonts/aller-bold.eot?#iefix') format('embedded-opentype'), - url('public/fonts/aller-bold.woff') format('woff'), - url('public/fonts/aller-bold.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -@font-face { - font-family: 'roboto-black'; - src: url('public/fonts/roboto-black.eot'); - src: url('public/fonts/roboto-black.eot?#iefix') format('embedded-opentype'), - url('public/fonts/roboto-black.woff') format('woff'), - url('public/fonts/roboto-black.ttf') format('truetype'); - font-weight: normal; - font-style: normal; -} - -/*--------------------- Layout ----------------------------*/ -html { height: 100%; } -body { - font-family: "aller-light"; - font-size: 14px; - line-height: 18px; - color: #30404f; - margin: 0; padding: 0; - height:100%; -} -#container { min-height: 100%; } - -a { - color: #000; -} - -b, strong { - font-weight: normal; - font-family: "aller-bold"; -} - -p { - margin: 15px 0 0px; -} - .annotation ul, .annotation ol { - margin: 25px 0; - } - .annotation ul li, .annotation ol li { - font-size: 14px; - line-height: 18px; - margin: 10px 0; - } - -h1, h2, h3, h4, h5, h6 { - color: #112233; - line-height: 1em; - font-weight: normal; - font-family: "roboto-black"; - text-transform: uppercase; - margin: 30px 0 15px 0; -} - -h1 { - margin-top: 40px; -} -h2 { - font-size: 1.26em; -} - -hr { - border: 0; - background: 1px #ddd; - height: 1px; - margin: 20px 0; -} - -pre, tt, code { - font-size: 12px; line-height: 16px; - font-family: Menlo, Monaco, Consolas, "Lucida Console", monospace; - margin: 0; padding: 0; -} - .annotation pre { - display: block; - margin: 0; - padding: 7px 10px; - background: #fcfcfc; - -moz-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); - -webkit-box-shadow: inset 0 0 10px rgba(0,0,0,0.1); - box-shadow: inset 0 0 10px rgba(0,0,0,0.1); - overflow-x: auto; - } - .annotation pre code { - border: 0; - padding: 0; - background: transparent; - } - - -blockquote { - border-left: 5px solid #ccc; - margin: 0; - padding: 1px 0 1px 1em; -} - .sections blockquote p { - font-family: Menlo, Consolas, Monaco, monospace; - font-size: 12px; line-height: 16px; - color: #999; - margin: 10px 0 0; - white-space: pre-wrap; - } - -ul.sections { - list-style: none; - padding:0 0 5px 0;; - margin:0; -} - -/* - Force border-box so that % widths fit the parent - container without overlap because of margin/padding. - - More Info : http://www.quirksmode.org/css/box.html -*/ -ul.sections > li > div { - -moz-box-sizing: border-box; /* firefox */ - -ms-box-sizing: border-box; /* ie */ - -webkit-box-sizing: border-box; /* webkit */ - -khtml-box-sizing: border-box; /* konqueror */ - box-sizing: border-box; /* css3 */ -} - - -/*---------------------- Jump Page -----------------------------*/ -#jump_to, #jump_page { - margin: 0; - background: white; - -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777; - -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px; - font: 16px Arial; - cursor: pointer; - text-align: right; - list-style: none; -} - -#jump_to a { - text-decoration: none; -} - -#jump_to a.large { - display: none; -} -#jump_to a.small { - font-size: 22px; - font-weight: bold; - color: #676767; -} - -#jump_to, #jump_wrapper { - position: fixed; - right: 0; top: 0; - padding: 10px 15px; - margin:0; -} - -#jump_wrapper { - display: none; - padding:0; -} - -#jump_to:hover #jump_wrapper { - display: block; -} - -#jump_page_wrapper{ - position: fixed; - right: 0; - top: 0; - bottom: 0; -} - -#jump_page { - padding: 5px 0 3px; - margin: 0 0 25px 25px; - max-height: 100%; - overflow: auto; -} - -#jump_page .source { - display: block; - padding: 15px; - text-decoration: none; - border-top: 1px solid #eee; -} - -#jump_page .source:hover { - background: #f5f5ff; -} - -#jump_page .source:first-child { -} - -/*---------------------- Low resolutions (> 320px) ---------------------*/ -@media only screen and (min-width: 320px) { - .pilwrap { display: none; } - - ul.sections > li > div { - display: block; - padding:5px 10px 0 10px; - } - - ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { - padding-left: 30px; - } - - ul.sections > li > div.content { - overflow-x:auto; - -webkit-box-shadow: inset 0 0 5px #e5e5ee; - box-shadow: inset 0 0 5px #e5e5ee; - border: 1px solid #dedede; - margin:5px 10px 5px 10px; - padding-bottom: 5px; - } - - ul.sections > li > div.annotation pre { - margin: 7px 0 7px; - padding-left: 15px; - } - - ul.sections > li > div.annotation p tt, .annotation code { - background: #f8f8ff; - border: 1px solid #dedede; - font-size: 12px; - padding: 0 0.2em; - } -} - -/*---------------------- (> 481px) ---------------------*/ -@media only screen and (min-width: 481px) { - #container { - position: relative; - } - body { - background-color: #F5F5FF; - font-size: 15px; - line-height: 21px; - } - pre, tt, code { - line-height: 18px; - } - p, ul, ol { - margin: 0 0 15px; - } - - - #jump_to { - padding: 5px 10px; - } - #jump_wrapper { - padding: 0; - } - #jump_to, #jump_page { - font: 10px Arial; - text-transform: uppercase; - } - #jump_page .source { - padding: 5px 10px; - } - #jump_to a.large { - display: inline-block; - } - #jump_to a.small { - display: none; - } - - - - #background { - position: absolute; - top: 0; bottom: 0; - width: 350px; - background: #fff; - border-right: 1px solid #e5e5ee; - z-index: -1; - } - - ul.sections > li > div.annotation ul, ul.sections > li > div.annotation ol { - padding-left: 40px; - } - - ul.sections > li { - white-space: nowrap; - } - - ul.sections > li > div { - display: inline-block; - } - - ul.sections > li > div.annotation { - max-width: 350px; - min-width: 350px; - min-height: 5px; - padding: 13px; - overflow-x: hidden; - white-space: normal; - vertical-align: top; - text-align: left; - } - ul.sections > li > div.annotation pre { - margin: 15px 0 15px; - padding-left: 15px; - } - - ul.sections > li > div.content { - padding: 13px; - vertical-align: top; - border: none; - -webkit-box-shadow: none; - box-shadow: none; - } - - .pilwrap { - position: relative; - display: inline; - } - - .pilcrow { - font: 12px Arial; - text-decoration: none; - color: #454545; - position: absolute; - top: 3px; left: -20px; - padding: 1px 2px; - opacity: 0; - -webkit-transition: opacity 0.2s linear; - } - .for-h1 .pilcrow { - top: 47px; - } - .for-h2 .pilcrow, .for-h3 .pilcrow, .for-h4 .pilcrow { - top: 35px; - } - - ul.sections > li > div.annotation:hover .pilcrow { - opacity: 1; - } -} - -/*---------------------- (> 1025px) ---------------------*/ -@media only screen and (min-width: 1025px) { - - body { - font-size: 16px; - line-height: 24px; - } - - #background { - width: 525px; - } - ul.sections > li > div.annotation { - max-width: 525px; - min-width: 525px; - padding: 10px 25px 1px 50px; - } - ul.sections > li > div.content { - padding: 9px 15px 16px 25px; - } -} - -/*---------------------- Syntax Highlighting -----------------------------*/ - -td.linenos { background-color: #f0f0f0; padding-right: 10px; } -span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; } -/* - -github.com style (c) Vasily Polovnyov <vast@whiteants.net> - -*/ - -pre code { - display: block; padding: 0.5em; - color: #000; - background: #f8f8ff -} - -pre .hljs-comment, -pre .hljs-template_comment, -pre .hljs-diff .hljs-header, -pre .hljs-javadoc { - color: #408080; - font-style: italic -} - -pre .hljs-keyword, -pre .hljs-assignment, -pre .hljs-literal, -pre .hljs-css .hljs-rule .hljs-keyword, -pre .hljs-winutils, -pre .hljs-javascript .hljs-title, -pre .hljs-lisp .hljs-title, -pre .hljs-subst { - color: #954121; - /*font-weight: bold*/ -} - -pre .hljs-number, -pre .hljs-hexcolor { - color: #40a070 -} - -pre .hljs-string, -pre .hljs-tag .hljs-value, -pre .hljs-phpdoc, -pre .hljs-tex .hljs-formula { - color: #219161; -} - -pre .hljs-title, -pre .hljs-id { - color: #19469D; -} -pre .hljs-params { - color: #00F; -} - -pre .hljs-javascript .hljs-title, -pre .hljs-lisp .hljs-title, -pre .hljs-subst { - font-weight: normal -} - -pre .hljs-class .hljs-title, -pre .hljs-haskell .hljs-label, -pre .hljs-tex .hljs-command { - color: #458; - font-weight: bold -} - -pre .hljs-tag, -pre .hljs-tag .hljs-title, -pre .hljs-rules .hljs-property, -pre .hljs-django .hljs-tag .hljs-keyword { - color: #000080; - font-weight: normal -} - -pre .hljs-attribute, -pre .hljs-variable, -pre .hljs-instancevar, -pre .hljs-lisp .hljs-body { - color: #008080 -} - -pre .hljs-regexp { - color: #B68 -} - -pre .hljs-class { - color: #458; - font-weight: bold -} - -pre .hljs-symbol, -pre .hljs-ruby .hljs-symbol .hljs-string, -pre .hljs-ruby .hljs-symbol .hljs-keyword, -pre .hljs-ruby .hljs-symbol .hljs-keymethods, -pre .hljs-lisp .hljs-keyword, -pre .hljs-tex .hljs-special, -pre .hljs-input_number { - color: #990073 -} - -pre .hljs-builtin, -pre .hljs-constructor, -pre .hljs-built_in, -pre .hljs-lisp .hljs-title { - color: #0086b3 -} - -pre .hljs-preprocessor, -pre .hljs-pi, -pre .hljs-doctype, -pre .hljs-shebang, -pre .hljs-cdata { - color: #999; - font-weight: bold -} - -pre .hljs-deletion { - background: #fdd -} - -pre .hljs-addition { - background: #dfd -} - -pre .hljs-diff .hljs-change { - background: #0086b3 -} - -pre .hljs-chunk { - color: #aaa -} - -pre .hljs-tex .hljs-formula { - opacity: 0.5; -} diff --git a/node_modules/twig/docs/licenses.md b/node_modules/twig/docs/licenses.md deleted file mode 100644 index 949a254..0000000 --- a/node_modules/twig/docs/licenses.md +++ /dev/null @@ -1,177 +0,0 @@ -## LICENSE for the sprintf and vsprintf functions is src/lib/twig.lib.js - - - Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com> - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of sprintf() for JavaScript nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -## LICENSE for the Date.format function is src/lib/twig.lib.js - - Copyright (c) 2010 Christopher West - - 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. - - -## LICENSE for the strip_tags function in src/twig.lib.js and range function -## in src/twig.functions.js - - This is version: 3.26 - php.js is copyright 2011 Kevin van Zonneveld. - - Portions copyright Brett Zamir (http://brett-zamir.me), Kevin van Zonneveld - (http://kevin.vanzonneveld.net), Onno Marsman, Theriault, Michael White - (http://getsprink.com), Waldo Malqui Silva, Paulo Freitas, Jack, Jonas - Raoni Soares Silva (http://www.jsfromhell.com), Philip Peterson, Legaev - Andrey, Ates Goral (http://magnetiq.com), Alex, Ratheous, Martijn Wieringa, - Rafał Kukawski (http://blog.kukawski.pl), lmeyrick - (https://sourceforge.net/projects/bcmath-js/), Nate, Philippe Baumann, - Enrique Gonzalez, Webtoolkit.info (http://www.webtoolkit.info/), Carlos R. - L. Rodrigues (http://www.jsfromhell.com), Ash Searle - (http://hexmen.com/blog/), Jani Hartikainen, travc, Ole Vrijenhoek, - Erkekjetter, Michael Grier, Rafał Kukawski (http://kukawski.pl), Johnny - Mast (http://www.phpvrouwen.nl), T.Wild, d3x, - http://stackoverflow.com/questions/57803/how-to-convert-decimal-to-hex-in-javascript, - Rafał Kukawski (http://blog.kukawski.pl/), stag019, pilus, WebDevHobo - (http://webdevhobo.blogspot.com/), marrtins, GeekFG - (http://geekfg.blogspot.com), Andrea Giammarchi - (http://webreflection.blogspot.com), Arpad Ray (mailto:arpad@php.net), - gorthaur, Paul Smith, Tim de Koning (http://www.kingsquare.nl), Joris, Oleg - Eremeev, Steve Hilder, majak, gettimeofday, KELAN, Josh Fraser - (http://onlineaspect.com/2007/06/08/auto-detect-a-time-zone-with-javascript/), - Marc Palau, Kevin van Zonneveld (http://kevin.vanzonneveld.net/), Martin - (http://www.erlenwiese.de/), Breaking Par Consulting Inc - (http://www.breakingpar.com/bkp/home.nsf/0/87256B280015193F87256CFB006C45F7), - Chris, Mirek Slugen, saulius, Alfonso Jimenez - (http://www.alfonsojimenez.com), Diplom@t (http://difane.com/), felix, - Mailfaker (http://www.weedem.fr/), Tyler Akins (http://rumkin.com), Caio - Ariede (http://caioariede.com), Robin, Kankrelune - (http://www.webfaktory.info/), Karol Kowalski, Imgen Tata - (http://www.myipdf.com/), mdsjack (http://www.mdsjack.bo.it), Dreamer, - Felix Geisendoerfer (http://www.debuggable.com/felix), Lars Fischer, AJ, - David, Aman Gupta, Michael White, Public Domain - (http://www.json.org/json2.js), Steven Levithan - (http://blog.stevenlevithan.com), Sakimori, Pellentesque Malesuada, - Thunder.m, Dj (http://phpjs.org/functions/htmlentities:425#comment_134018), - Steve Clay, David James, Francois, class_exists, nobbler, T. Wild, Itsacon - (http://www.itsacon.net/), date, Ole Vrijenhoek (http://www.nervous.nl/), - Fox, Raphael (Ao RUDLER), Marco, noname, Mateusz "loonquawl" Zalega, Frank - Forte, Arno, ger, mktime, john (http://www.jd-tech.net), Nick Kolosov - (http://sammy.ru), marc andreu, Scott Cariss, Douglas Crockford - (http://javascript.crockford.com), madipta, Slawomir Kaniecki, - ReverseSyntax, Nathan, Alex Wilson, kenneth, Bayron Guevara, Adam Wallner - (http://web2.bitbaro.hu/), paulo kuong, jmweb, Lincoln Ramsay, djmix, - Pyerre, Jon Hohle, Thiago Mata (http://thiagomata.blog.com), lmeyrick - (https://sourceforge.net/projects/bcmath-js/this.), Linuxworld, duncan, - Gilbert, Sanjoy Roy, Shingo, sankai, Oskar Larsson Högfeldt - (http://oskar-lh.name/), Denny Wardhana, 0m3r, Everlasto, Subhasis Deb, - josh, jd, Pier Paolo Ramon (http://www.mastersoup.com/), P, merabi, Soren - Hansen, Eugene Bulkin (http://doubleaw.com/), Der Simon - (http://innerdom.sourceforge.net/), echo is bad, Ozh, XoraX - (http://www.xorax.info), EdorFaus, JB, J A R, Marc Jansen, Francesco, LH, - Stoyan Kyosev (http://www.svest.org/), nord_ua, omid - (http://phpjs.org/functions/380:380#comment_137122), Brad Touesnard, MeEtc - (http://yass.meetcweb.com), Peter-Paul Koch - (http://www.quirksmode.org/js/beat.html), Olivier Louvignes - (http://mg-crea.com/), T0bsn, Tim Wiel, Bryan Elliott, Jalal Berrami, - Martin, JT, David Randall, Thomas Beaucourt (http://www.webapp.fr), taith, - vlado houba, Pierre-Luc Paour, Kristof Coomans (SCK-CEN Belgian Nucleair - Research Centre), Martin Pool, Kirk Strobeck, Rick Waldron, Brant Messenger - (http://www.brantmessenger.com/), Devan Penner-Woelk, Saulo Vallory, Wagner - B. Soares, Artur Tchernychev, Valentina De Rosa, Jason Wong - (http://carrot.org/), Christoph, Daniel Esteban, strftime, Mick@el, rezna, - Simon Willison (http://simonwillison.net), Anton Ongson, Gabriel Paderni, - Marco van Oort, penutbutterjelly, Philipp Lenssen, Bjorn Roesbeke - (http://www.bjornroesbeke.be/), Bug?, Eric Nagel, Tomasz Wesolowski, - Evertjan Garretsen, Bobby Drake, Blues (http://tech.bluesmoon.info/), Luke - Godfrey, Pul, uestla, Alan C, Ulrich, Rafal Kukawski, Yves Sucaet, - sowberry, Norman "zEh" Fuchs, hitwork, Zahlii, johnrembo, Nick Callen, - Steven Levithan (stevenlevithan.com), ejsanders, Scott Baker, Brian Tafoya - (http://www.premasolutions.com/), Philippe Jausions - (http://pear.php.net/user/jausions), Aidan Lister - (http://aidanlister.com/), Rob, e-mike, HKM, ChaosNo1, metjay, strcasecmp, - strcmp, Taras Bogach, jpfle, Alexander Ermolaev - (http://snippets.dzone.com/user/AlexanderErmolaev), DxGx, kilops, Orlando, - dptr1988, Le Torbi, James (http://www.james-bell.co.uk/), Pedro Tainha - (http://www.pedrotainha.com), James, Arnout Kazemier - (http://www.3rd-Eden.com), Chris McMacken, gabriel paderni, Yannoo, - FGFEmperor, baris ozdil, Tod Gentille, Greg Frazier, jakes, 3D-GRAF, Allan - Jensen (http://www.winternet.no), Howard Yeend, Benjamin Lupton, davook, - daniel airton wermann (http://wermann.com.br), Atli Þór, Maximusya, Ryan - W Tenney (http://ryan.10e.us), Alexander M Beedie, fearphage - (http://http/my.opera.com/fearphage/), Nathan Sepulveda, Victor, Matteo, - Billy, stensi, Cord, Manish, T.J. Leahy, Riddler - (http://www.frontierwebdev.com/), Rafał Kukawski, FremyCompany, Matt - Bradley, Tim de Koning, Luis Salazar (http://www.freaky-media.com/), Diogo - Resende, Rival, Andrej Pavlovic, Garagoth, Le Torbi - (http://www.letorbi.de/), Dino, Josep Sanz (http://www.ws3.es/), rem, - Russell Walker (http://www.nbill.co.uk/), Jamie Beck - (http://www.terabit.ca/), setcookie, Michael, YUI Library: - http://developer.yahoo.com/yui/docs/YAHOO.util.DateLocale.html, Blues at - http://hacks.bluesmoon.info/strftime/strftime.js, Ben - (http://benblume.co.uk/), DtTvB - (http://dt.in.th/2008-09-16.string-length-in-bytes.html), Andreas, William, - meo, incidence, Cagri Ekin, Amirouche, Amir Habibi - (http://www.residence-mixte.com/), Luke Smith (http://lucassmith.name), - Kheang Hok Chin (http://www.distantia.ca/), Jay Klehr, Lorenzo Pisani, - Tony, Yen-Wei Liu, Greenseed, mk.keck, Leslie Hoare, dude, booeyOH, Ben - Bryan - - Dual licensed under the MIT (MIT-LICENSE.txt) - and GPL (GPL-LICENSE.txt) licenses. - - 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 KEVIN VAN ZONNEVELD 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. diff --git a/node_modules/twig/docs/public/fonts/aller-bold.eot b/node_modules/twig/docs/public/fonts/aller-bold.eot Binary files differdeleted file mode 100644 index 1b32532..0000000 --- a/node_modules/twig/docs/public/fonts/aller-bold.eot +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/aller-bold.ttf b/node_modules/twig/docs/public/fonts/aller-bold.ttf Binary files differdeleted file mode 100644 index dc4cc9c..0000000 --- a/node_modules/twig/docs/public/fonts/aller-bold.ttf +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/aller-bold.woff b/node_modules/twig/docs/public/fonts/aller-bold.woff Binary files differdeleted file mode 100644 index fa16fd0..0000000 --- a/node_modules/twig/docs/public/fonts/aller-bold.woff +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/aller-light.eot b/node_modules/twig/docs/public/fonts/aller-light.eot Binary files differdeleted file mode 100644 index 40bd654..0000000 --- a/node_modules/twig/docs/public/fonts/aller-light.eot +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/aller-light.ttf b/node_modules/twig/docs/public/fonts/aller-light.ttf Binary files differdeleted file mode 100644 index c2c7290..0000000 --- a/node_modules/twig/docs/public/fonts/aller-light.ttf +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/aller-light.woff b/node_modules/twig/docs/public/fonts/aller-light.woff Binary files differdeleted file mode 100644 index 81a09d1..0000000 --- a/node_modules/twig/docs/public/fonts/aller-light.woff +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/novecento-bold.eot b/node_modules/twig/docs/public/fonts/novecento-bold.eot Binary files differdeleted file mode 100644 index 98a9a7f..0000000 --- a/node_modules/twig/docs/public/fonts/novecento-bold.eot +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/novecento-bold.ttf b/node_modules/twig/docs/public/fonts/novecento-bold.ttf Binary files differdeleted file mode 100644 index 2af39b0..0000000 --- a/node_modules/twig/docs/public/fonts/novecento-bold.ttf +++ /dev/null diff --git a/node_modules/twig/docs/public/fonts/novecento-bold.woff b/node_modules/twig/docs/public/fonts/novecento-bold.woff Binary files differdeleted file mode 100644 index de558b5..0000000 --- a/node_modules/twig/docs/public/fonts/novecento-bold.woff +++ /dev/null diff --git a/node_modules/twig/docs/public/stylesheets/normalize.css b/node_modules/twig/docs/public/stylesheets/normalize.css deleted file mode 100644 index 73abb76..0000000 --- a/node_modules/twig/docs/public/stylesheets/normalize.css +++ /dev/null @@ -1,375 +0,0 @@ -/*! normalize.css v2.0.1 | MIT License | git.io/normalize */ - -/* ========================================================================== - HTML5 display definitions - ========================================================================== */ - -/* - * Corrects `block` display not defined in IE 8/9. - */ - -article, -aside, -details, -figcaption, -figure, -footer, -header, -hgroup, -nav, -section, -summary { - display: block; -} - -/* - * Corrects `inline-block` display not defined in IE 8/9. - */ - -audio, -canvas, -video { - display: inline-block; -} - -/* - * Prevents modern browsers from displaying `audio` without controls. - * Remove excess height in iOS 5 devices. - */ - -audio:not([controls]) { - display: none; - height: 0; -} - -/* - * Addresses styling for `hidden` attribute not present in IE 8/9. - */ - -[hidden] { - display: none; -} - -/* ========================================================================== - Base - ========================================================================== */ - -/* - * 1. Sets default font family to sans-serif. - * 2. Prevents iOS text size adjust after orientation change, without disabling - * user zoom. - */ - -html { - font-family: sans-serif; /* 1 */ - -webkit-text-size-adjust: 100%; /* 2 */ - -ms-text-size-adjust: 100%; /* 2 */ -} - -/* - * Removes default margin. - */ - -body { - margin: 0; -} - -/* ========================================================================== - Links - ========================================================================== */ - -/* - * Addresses `outline` inconsistency between Chrome and other browsers. - */ - -a:focus { - outline: thin dotted; -} - -/* - * Improves readability when focused and also mouse hovered in all browsers. - */ - -a:active, -a:hover { - outline: 0; -} - -/* ========================================================================== - Typography - ========================================================================== */ - -/* - * Addresses `h1` font sizes within `section` and `article` in Firefox 4+, - * Safari 5, and Chrome. - */ - -h1 { - font-size: 2em; -} - -/* - * Addresses styling not present in IE 8/9, Safari 5, and Chrome. - */ - -abbr[title] { - border-bottom: 1px dotted; -} - -/* - * Addresses style set to `bolder` in Firefox 4+, Safari 5, and Chrome. - */ - -b, -strong { - font-weight: bold; -} - -/* - * Addresses styling not present in Safari 5 and Chrome. - */ - -dfn { - font-style: italic; -} - -/* - * Addresses styling not present in IE 8/9. - */ - -mark { - background: #ff0; - color: #000; -} - - -/* - * Corrects font family set oddly in Safari 5 and Chrome. - */ - -code, -kbd, -pre, -samp { - font-family: monospace, serif; - font-size: 1em; -} - -/* - * Improves readability of pre-formatted text in all browsers. - */ - -pre { - white-space: pre; - white-space: pre-wrap; - word-wrap: break-word; -} - -/* - * Sets consistent quote types. - */ - -q { - quotes: "\201C" "\201D" "\2018" "\2019"; -} - -/* - * Addresses inconsistent and variable font size in all browsers. - */ - -small { - font-size: 80%; -} - -/* - * Prevents `sub` and `sup` affecting `line-height` in all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sup { - top: -0.5em; -} - -sub { - bottom: -0.25em; -} - -/* ========================================================================== - Embedded content - ========================================================================== */ - -/* - * Removes border when inside `a` element in IE 8/9. - */ - -img { - border: 0; -} - -/* - * Corrects overflow displayed oddly in IE 9. - */ - -svg:not(:root) { - overflow: hidden; -} - -/* ========================================================================== - Figures - ========================================================================== */ - -/* - * Addresses margin not present in IE 8/9 and Safari 5. - */ - -figure { - margin: 0; -} - -/* ========================================================================== - Forms - ========================================================================== */ - -/* - * Define consistent border, margin, and padding. - */ - -fieldset { - border: 1px solid #c0c0c0; - margin: 0 2px; - padding: 0.35em 0.625em 0.75em; -} - -/* - * 1. Corrects color not being inherited in IE 8/9. - * 2. Remove padding so people aren't caught out if they zero out fieldsets. - */ - -legend { - border: 0; /* 1 */ - padding: 0; /* 2 */ -} - -/* - * 1. Corrects font family not being inherited in all browsers. - * 2. Corrects font size not being inherited in all browsers. - * 3. Addresses margins set differently in Firefox 4+, Safari 5, and Chrome - */ - -button, -input, -select, -textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 2 */ - margin: 0; /* 3 */ -} - -/* - * Addresses Firefox 4+ setting `line-height` on `input` using `!important` in - * the UA stylesheet. - */ - -button, -input { - line-height: normal; -} - -/* - * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` - * and `video` controls. - * 2. Corrects inability to style clickable `input` types in iOS. - * 3. Improves usability and consistency of cursor style between image-type - * `input` and others. - */ - -button, -html input[type="button"], /* 1 */ -input[type="reset"], -input[type="submit"] { - -webkit-appearance: button; /* 2 */ - cursor: pointer; /* 3 */ -} - -/* - * Re-set default cursor for disabled elements. - */ - -button[disabled], -input[disabled] { - cursor: default; -} - -/* - * 1. Addresses box sizing set to `content-box` in IE 8/9. - * 2. Removes excess padding in IE 8/9. - */ - -input[type="checkbox"], -input[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/* - * 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome. - * 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome - * (include `-moz` to future-proof). - */ - -input[type="search"] { - -webkit-appearance: textfield; /* 1 */ - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; /* 2 */ - box-sizing: content-box; -} - -/* - * Removes inner padding and search cancel button in Safari 5 and Chrome - * on OS X. - */ - -input[type="search"]::-webkit-search-cancel-button, -input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/* - * Removes inner padding and border in Firefox 4+. - */ - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0; -} - -/* - * 1. Removes default vertical scrollbar in IE 8/9. - * 2. Improves readability and alignment in all browsers. - */ - -textarea { - overflow: auto; /* 1 */ - vertical-align: top; /* 2 */ -} - -/* ========================================================================== - Tables - ========================================================================== */ - -/* - * Remove most spacing between table cells. - */ - -table { - border-collapse: collapse; - border-spacing: 0; -}
\ No newline at end of file diff --git a/node_modules/twig/docs/release checklist.md b/node_modules/twig/docs/release checklist.md deleted file mode 100644 index 1718c0d..0000000 --- a/node_modules/twig/docs/release checklist.md +++ /dev/null @@ -1,20 +0,0 @@ -Steps to release twig.js - -## repository - -1. Compile list of changes in CHANGELOG.md -2. Update version in package.json -3. Update version in bower.json -4. Update version in src/twig.header.js -5. `make`, `make docs`, `make test` and commit the changes. -6. `git tag` new version - -## bower - -Bower will pick up the new version in bower.json and use the associated git tag. - -## npm - -To publish the latest version to npmjs.org run this command from the twig.js directory: - - npm publish diff --git a/node_modules/twig/docs/tests.md b/node_modules/twig/docs/tests.md deleted file mode 100644 index 5afa1b7..0000000 --- a/node_modules/twig/docs/tests.md +++ /dev/null @@ -1,3567 +0,0 @@ -# TOC - - [Twig.js Blocks ->](#twigjs-blocks--) - - [block function ->](#twigjs-blocks---block-function--) - - [block shorthand ->](#twigjs-blocks---block-shorthand--) - - [Twig.js Control Structures ->](#twigjs-control-structures--) - - [if tag ->](#twigjs-control-structures---if-tag--) - - [for tag ->](#twigjs-control-structures---for-tag--) - - [set tag ->](#twigjs-control-structures---set-tag--) - - [Twig.js Core ->](#twigjs-core--) - - [Key Notation ->](#twigjs-core---key-notation--) - - [Context ->](#twigjs-core---context--) - - [Twig.js Embed ->](#twigjs-embed--) - - [Twig.js Expressions ->](#twigjs-expressions--) - - [Basic Operators ->](#twigjs-expressions---basic-operators--) - - [Comparison Operators ->](#twigjs-expressions---comparison-operators--) - - [Other Operators ->](#twigjs-expressions---other-operators--) - - [Twig.js Extensions ->](#twigjs-extensions--) - - [Twig.js Filters ->](#twigjs-filters--) - - [url_encode ->](#twigjs-filters---url_encode--) - - [json_encode ->](#twigjs-filters---json_encode--) - - [upper ->](#twigjs-filters---upper--) - - [lower ->](#twigjs-filters---lower--) - - [capitalize ->](#twigjs-filters---capitalize--) - - [title ->](#twigjs-filters---title--) - - [length ->](#twigjs-filters---length--) - - [sort ->](#twigjs-filters---sort--) - - [reverse ->](#twigjs-filters---reverse--) - - [keys ->](#twigjs-filters---keys--) - - [merge ->](#twigjs-filters---merge--) - - [join ->](#twigjs-filters---join--) - - [default ->](#twigjs-filters---default--) - - [date ->](#twigjs-filters---date--) - - [replace ->](#twigjs-filters---replace--) - - [format ->](#twigjs-filters---format--) - - [striptags ->](#twigjs-filters---striptags--) - - [escape ->](#twigjs-filters---escape--) - - [e ->](#twigjs-filters---e--) - - [nl2br ->](#twigjs-filters---nl2br--) - - [truncate ->](#twigjs-filters---truncate--) - - [trim ->](#twigjs-filters---trim--) - - [number_format ->](#twigjs-filters---number_format--) - - [slice ->](#twigjs-filters---slice--) - - [abs ->](#twigjs-filters---abs--) - - [first ->](#twigjs-filters---first--) - - [split ->](#twigjs-filters---split--) - - [batch ->](#twigjs-filters---batch--) - - [last ->](#twigjs-filters---last--) - - [raw ->](#twigjs-filters---raw--) - - [round ->](#twigjs-filters---round--) - - [Twig.js Loader ->](#twigjs-loader--) - - [source ->](#twigjs-loader---source--) - - [Twig.js Include ->](#twigjs-include--) - - [Twig.js Functions ->](#twigjs-functions--) - - [Built-in Functions ->](#twigjs-functions---built-in-functions--) - - [range ->](#twigjs-functions---built-in-functions---range--) - - [cycle ->](#twigjs-functions---built-in-functions---cycle--) - - [date ->](#twigjs-functions---built-in-functions---date--) - - [dump ->](#twigjs-functions---built-in-functions---dump--) - - [block ->](#twigjs-functions---built-in-functions---block--) - - [attribute ->](#twigjs-functions---built-in-functions---attribute--) - - [template_from_string ->](#twigjs-functions---built-in-functions---template_from_string--) - - [random ->](#twigjs-functions---built-in-functions---random--) - - [min, max ->](#twigjs-functions---built-in-functions---min-max--) - - [Twig.js Loaders ->](#twigjs-loaders--) - - [custom loader ->](#twigjs-loaders---custom-loader--) - - [Twig.js Macro ->](#twigjs-macro--) - - [Twig.js Namespaces ->](#twigjs-namespaces--) - - [Twig.js Optional Functionality ->](#twigjs-optional-functionality--) - - [Twig.js Parsers ->](#twigjs-parsers--) - - [custom parser ->](#twigjs-parsers---custom-parser--) - - [Twig.js Path ->](#twigjs-path--) - - [relativePath ->](#twigjs-path---relativepath--) - - [url ->](#twigjs-path---relativepath---url--) - - [path ->](#twigjs-path---relativepath---path--) - - [parsePath ->](#twigjs-path---parsepath--) - - [Twig.js Regression Tests ->](#twigjs-regression-tests--) - - [Twig.js Tags ->](#twigjs-tags--) - - [Twig.js Tests ->](#twigjs-tests--) - - [empty test ->](#twigjs-tests---empty-test--) - - [odd test ->](#twigjs-tests---odd-test--) - - [even test ->](#twigjs-tests---even-test--) - - [divisibleby test ->](#twigjs-tests---divisibleby-test--) - - [defined test ->](#twigjs-tests---defined-test--) - - [none test ->](#twigjs-tests---none-test--) - - [sameas test ->](#twigjs-tests---sameas-test--) - - [iterable test ->](#twigjs-tests---iterable-test--) -<a name=""></a> - -<a name="twigjs-blocks--"></a> -# Twig.js Blocks -> -should load a parent template and render the default values. - -```js -twig({ - id: 'remote-no-extends', - path: 'test/templates/template.twig', - async: false -}); -// Load the template -twig({ref: 'remote-no-extends'}).render({ }).should.equal( "Default Title - body" ); -``` - -should understand {% endblock title %} syntax. - -```js -twig({ - id: 'endblock-extended-syntax', - path: 'test/templates/blocks-extended-syntax.twig', - async: false -}); -// Load the template -twig({ref: 'endblock-extended-syntax'}).render({ }).should.equal( "This is the only thing." ); -``` - -should load a child template and replace the parent block's content. - -```js -// Test loading a template from a remote endpoint -twig({ - id: 'child-extends', - path: 'test/templates/child.twig', - load: function(template) { - template.render({ base: "template.twig" }).should.equal( "Other Title - child" ); - done(); - } -}); -``` - -should have access to a parent block content. - -```js -// Test loading a template from a remote endpoint -twig({ - id: 'child-parent', - path: 'test/templates/child-parent.twig', - load: function(template) { - template.render({ - base: "template.twig", - inner: ':value' - }).should.equal( "Other Title - body:value:child" ); - done(); - } -}); -``` - -should include blocks from another template for horizontal reuse. - -```js -// Test horizontal reuse -twig({ - id: 'use', - path: 'test/templates/use.twig', - load: function(template) { - // Load the template - template.render({ place: "diner" }).should.equal("Coming soon to a diner near you!" ); - done(); - } -}); -``` - -should allow overriding of included blocks. - -```js -// Test overriding of included blocks -twig({ - id: 'use-override-block', - path: 'test/templates/use-override-block.twig', - load: function(template) { - // Load the template - template.render({ place: "diner" }).should.equal("Sorry, can't come to a diner today." ); - done(); - } -}); -``` - -should allow overriding of included nested blocks. - -```js -// Test overriding of included blocks -twig({ - id: 'use-override-nested-block', - path: 'test/templates/use-override-nested-block.twig', - load: function(template) { - // Load the template - template.render().should.equal("parent:new-child1:new-child2"); - done(); - } -}); -``` - -should make the contents of blocks available after they're rendered. - -```js -// Test rendering and loading one block -twig({ - id: 'blocks', - path: 'test/templates/blocks.twig', - load: function(template) { - // Render the template with the blocks parameter - template.render({ place: "block" }, {output: 'blocks'}).msg.should.equal("Coming soon to a block near you!" ); - done(); - } -}); -``` - -should render nested blocks. - -```js -// Test rendering of blocks within blocks -twig({ - id: 'blocks-nested', - path: 'test/templates/blocks-nested.twig', - load: function(template) { - template.render({ }).should.equal( "parent:child" ) - done(); - } -}) -``` - -should render extended nested blocks. - -```js -// Test rendering of blocks within blocks -twig({ - id: 'child-blocks-nested', - path: 'test/templates/child-blocks-nested.twig', - load: function(template) { - template.render({ base: "template.twig" }).should.equal( "Default Title - parent:child" ); - done(); - } -}) -``` - -should be able to extend to a absolute template path. - -```js -// Test loading a template from a remote endpoint -twig({ - base: 'test/templates', - path: 'test/templates/a/child.twig', - load: function(template) { - template.render({ base: "b/template.twig" }).should.equal( "Other Title - child" ); - done(); - } -}); -``` - -should extends blocks inline. - -```js -twig({ - id: 'inline-parent-template', - data: 'Title: {% block title %}parent{% endblock %}' -}); -twig({ - allowInlineIncludes: true, - data: '{% extends "inline-parent-template" %}{% block title %}child{% endblock %}' -}).render().should.equal("Title: child"); -``` - -<a name="twigjs-blocks---block-function--"></a> -## block function -> -should render block content from an included block. - -```js -twig({ - path: 'test/templates/block-function.twig', - load: function(template) { - template.render({ - base: "block-function-parent.twig", - val: "abcd" - }) - .should.equal( "Child content = abcd / Result: Child content = abcd" ); - done(); - } -}) -``` - -should render block content from a parent block. - -```js -twig({ - path: 'test/templates/block-parent.twig', - load: function(template) { - template.render({ - base: "block-function-parent.twig" - }) - .should.equal( "parent block / Result: parent block" ); - done(); - } -}) -``` - -should render block content with outer context. - -```js -twig({ - path: 'test/templates/block-outer-context.twig', - load: function(template) { - template.render({ - base: "block-outer-context.twig", - items: ["twig", "js", "rocks"] - }) - .should.equal( "Hello twig!Hello js!Hello rocks!twigjsrocks" ); - done(); - } -}) -``` - -should respect changes of the context made before calling the function. - -```js -twig({ - data: '{% set foo = "original" %}{% block test %}{{ foo }}{% endblock %} {% set foo = "changed" %}{{ block("test") }}' -}).render() -.should.equal("original changed"); -``` - -<a name="twigjs-blocks---block-shorthand--"></a> -## block shorthand -> -should render block content using shorthand syntax. - -```js -twig({ - data: '{% set prefix = "shorthand" %}{% block title (prefix ~ " - " ~ block_value)|title %}' -}) -.render({block_value: 'test succeeded'}) -.should.equal('Shorthand - Test Succeeded'); -``` - -should overload blocks from an extended template using shorthand syntax. - -```js -twig({ - allowInlineIncludes: true, - data: '{% extends "child-extends" %}{% block title "New Title" %}{% block body "new body uses the " ~ base ~ " template" %}' -}) -.render({ base: "template.twig" }) -.should.equal( "New Title - new body uses the template.twig template" ); -``` - -<a name="twigjs-control-structures--"></a> -# Twig.js Control Structures -> -<a name="twigjs-control-structures---if-tag--"></a> -## if tag -> -should parse the contents of the if block if the expression is true. - -```js -var test_template = twig({data: '{% if test %}true{% endif%}'}); -test_template.render({test: true}).should.equal("true" ); -test_template.render({test: false}).should.equal("" ); -``` - -should call the if or else blocks based on the expression result. - -```js -var test_template = twig({data: '{% if test %}true{% endif%}'}); -test_template.render({test: true}).should.equal("true" ); -test_template.render({test: false}).should.equal("" ); -``` - -should support elseif. - -```js -var test_template = twig({data: '{% if test %}1{% elseif other %}2{%else%}3{% endif%}'}); -test_template.render({test: true, other:false}).should.equal("1" ); -test_template.render({test: true, other:true}).should.equal("1" ); -test_template.render({test: false, other:true}).should.equal("2" ); -test_template.render({test: false, other:false}).should.equal("3" ); -``` - -should be able to nest. - -```js -var test_template = twig({data: '{% if test %}{% if test2 %}true{% else %}false{% endif%}{% else %}not{% endif%}'}); -test_template.render({test: true, test2: true}).should.equal("true" ); -test_template.render({test: true, test2: false}).should.equal("false" ); -test_template.render({test: false, test2: true}).should.equal("not" ); -test_template.render({test: false, test2: false}).should.equal("not" ); -``` - -should support newlines in if statement. - -```js -var test_template = twig({data: '{% if test or\r\nother %}true{% endif%}'}); -test_template.render({test: true, other: false}).should.equal("true" ); -test_template.render({test: false, other: false}).should.equal("" ); -``` - -<a name="twigjs-control-structures---for-tag--"></a> -## for tag -> -should provide value only for array input. - -```js -var test_template = twig({data: '{% for value in test %}{{ value }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("1234" ); -test_template.render({test: []}).should.equal("" ); -``` - -should provide both key and value for array input. - -```js -var test_template = twig({data: '{% for key,value in test %}{{key}}:{{ value }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("0:11:22:33:4" ); -test_template.render({test: []}).should.equal("" ); -``` - -should provide value only for object input. - -```js -var test_template = twig({data: '{% for value in test %}{{ value }}{% endfor %}'}); -test_template.render({test: {one: 1, two: 2, three: 3}}).should.equal("123" ); -test_template.render({test: {}}).should.equal("" ); -``` - -should provide both key and value for object input. - -```js -var test_template = twig({data: '{% for key, value in test %}{{key}}:{{ value }}{% endfor %}'}); -test_template.render({test: {one: 1, two: 2, three: 3}}).should.equal("one:1two:2three:3" ); -test_template.render({test: {}}).should.equal("" ); -``` - -should support else if the input is empty. - -```js -var test_template = twig({data: '{% for key,value in test %}{{ value }}{% else %}else{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("1234" ); -test_template.render({test: []}).should.equal("else" ); -``` - -should be able to nest. - -```js -var test_template = twig({data: '{% for key,list in test %}{% for val in list %}{{ val }}{%endfor %}.{% else %}else{% endfor %}'}); -test_template.render({test: [[1,2],[3,4],[5,6]]}).should.equal("12.34.56." ); -test_template.render({test: []}).should.equal("else" ); -``` - -should have a loop context item available for arrays. - -```js -var test_template = twig({data: '{% for key,value in test %}{{ loop.index }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("1234" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.index0 }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("0123" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.revindex }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("4321" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.revindex0 }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("3210" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.length }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("4444" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.first }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("truefalsefalsefalse" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.last }}{% endfor %}'}); -test_template.render({test: [1,2,3,4]}).should.equal("falsefalsefalsetrue" ); -``` - -should have a loop context item available for objects. - -```js -var test_template = twig({data: '{% for key,value in test %}{{ loop.index }}{% endfor %}'}); -test_template.render({test: {a:1,b:2,c:3,d:4}}).should.equal("1234" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.index0 }}{% endfor %}'}); -test_template.render({test: {a:1,b:2,c:3,d:4}}).should.equal("0123" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.revindex }}{% endfor %}'}); -test_template.render({test: {a:1,b:2,c:3,d:4}}).should.equal("4321" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.revindex0 }}{% endfor %}'}); -test_template.render({test: {a:1,b:2,c:3,d:4}}).should.equal("3210" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.length }}{% endfor %}'}); -test_template.render({test: {a:1,b:2,c:3,d:4}}).should.equal("4444" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.first }}{% endfor %}'}); -test_template.render({test: {a:1,b:2,c:3,d:4}}).should.equal("truefalsefalsefalse" ); -test_template = twig({data: '{% for key,value in test %}{{ loop.last }}{% endfor %}'}); -test_template.render({test: {a:1,b:2,c:3,d:4}}).should.equal("falsefalsefalsetrue" ); -``` - -should have a loop context item available in child loops objects. - -```js -var test_template = twig({data: '{% for value in test %}{% for value in inner %}({{ loop.parent.loop.index }},{{ loop.index }}){% endfor %}{% endfor %}'}); -test_template.render({test: {a:1,b:2}, inner:[1,2,3]}).should.equal("(1,1)(1,2)(1,3)(2,1)(2,2)(2,3)"); -``` - -should support conditionals on for loops. - -```js -var test_template = twig({data: '{% for value in test if false %}{{ value }},{% endfor %}'}); -test_template.render({test: ["one", "two", "a", "b", "other"]}).should.equal(""); -test_template = twig({data: '{% for value in test if true %}{{ value }}{% endfor %}'}); -test_template.render({test: ["a", "s", "d", "f"]}).should.equal("asdf"); -test_template = twig({data: '{% for value in test if value|length > 2 %}{{ value }},{% endfor %}'}); -test_template.render({test: ["one", "two", "a", "b", "other"]}).should.equal("one,two,other,"); -test_template = twig({data: '{% for key,item in test if item.show %}{{key}}:{{ item.value }},{% endfor %}'}); -test_template.render({test: { - a: {show:true, value: "one"}, - b: {show:false, value: "two"}, - c: {show:true, value: "three"}}}).should.equal("a:one,c:three,"); -``` - -<a name="twigjs-control-structures---set-tag--"></a> -## set tag -> -should not set the global context from within a for loop. - -```js -var test_template = twig({data: '{% for value in [1] %}{% set foo="right" %}{% endfor %}{{ foo }}'}); -test_template.render().should.equal(""); -``` - -should set the global context from within a for loop when the variable is initialized outside of the loop. - -```js -var test_template = twig({data: '{% set foo="wrong" %}{% for value in [1] %}{% set foo="right" %}{% endfor %}{{ foo }}'}); -test_template.render().should.equal("right"); -``` - -should set the global context from within a nested for loop when the variable is initialized outside of the loop. - -```js -var test_template = twig({data: '{% set k = 0 %}{% for i in 0..2 %}{% for j in 0..2 %}{{ k }}{% set k = k + 1 %}{% endfor %}{% endfor %}'}); -test_template.render().should.equal("012345678"); -``` - -<a name="twigjs-core--"></a> -# Twig.js Core -> -should save and load a template by reference. - -```js -// Define and save a template - twig({ - id: 'test', - data: '{{ "test" }}' - }); - // Load and render the template - twig({ref: 'test'}).render() - .should.equal("test"); -``` - -should ignore comments. - -```js -twig({data: 'good {# comment #}morning'}).render().should.equal("good morning"); -twig({data: 'good{#comment#}morning'}).render().should.equal("goodmorning"); -``` - -should ignore output tags within comments. - -```js -twig({data: 'good {# {{ "Hello" }} #}morning'}).render().should.equal("good morning"); -twig({data: 'good{#c}}om{{m{{ent#}morning'}).render().should.equal("goodmorning"); -``` - -should ignore logic tags within comments. - -```js -twig({data: 'test {# {% bad syntax if not in comment %} #}test'}).render().should.equal("test test"); -twig({data: '{##}{##}test{# %}}}%}%{%{{% #}pass'}).render().should.equal("testpass"); -``` - -should ignore quotation marks within comments. - -```js -twig({data: "good {# don't stop #}morning"}).render().should.equal("good morning"); -twig({data: 'good{#"dont stop"#}morning'}).render().should.equal("goodmorning"); -twig({data: 'good {# "don\'t stop" #}morning'}).render().should.equal("good morning"); -twig({data: 'good{#"\'#}morning'}).render().should.equal("goodmorning"); -twig({data: 'good {#"\'"\'"\'#} day'}).render().should.equal("good day"); -twig({data: "a {# ' #}b{# ' #} c"}).render().should.equal("a b c"); -``` - -should be able to parse output tags with tag ends in strings. - -```js -// Really all we care about here is not throwing exceptions. -twig({data: '{{ "test" }}'}).render().should.equal("test"); -twig({data: '{{ " }} " }}'}).render().should.equal(" }} "); -twig({data: '{{ " \\"}} " }}'}).render().should.equal(' "}} '); -twig({data: "{{ ' }} ' }}"}).render().should.equal(" }} "); -twig({data: "{{ ' \\'}} ' }}"}).render().should.equal(" '}} "); -twig({data: '{{ " \'}} " }}'}).render().should.equal(" '}} "); -twig({data: "{{ ' \"}} ' }}"}).render().should.equal(' "}} '); -``` - -should be able to parse whitespace control output tags. - -```js -twig({data: ' {{- "test" -}}'}).render().should.equal("test"); -twig({data: ' {{- "test" -}} '}).render().should.equal("test"); -twig({data: '\n{{- "test" -}}'}).render().should.equal("test"); -twig({data: '{{- "test" -}}\n'}).render().should.equal("test"); -twig({data: '\n{{- "test" -}}\n'}).render().should.equal("test"); -twig({data: '\t{{- "test" -}}\t'}).render().should.equal("test"); -twig({data: '\n\t{{- "test" -}}\n\t'}).render().should.equal("test"); -twig({data: '123\n\t{{- "test" -}}\n\t456'}).render().should.equal("123test456"); -twig({data: '\n{{- orp -}}\n'}).render({ orp: "test"}).should.equal("test"); -twig({data: '\n{{- [1,2 ,1+2 ] -}}\n'}).render().should.equal("1,2,3"); -twig({data: ' {{- "test" -}} {{- "test" -}}'}).render().should.equal("testtest"); -twig({data: '{{ "test" }} {{- "test" -}}'}).render().should.equal("testtest"); -twig({data: '{{- "test" -}} {{ "test" }}'}).render().should.equal("testtest"); -twig({data: '<>{{- "test" -}}<>'}).render().should.equal("<>test<>"); -``` - -should be able to parse mismatched opening whitespace control output tags. - -```js -twig({data: ' {{- "test" }}'}).render().should.equal("test"); -twig({data: '{{- "test" }}\n'}).render().should.equal("test\n"); -twig({data: '\t{{- "test" }}\t'}).render().should.equal("test\t"); -twig({data: '123\n\t{{- "test" }}\n\t456'}).render().should.equal("123test\n\t456"); -twig({data: '\n{{- [1,2 ,1+2 ] }}\n'}).render().should.equal("1,2,3\n"); -twig({data: ' {{- "test" }} {{- "test" }}'}).render().should.equal("testtest"); -twig({data: '{{ "test" }} {{- "test" }}'}).render().should.equal("testtest"); -twig({data: ' {{- "test" }} {{ "test" }}'}).render().should.equal("test test"); -twig({data: ' {{- "test" }} {{- "test" -}}'}).render().should.equal("testtest"); -twig({data: '<>{{- "test" }}'}).render().should.equal("<>test"); -``` - -should be able to parse mismatched closing whitespace control output tags. - -```js -twig({data: ' {{ "test" -}}'}).render().should.equal(" test"); -twig({data: '\n{{ "test" -}}\n'}).render().should.equal("\ntest"); -twig({data: '\t{{ "test" -}}\t'}).render().should.equal("\ttest"); -twig({data: '123\n\t{{ "test" -}}\n\t456'}).render().should.equal("123\n\ttest456"); -twig({data: '\n{{ [1,2 ,1+2 ] -}}\n'}).render().should.equal("\n1,2,3"); -twig({data: ' {{ "test" -}} {{ "test" -}}'}).render().should.equal(" testtest"); -twig({data: '{{ "test" }} {{ "test" -}} '}).render().should.equal("test test"); -twig({data: ' {{ "test" -}} {{ "test" }} '}).render().should.equal(" testtest "); -twig({data: ' {{ "test" -}} {{- "test" -}}'}).render().should.equal(" testtest"); -twig({data: '{{ "test" -}}<>'}).render().should.equal("test<>"); -``` - -should be able to parse whitespace control logic tags. - -```js -// Newlines directly after logic tokens are ignored -// So use double newlines -twig({data: '{%- if true -%}{{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: '{%- if true -%}{{ "test" }}{%- endif -%}'}).render().should.equal("test"); -twig({data: ' {%- if true -%} {{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: '\n{%- if true -%}\n\n{{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: '\n\t{%- if true -%}\n\n\t{{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: '123\n\t{%- if true -%}\n\n\t{{ "test" }}{% endif %}456'}).render().should.equal("123test456"); -twig({data: '\n\t{%- if true -%}\n\n\t{{ [1,2 ,1+2 ] }}{% endif %}'}).render().should.equal("1,2,3"); -twig({data: '<>{%- if true -%}test{% endif %}<>'}).render().should.equal("<>test<>"); -``` - -should be able to parse mismatched opening whitespace control logic tags. - -```js -twig({data: '{%- if true %}{{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: '{%- if true %}{{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: ' {% if true %} {{ "test" }}{% endif %}'}).render().should.equal(" test"); -twig({data: ' {%- if true %} {{ "test" }}{% endif %}'}).render().should.equal(" test"); -twig({data: '\n{% if true %}\n\n{{ "test" }}{% endif %}'}).render().should.equal("\n\ntest"); -twig({data: '\n{%- if true %}\n\n{{ "test" }}{% endif %}'}).render().should.equal("\ntest"); -twig({data: '\n\t{%- if true %}\n\n\t{{ "test" }}{% endif %}'}).render().should.equal("\n\ttest"); -twig({data: '123\n\t{%- if true %}\n\n\t{{ "test" }}{% endif %}456'}).render().should.equal("123\n\ttest456"); -twig({data: '\n\t{%- if true %}\n\n\t{{ [1,2 ,1+2 ] }}{% endif %}'}).render().should.equal("\n\t1,2,3"); -twig({data: '<>{%- if true %}test{% endif %}'}).render().should.equal("<>test"); -``` - -should be able to parse mismatched closing whitespace control logic tags. - -```js -twig({data: '{% if true %}{{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: '{% if true -%} {{ "test" }}{% endif %}'}).render().should.equal("test"); -twig({data: ' {% if true -%} {{ "test" }}{% endif %}'}).render().should.equal(" test"); -twig({data: ' {% if true -%} {{ "test" }}{% endif %}'}).render().should.equal(" test"); -twig({data: '\n{% if true %}\n\n{{ "test" }}{% endif %}'}).render().should.equal("\n\ntest"); -twig({data: '\n{% if true -%}\n\n{{ "test" }}{% endif %}'}).render().should.equal("\ntest"); -twig({data: '\n\t{% if true -%}\n\n\t{{ "test" }}{% endif %}'}).render().should.equal("\n\ttest"); -twig({data: '123\n\t{% if true -%}\n\n\t{{ "test" }}{% endif %}456'}).render().should.equal("123\n\ttest456"); -twig({data: '\n\t{% if true -%}\n\n\t{{ [1,2 ,1+2 ] }}{% endif %}'}).render().should.equal("\n\t1,2,3"); -twig({data: '{% if true -%}<>test{% endif %}'}).render().should.equal("<>test"); -``` - -should be able to output numbers. - -```js -twig({data: '{{ 12 }}'}).render().should.equal( "12" ); -twig({data: '{{ 12.64 }}'}).render().should.equal( "12.64" ); -twig({data: '{{ 0.64 }}'}).render().should.equal("0.64" ); -``` - -should be able to output booleans. - -```js -twig({data: '{{ true }}'}).render().should.equal( "true" ); -twig({data: '{{ false }}'}).render().should.equal( "false" ); -``` - -should be able to output strings. - -```js -twig({data: '{{ "double" }}'}).render().should.equal("double"); -twig({data: "{{ 'single' }}"}).render().should.equal('single'); -twig({data: '{{ "dou\'ble" }}'}).render().should.equal("dou'ble"); -twig({data: "{{ 'sin\"gle' }}"}).render().should.equal('sin"gle'); -twig({data: '{{ "dou\\"ble" }}'}).render().should.equal("dou\"ble"); -twig({data: "{{ 'sin\\'gle' }}"}).render().should.equal("sin'gle"); -``` - -should be able to output strings with newlines. - -```js -twig({data: "{{ 'a\nb\rc\r\nd' }}"}).render().should.equal("a\nb\rc\r\nd"); -``` - -should be able to output arrays. - -```js -twig({data: '{{ [1] }}'}).render().should.equal("1" ); -twig({data: '{{ [1,2 ,3 ] }}'}).render().should.equal("1,2,3" ); -twig({data: '{{ [1,2 ,3 , val ] }}'}).render({val: 4}).should.equal("1,2,3,4" ); -twig({data: '{{ ["[to",\'the\' ,"string]" ] }}'}).render().should.equal('[to,the,string]' ); -twig({data: '{{ ["[to",\'the\' ,"str\\"ing]" ] }}'}).render().should.equal('[to,the,str"ing]' ); -``` - -should be able to output parse expressions in an array. - -```js -twig({data: '{{ [1,2 ,1+2 ] }}'}).render().should.equal("1,2,3" ); -twig({data: '{{ [1,2 ,3 , "-", [4,5, 6] ] }}'}).render({val: 4}).should.equal("1,2,3,-,4,5,6" ); -twig({data: '{{ [a,b ,(1+2) * a ] }}'}).render({a:1,b:2}).should.equal("1,2,3" ); -``` - -should be able to output variables. - -```js -twig({data: '{{ orp }}'}).render({ orp: "test"}).should.equal("test"); -twig({data: '{{ val }}'}).render({ val: function() { - return "test" - }}).should.equal("test"); -``` - -should recognize null. - -```js -twig({data: '{{ null == val }}'}).render({val: null}).should.equal( "true" ); -twig({data: '{{ null == val }}'}).render({val: undefined}).should.equal( "true" ); -twig({data: '{{ null == val }}'}).render({val: "test"}).should.equal( "false" ); -twig({data: '{{ null == val }}'}).render({val: 0}).should.equal( "false" ); -twig({data: '{{ null == val }}'}).render({val: false}).should.equal( "false" ); -``` - -should recognize object literals. - -```js -twig({data: '{% set at = {"foo": "test", bar: "other", 1:"zip"} %}{{ at.foo ~ at.bar ~ at.1 }}'}).render().should.equal( "testotherzip" ); -``` - -should allow newlines in object literals. - -```js -twig({data: '{% set at = {\n"foo": "test",\rbar: "other",\r\n1:"zip"\n} %}{{ at.foo ~ at.bar ~ at.1 }}'}).render().should.equal( "testotherzip" ); -``` - -should recognize null in an object. - -```js -twig({data: '{% set at = {"foo": null} %}{{ at.foo == val }}'}).render({val: null}).should.equal( "true" ); -``` - -should allow int 0 as a key in an object. - -```js -twig({data: '{% set at = {0: "value"} %}{{ at.0 }}'}).render().should.equal( "value" ); -``` - -should support set capture. - -```js -twig({data: '{% set foo %}bar{% endset %}{{foo}}'}).render().should.equal( "bar" ); -``` - -should support raw data. - -```js -twig({ - data: "before {% raw %}{{ test }} {% test2 %} {{{% endraw %} after" -}).render().should.equal( - "before {{ test }} {% test2 %} {{ after" -); -``` - -should support raw data using 'verbatim' tag. - -```js -twig({ - data: "before {% verbatim %}{{ test }} {% test2 %} {{{% endverbatim %} after" -}).render().should.equal( - "before {{ test }} {% test2 %} {{ after" -); -``` - -<a name="twigjs-core---key-notation--"></a> -## Key Notation -> -should support dot key notation. - -```js -twig({data: '{{ key.value }} {{ key.sub.test }}'}).render({ - key: { - value: "test", - sub: { - test: "value" - } - } -}).should.equal("test value"); -``` - -should support square bracket key notation. - -```js -twig({data: '{{ key["value"] }} {{ key[\'sub\']["test"] }}'}).render({ - key: { - value: "test", - sub: { - test: "value" - } - } -}).should.equal("test value"); -``` - -should support mixed dot and bracket key notation. - -```js -twig({data: '{{ key["value"] }} {{ key.sub[key.value] }} {{ s.t["u"].v["w"] }}'}).render({ - key: { - value: "test", - sub: { - test: "value" - } - }, - s: { t: { u: { v: { w: 'x' } } } } -}).should.equal("test value x" ); -``` - -should support dot key notation after a function. - -```js -var test_template = twig({data: '{{ key.fn().value }}'}); -var output = test_template.render({ - key: { - fn: function() { - return { - value: "test" - } - } - } -}); -output.should.equal("test"); -``` - -should support bracket key notation after a function. - -```js -var test_template = twig({data: '{{ key.fn()["value"] }}'}); -var output = test_template.render({ - key: { - fn: function() { - return { - value: "test 2" - } - } - } -}); -output.should.equal("test 2"); -``` - -should check for getKey methods if a key doesn't exist.. - -```js -twig({data: '{{ obj.value }}'}).render({ - obj: { - getValue: function() { - return "val"; - }, - isValue: function() { - return "not val"; - } - } -}).should.equal("val"); -``` - -should check for isKey methods if a key doesn't exist.. - -```js -twig({data: '{{ obj.value }}'}).render({ - obj: { - isValue: function() { - return "val"; - } - } -}).should.equal("val"); -``` - -should check for getKey methods on prototype objects.. - -```js -var object = { - getValue: function() { - return "val"; - } - }; -function Subobj() {}; -Subobj.prototype = object; -var subobj = new Subobj(); - - twig({data: '{{ obj.value }}'}).render({ - obj: subobj - }).should.equal("val"); -``` - -should return null if a period key doesn't exist.. - -```js -twig({data: '{{ obj.value == null }}'}).render({ - obj: {} -}).should.equal("true"); -``` - -should return null if a bracket key doesn't exist.. - -```js -twig({data: '{{ obj["value"] == null }}'}).render({ - obj: {} -}).should.equal("true"); -``` - -<a name="twigjs-core---context--"></a> -## Context -> -should be supported. - -```js -twig({data: '{{ _context.value }}'}).render({ - value: "test" -}).should.equal("test"); -``` - -should be an object even if it's not passed. - -```js -twig({data: '{{ _context|json_encode }}'}).render().should.equal("{}"); -``` - -should support {% set %} tag. - -```js -twig({data: '{% set value = "test" %}{{ _context.value }}'}).render().should.equal("test"); -``` - -should work correctly with properties named dynamically. - -```js -twig({data: '{{ _context[key] }}'}).render({ - key: "value", - value: "test" -}).should.equal("test"); -``` - -should not allow to override context using {% set %}. - -```js -twig({data: '{% set _context = "test" %}{{ _context|json_encode }}'}).render().should.equal('{"_context":"test"}'); -twig({data: '{% set _context = "test" %}{{ _context._context }}'}).render().should.equal("test"); -``` - -should support autoescape option. - -```js -twig({ - autoescape: true, - data: '{{ value }}' -}).render({ - value: "<test>&</test>" -}).should.equal('<test>&</test>'); -``` - -should support autoescape option with alternative strategy. - -```js -twig({ - autoescape: 'js', - data: '{{ value }}' -}).render({ - value: "<test>&</test>" -}).should.equal('\\x3Ctest\\x3E\\x26\\x3C\\x2Ftest\\x3E'); -``` - -should autoescape parent() output correctly. - -```js -twig({id: 'parent1', data: '{% block body %}<p>{{ value }}</p>{% endblock body %}'}); -twig({ - allowInlineIncludes: true, - autoescape: true, - data: '{% extends "parent1" %}{% block body %}{{ parent() }}{% endblock %}' -}).render({ - value: "<test>&</test>" -}).should.equal('<p><test>&</test></p>'); -``` - -should use a correct context in the extended template. - -```js -twig({id: 'parent', data: '{% block body %}{{ value }}{% endblock body %}'}); -twig({ - allowInlineIncludes: true, - data: '{% extends "parent" %}{% set value = "test" %}{% block body %}{{ parent() }}{% endblock %}' -}).render().should.equal("test"); -``` - -should use a correct context in the included template. - -```js -twig({id: 'included', data: '{{ value }}\n{% set value = "inc" %}{{ value }}\n'}); -twig({ - allowInlineIncludes: true, - data: '{% set value = "test" %}{% for i in [0, 1] %}{% include "included" %}{% endfor %}{{ value }}' -}).render().should.equal("test\ninc\ntest\ninc\ntest"); -``` - -<a name="twigjs-embed--"></a> -# Twig.js Embed -> -it should load embed and render. - -```js -twig({ - id: 'embed', - path: 'test/templates/embed-simple.twig', - async: false -}); -// Load the template -twig({ref: 'embed'}).render({ }).trim().should.equal( ['START', - 'A', - 'new header', - 'base footer', - 'B', - '', - 'A', - 'base header', - 'base footer', - 'extended', - 'B', - '', - 'A', - 'base header', - 'extended', - 'base footer', - 'extended', - 'B', - '', - 'A', - 'Super cool new header', - 'Cool footer', - 'B', - 'END'].join('\n') ); -``` - -<a name="twigjs-expressions--"></a> -# Twig.js Expressions -> -<a name="twigjs-expressions---basic-operators--"></a> -## Basic Operators -> -should parse parenthesis. - -```js -var test_template = twig({data: '{{ a - (b + c) }}'}), - d = {a: 10, b: 4, c: 2}, - output = test_template.render(d); -output.should.equal( (d.a - (d.b + d.c)).toString() ); -``` - -should parse nested parenthesis. - -```js -var test_template = twig({data: '{{ a - ((b) + (1 + c)) }}'}), - d = {a: 10, b: 4, c: 2}, - output = test_template.render(d); -output.should.equal( (d.a - (d.b + 1 + d.c)).toString() ); -``` - -should add numbers. - -```js -var test_template = twig({data: '{{ a + b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal( (pair.a + pair.b).toString() ); -}); -``` - -should subtract numbers. - -```js -var test_template = twig({data: '{{ a - b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal( (pair.a - pair.b).toString() ); -}); -``` - -should multiply numbers. - -```js -var test_template = twig({data: '{{ a * b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a * pair.b).toString() ); -}); -``` - -should divide numbers. - -```js -var test_template = twig({data: '{{ a / b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a / pair.b).toString() ); -}); -``` - -should divide numbers and return an int result. - -```js -var test_template = twig({data: '{{ a // b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - // Get expected truncated result - var c = parseInt(pair.a/pair.b); - output.should.equal(c.toString() ); -}); -``` - -should raise numbers to a power. - -```js -var test_template = twig({data: '{{ a ** b }}'}); -var pow_test_data = [ - {a: 2, b:3, c: 8} - , {a: 4, b:.5, c: 2} - , {a: 5, b: 1, c: 5} -]; -pow_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal(pair.c.toString() ); -}); -``` - -should concatanate values. - -```js -twig({data: '{{ "test" ~ a }}'}).render({a:1234}).should.equal("test1234"); -twig({data: '{{ a ~ "test" ~ a }}'}).render({a:1234}).should.equal("1234test1234"); -twig({data: '{{ "this" ~ "test" }}'}).render({a:1234}).should.equal("thistest"); -// Test numbers -var test_template = twig({data: '{{ a ~ b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal(pair.a.toString() + pair.b.toString()); -}); -// Test strings -test_template = twig({data: '{{ a ~ b }}'}); -string_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal(pair.a.toString() + pair.b.toString()); -}); -``` - -should concatenate null and undefined values and not throw an exception. - -```js -twig({data: '{{ a ~ b }}'}).render().should.equal(""); -twig({data: '{{ a ~ b }}'}).render({ - a: null, - b: null -}).should.equal(""); -``` - -should handle multiple chained operations. - -```js -var data = {a: 4.5, b: 10, c: 12, d: -0.25, e:0, f: 65, g: 21, h: -0.0002}; -var test_template = twig({data: '{{a/b+c*d-e+f/g*h}}'}); -var output = test_template.render(data); -var expected = data.a / data.b + data.c * data.d - data.e + data.f / data.g * data.h; -output.should.equal(expected.toString()); -``` - -should handle parenthesis in chained operations. - -```js -var data = {a: 4.5, b: 10, c: 12, d: -0.25, e:0, f: 65, g: 21, h: -0.0002}; -var test_template = twig({data: '{{a /(b+c )*d-(e+f)/(g*h)}}'}); -var output = test_template.render(data); -var expected = data.a / (data.b + data.c) * data.d - (data.e + data.f) / (data.g * data.h); -output.should.equal(expected.toString()); -``` - -<a name="twigjs-expressions---comparison-operators--"></a> -## Comparison Operators -> -should support less then. - -```js -var test_template = twig({data: '{{ a < b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a < pair.b).toString() ); -}); -``` - -should support less then or equal. - -```js -var test_template = twig({data: '{{ a <= b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a <= pair.b).toString() ); -}); -``` - -should support greater then. - -```js -var test_template = twig({data: '{{ a > b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a > pair.b).toString() ); -}); -``` - -should support greater then or equal. - -```js -var test_template = twig({data: '{{ a >= b }}'}); -numeric_test_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a >= pair.b).toString() ); -}); -``` - -should support equals. - -```js -var test_template = twig({data: '{{ a == b }}'}); -boolean_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a == pair.b).toString() ); -}); -equality_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a == pair.b).toString() ); -}); -``` - -should support not equals. - -```js -var test_template = twig({data: '{{ a != b }}'}); -boolean_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a != pair.b).toString() ); -}); -equality_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a != pair.b).toString() ); -}); -``` - -should support boolean or. - -```js -var test_template = twig({data: '{{ a or b }}'}); -boolean_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a || pair.b).toString() ); -}); -``` - -should support boolean and. - -```js -var test_template = twig({data: '{{ a and b }}'}); -boolean_data.forEach(function(pair) { - var output = test_template.render(pair); - output.should.equal((pair.a && pair.b).toString() ); -}); -``` - -should support boolean not. - -```js -var test_template = twig({data: '{{ not a }}'}); -test_template.render({a:false}).should.equal(true.toString()); -test_template.render({a:true}).should.equal(false.toString()); -``` - -<a name="twigjs-expressions---other-operators--"></a> -## Other Operators -> -should support the ternary operator. - -```js -var test_template = twig({data: '{{ a ? b:c }}'}) - , output_t = test_template.render({a: true, b: "one", c: "two"}) - , output_f = test_template.render({a: false, b: "one", c: "two"}); -output_t.should.equal( "one" ); -output_f.should.equal( "two" ); -``` - -should support the ternary operator with objects in it. - -```js -var test_template2 = twig({data: '{{ (a ? {"a":e+f}:{"a":1}).a }}'}) - , output2 = test_template2.render({a: true, b: false, e: 1, f: 2}); -output2.should.equal( "3" ); -``` - -should support the ternary operator inside objects. - -```js -var test_template2 = twig({data: '{{ {"b" : a or b ? {"a":e+f}:{"a":1} }.b.a }}'}) - , output2 = test_template2.render({a: false, b: false, e: 1, f: 2}); -output2.should.equal( "1" ); -``` - -should support in/containment functionality for arrays. - -```js -var test_template = twig({data: '{{ "a" in ["a", "b", "c"] }}'}); -test_template.render().should.equal(true.toString()); -var test_template = twig({data: '{{ "d" in ["a", "b", "c"] }}'}); -test_template.render().should.equal(false.toString()); -``` - -should support not in/containment functionality for arrays. - -```js -var test_template = twig({data: '{{ "a" not in ["a", "b", "c"] }}'}); -test_template.render().should.equal(false.toString()); -var test_template = twig({data: '{{ "d" not in ["a", "b", "c"] }}'}); -test_template.render().should.equal(true.toString()); -``` - -should support in/containment functionality for strings. - -```js -var test_template = twig({data: '{{ "at" in "hat" }}'}); -test_template.render().should.equal(true.toString()); -var test_template = twig({data: '{{ "d" in "not" }}'}); -test_template.render().should.equal(false.toString()); -``` - -should support not in/containment functionality for strings. - -```js -var test_template = twig({data: '{{ "at" not in "hat" }}'}); -test_template.render().should.equal(false.toString()); -var test_template = twig({data: '{{ "d" not in "not" }}'}); -test_template.render().should.equal(true.toString()); -``` - -should support in/containment functionality for objects. - -```js -var test_template = twig({data: '{{ "value" in {"key" : "value", "2": "other"} }}'}); -test_template.render().should.equal(true.toString()); -var test_template = twig({data: '{{ "d" in {"key_a" : "no"} }}'}); -test_template.render().should.equal(false.toString()); -``` - -should support not in/containment functionality for objects. - -```js -var test_template = twig({data: '{{ "value" not in {"key" : "value", "2": "other"} }}'}); -test_template.render().should.equal(false.toString()); -var test_template = twig({data: '{{ "d" not in {"key_a" : "no"} }}'}); -test_template.render().should.equal(true.toString()); -``` - -should support undefined and null for the in operator. - -```js -var test_template = twig({data: '{{ 0 in undefined }} {{ 0 in null }}'}); -test_template.render().should.equal(' '); -``` - -should support expressions as object keys. - -```js -var test_template; -test_template = twig({data: '{% set a = {(foo): "value"} %}{{ a.bar }}'}); -test_template.render({foo: 'bar'}).should.equal('value'); -test_template = twig({data: '{{ {(foo): "value"}.bar }}'}); -test_template.render({foo: 'bar'}).should.equal('value'); -``` - -<a name="twigjs-extensions--"></a> -# Twig.js Extensions -> -should be able to extend a meta-type tag. - -```js -var flags = {}; - Twig.extend(function(Twig) { - Twig.exports.extendTag({ - type: "flag", - regex: /^flag\s+(.+)$/, - next: [ ], - open: true, - compile: function (token) { - var expression = token.match[1]; - - // Compile the expression. - token.stack = Twig.expression.compile.apply(this, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - delete token.match; - return token; - }, - parse: function (token, context, chain) { - var name = Twig.expression.parse.apply(this, [token.stack, context]), - output = ''; - - flags[name] = true; - - return { - chain: false, - output: output - }; - } - }); - }); - var template = twig({data:"{% flag 'enabled' %}"}).render(); - flags.enabled.should.equal(true); -``` - -should be able to extend paired tags. - -```js -// demo data - var App = { - user: "john", - users: { - john: {level: "admin"}, - tom: {level: "user"} - } - }; - Twig.extend(function(Twig) { - // example of extending a tag type that would - // restrict content to the specified "level" - Twig.exports.extendTag({ - type: "auth", - regex: /^auth\s+(.+)$/, - next: ["endauth"], // match the type of the end tag - open: true, - compile: function (token) { - var expression = token.match[1]; - - // turn the string expression into tokens. - token.stack = Twig.expression.compile.apply(this, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - delete token.match; - return token; - }, - parse: function (token, context, chain) { - var level = Twig.expression.parse.apply(this, [token.stack, context]), - output = ""; - - if (App.users[App.currentUser].level == level) - { - output = Twig.parse.apply(this, [token.output, context]); - } - - return { - chain: chain, - output: output - }; - } - }); - Twig.exports.extendTag({ - type: "endauth", - regex: /^endauth$/, - next: [ ], - open: false - }); - }); - var template = twig({data:"Welcome{% auth 'admin' %} ADMIN{% endauth %}!"}); - - App.currentUser = "john"; - template.render().should.equal("Welcome ADMIN!"); - - App.currentUser = "tom"; - template.render().should.equal("Welcome!"); -``` - -should be able to extend the same tag twice, replacing it. - -```js -var flags = {}; -Twig.extend(function(Twig) { - Twig.exports.extendTag({ - type: "noop", - regex: /^noop$/, - next: [ ], - open: true, - parse: function (token, context, chain) { - return { - chain: false, - output: "noop1" - }; - } - }); -}); -var result = twig({data:"{% noop %}"}).render(); -result.should.equal("noop1"); -Twig.extend(function(Twig) { - Twig.exports.extendTag({ - type: "noop", - regex: /^noop$/, - next: [ ], - open: true, - parse: function (token, context, chain) { - return { - chain: false, - output: "noop2" - }; - } - }); -}); -var result = twig({data:"{% noop %}"}).render(); -result.should.equal("noop2"); -``` - -<a name="twigjs-filters--"></a> -# Twig.js Filters -> -should chain. - -```js -var test_template = twig({data: '{{ ["a", "b", "c"]|keys|reverse }}' }); -test_template.render().should.equal("2,1,0"); -``` - -<a name="twigjs-filters---url_encode--"></a> -## url_encode -> -should encode URLs. - -```js -var test_template = twig({data: '{{ "http://google.com/?q=twig.js"|url_encode() }}' }); -test_template.render().should.equal("http%3A%2F%2Fgoogle.com%2F%3Fq%3Dtwig.js" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|url_encode() }}' }); -test_template.render().should.equal("" ); -``` - -should handle special characters. - -```js -var data = { "foo": "<foo> \\&\"'.,-_?/Ķä€台北[]{}\t\r\n\b\x80" }; -var test_template = twig({data: '{{ foo|url_encode() }}' }); -test_template.render(data).should.equal("%3Cfoo%3E%20%5C%26%22%27.%2C-_%3F%2F%C4%B6%C3%A4%E2%82%AC%E5%8F%B0%E5%8C%97%5B%5D%7B%7D%09%0D%0A%08%C2%80" ); -``` - -<a name="twigjs-filters---json_encode--"></a> -## json_encode -> -should encode strings to json. - -```js -var test_template = twig({data: '{{ test|json_encode }}' }); -test_template.render({test:'value'}).should.equal('"value"' ); -``` - -should encode numbers to json. - -```js -var test_template = twig({data: '{{ test|json_encode }}' }); -test_template.render({test:21}).should.equal('21' ); -``` - -should encode arrays to json. - -```js -var test_template = twig({data: '{{ [1,"b",3]|json_encode }}' }); -test_template.render().should.equal('[1,"b",3]' ); -``` - -should encode objects to json. - -```js -var test_template = twig({data: '{{ {"a":[1,"b",3]}|json_encode }}' }); -test_template.render().should.equal('{"a":[1,"b",3]}' ); -``` - -should retain key order in an object. - -```js -twig({data: '{{ { "foo": 1, "bar": 2, "baz": 3 }|json_encode }}'}).render().should.equal( '{"foo":1,"bar":2,"baz":3}' ); -``` - -should not add additional information to objects. - -```js -twig({data: '{{ { "foo": 1, "bar": [1, 2, 3], "baz": { "a": "a", "b": "b" } }|json_encode }}'}).render().should.equal( '{"foo":1,"bar":[1,2,3],"baz":{"a":"a","b":"b"}}' ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|json_encode }}' }); -test_template.render().should.equal("null" ); -``` - -<a name="twigjs-filters---upper--"></a> -## upper -> -should convert text to uppercase. - -```js -var test_template = twig({data: '{{ "hello"|upper }}' }); -test_template.render().should.equal("HELLO" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|upper }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---lower--"></a> -## lower -> -should convert text to lowercase. - -```js -var test_template = twig({data: '{{ "HELLO"|lower }}' }); -test_template.render().should.equal("hello" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|lower }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---capitalize--"></a> -## capitalize -> -should capitalize the first word in a string. - -```js -var test_template = twig({data: '{{ "hello world"|capitalize }}' }); -test_template.render().should.equal("Hello world" ); -var test_template2 = twig({data: '{{ "HELLO WORLD"|capitalize }}' }); -test_template2.render().should.equal("Hello world" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|capitalize }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---title--"></a> -## title -> -should capitalize all the words in a string. - -```js -var test_template = twig({data: '{{ "hello world"|title }}' }); -test_template.render().should.equal("Hello World" ); -var test_template2 = twig({data: '{{ "HELLO WORLD"|title }}' }); -test_template2.render().should.equal("Hello World" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|title }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---length--"></a> -## length -> -should determine the length of a string. - -```js -var test_template = twig({data: '{{ "test"|length }}' }); -test_template.render().should.equal("4"); -``` - -should determine the length of an array. - -```js -var test_template = twig({data: '{{ [1,2,4,76,"tesrt"]|length }}' }); -test_template.render().should.equal("5"); -``` - -should determine the length of an object. - -```js -var test_template = twig({data: '{{ {"a": "b", "c": "1", "test": "test"}|length }}' }); -test_template.render().should.equal("3"); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|length }}' }); -test_template.render().should.equal("0" ); -``` - -<a name="twigjs-filters---sort--"></a> -## sort -> -should sort an array. - -```js -var test_template = twig({data: '{{ [1,5,2,7]|sort }}' }); -test_template.render().should.equal("1,2,5,7" ); -test_template = twig({data: '{{ ["test","abc",2,7]|sort }}' }); -test_template.render().should.equal("2,7,abc,test" ); -``` - -should sort an object. - -```js -var test_template = twig({data: "{% set obj = {'c': 1,'d': 5,'t': 2,'e':7}|sort %}{% for key,value in obj|sort %}{{key}}:{{value}} {%endfor %}" }); -test_template.render().should.equal("c:1 t:2 d:5 e:7 " ); -test_template = twig({data: "{% set obj = {'m':'test','z':'abc','a':2,'y':7} %}{% for key,value in obj|sort %}{{key}}:{{value}} {%endfor %}" }); -test_template.render().should.equal("a:2 y:7 z:abc m:test " ); -test_template = twig({data: "{% set obj = {'z':'abc','a':2,'y':7,'m':'test'} %}{% for key,value in obj|sort %}{{key}}:{{value}} {%endfor %}" }); -test_template.render().should.equal("a:2 y:7 z:abc m:test " ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{% set obj = undef|sort %}{% for key, value in obj|sort %}{{key}}:{{value}}{%endfor%}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---reverse--"></a> -## reverse -> -should reverse an array. - -```js -var test_template = twig({data: '{{ ["a", "b", "c"]|reverse }}' }); -test_template.render().should.equal("c,b,a" ); -``` - -should reverse an object. - -```js - -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|reverse }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---keys--"></a> -## keys -> -should return the keys of an array. - -```js -var test_template = twig({data: '{{ ["a", "b", "c"]|keys }}' }); -test_template.render().should.equal("0,1,2" ); -``` - -should return the keys of an object. - -```js -var test_template = twig({data: '{{ {"a": 1, "b": 4, "c": 5}|keys }}' }); -test_template.render().should.equal("a,b,c" ); -test_template = twig({data: '{{ {"0":"a", "1":"b", "2":"c"}|keys }}' }); -test_template.render().should.equal("0,1,2" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|keys }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---merge--"></a> -## merge -> -should merge two objects into an object. - -```js -// Object merging -var test_template = twig({data: '{% set obj= {"a":"test", "b":"1"}|merge({"b":2,"c":3}) %}{% for key in obj|keys|sort %}{{key}}:{{obj[key]}} {%endfor %}' }); -test_template.render().should.equal('a:test b:2 c:3 ' ); -``` - -should merge two arrays into and array. - -```js -// Array merging -var test_template = twig({data: '{% set obj= ["a", "b"]|merge(["c", "d"]) %}{% for key in obj|keys|sort %}{{key}}:{{obj[key]}} {%endfor %}' }); -test_template.render().should.equal('0:a 1:b 2:c 3:d ' ); -``` - -should merge an object and an array into an object. - -```js -// Mixed merging -var test_template = twig({data: '{% set obj= ["a", "b"]|merge({"a": "c", "3":4}, ["c", "d"]) %}{% for key in obj|keys|sort %}{{key}}:{{obj[key]}} {%endfor %}' }); -test_template.render().should.equal('0:a 1:b 3:4 4:c 5:d a:c ' ); -// Mixed merging(2) -test_template = twig({data: '{% set obj= {"1":"a", "a":"b"}|merge(["c", "d"]) %}{% for key in obj|keys %}{{key}}:{{obj[key]}} {%endfor %}' }); -test_template.render().should.equal('1:a a:b 2:c 3:d ' ); -``` - -<a name="twigjs-filters---join--"></a> -## join -> -should join all values in an object. - -```js -var test_template = twig({data: '{{ {"a":"1", "b": "b", "c":test}|join("-") }}' }); -test_template.render({"test": "t"}).should.equal("1-b-t" ); -``` - -should joing all values in an array. - -```js -var test_template = twig({data: '{{ [1,2,4,76]|join }}' }); -test_template.render().should.equal("12476" ); -test_template = twig({data: '{{ [1+ 5,2,4,76]|join("-" ~ ".") }}' }); -test_template.render().should.equal("6-.2-.4-.76" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|join }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---default--"></a> -## default -> -should not provide the default value if a key is defined and not empty. - -```js -var test_template = twig({data: '{{ var|default("Not Defined") }}' }); -test_template.render({"var":"value"}).should.equal("value" ); -``` - -should provide a default value if a key is not defined. - -```js -var test_template = twig({data: '{{ var|default("Not Defined") }}' }); -test_template.render().should.equal("Not Defined" ); -``` - -should provide a default value if a value is empty. - -```js -var test_template = twig({data: '{{ ""|default("Empty String") }}' }); -test_template.render().should.equal("Empty String" ); -test_template = twig({data: '{{ var.key|default("Empty Key") }}' }); -test_template.render({'var':{}}).should.equal("Empty Key" ); -``` - -should provide a default value of '' if no parameters are passed and a default key is not defined. - -```js -var test_template = twig({data: '{{ var|default }}' }); -test_template.render().should.equal(""); -``` - -should provide a default value of '' if no parameters are passed and a value is empty. - -```js -var test_template = twig({data: '{{ ""|default }}' }); -test_template.render().should.equal(""); -test_template = twig({data: '{{ var.key|default }}' }); -test_template.render({'var':{}}).should.equal(""); -``` - -<a name="twigjs-filters---date--"></a> -## date -> -should recognize timestamps. - -```js -var template = twig({data: '{{ 27571323556|date("d/m/Y @ H:i:s") }}'}) - , date = new Date(27571323556000); // 13/09/2843 @ 08:59:16 EST -template.render().should.equal( stringDate(date) ); -``` - -should recognize timestamps, when they are passed as string. - -```js -var template = twig({data: '{{ "27571323556"|date("d/m/Y @ H:i:s") }}'}) - , date = new Date(27571323556000); // 13/09/2843 @ 08:59:16 EST -template.render().should.equal( stringDate(date) ); -``` - -should recognize string date formats. - -```js -var template = twig({data: '{{ "Tue Aug 14 08:52:15 +0000 2007"|date("d/m/Y @ H:i:s") }}'}) - , date = new Date(1187081535000); // 14/08/2007 @ 04:52:15 EST -template.render().should.equal( stringDate(date) ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|date("d/m/Y @ H:i:s") }}' }); -var date = new Date(); -test_template.render().should.equal(stringDate(date)); -``` - -should work with no parameters. - -```js -var test_template = twig({data: '{{ 27571323556|date }}' }); -test_template.render().should.equal(twig({data: '{{ 27571323556|date("F j, Y H:i") }}'}).render()); -``` - -<a name="twigjs-filters---replace--"></a> -## replace -> -should replace strings provided in a map. - -```js -var template = twig({data: '{{ "I like %this% and %that%. Seriously, I like %this% and %that%."|replace({"%this%": foo, "%that%": "bar"}) }}'}); -template.render({foo: "foo"}).should.equal("I like foo and bar. Seriously, I like foo and bar." ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|replace }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---format--"></a> -## format -> -should replace formatting tags with parameters. - -```js -var template = twig({data: '{{ "I like %s and %s."|format(foo, "bar") }}'}); -template.render({foo: "foo"}).should.equal("I like foo and bar." ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|format }}' }); -test_template.render().should.equal("" ); -``` - -should handle positive leading sign without padding. - -```js -var template = twig({data: '{{ "I like positive numbers like %+d."|format(123) }}'}); -template.render({foo: "foo"}).should.equal("I like positive numbers like +123." ); -``` - -should handle negative leading sign without padding. - -```js -var template = twig({data: '{{ "I like negative numbers like %+d."|format(-123) }}'}); -template.render({foo: "foo"}).should.equal("I like negative numbers like -123." ); -``` - -should handle positive leading sign with padding zero. - -```js -var template = twig({data: '{{ "I like positive numbers like %+05d."|format(123) }}'}); -template.render({foo: "foo"}).should.equal("I like positive numbers like +0123." ); -``` - -should handle negative leading sign with padding zero. - -```js -var template = twig({data: '{{ "I like negative numbers like %+05d."|format(-123) }}'}); -template.render({foo: "foo"}).should.equal("I like negative numbers like -0123." ); -``` - -should handle positive leading sign with padding space. - -```js -var template = twig({data: '{{ "I like positive numbers like %+5d."|format(123) }}'}); -template.render({foo: "foo"}).should.equal("I like positive numbers like +123." ); -``` - -should handle negative leading sign with padding space. - -```js -var template = twig({data: '{{ "I like negative numbers like %+5d."|format(-123) }}'}); -template.render({foo: "foo"}).should.equal("I like negative numbers like -123." ); -``` - -<a name="twigjs-filters---striptags--"></a> -## striptags -> -should remove tags from a value. - -```js -var template = twig({data: '{{ "<p>Test paragraph.</p><!-- Comment --> <a href=\\"#fragment\\">Other text</a>"|striptags }}'}); -template.render().should.equal("Test paragraph. Other text" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|striptags }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---escape--"></a> -## escape -> -should convert unsafe characters to HTML entities. - -```js -var template = twig({data: '{{ "<p>Test paragraph.</p><!-- Comment --> <a href=\'#fragment\'>Other text</a>"|escape }}'}); -template.render().should.equal("<p>Test paragraph.</p><!-- Comment --> <a href='#fragment\'>Other text</a>" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|escape }}' }); -test_template.render().should.equal("" ); -``` - -should not escape twice if autoescape is on. - -```js -twig({ - autoescape: true, - data: '{{ value|escape }}' -}).render({ - value: "<test>&</test>" -}).should.equal('<test>&</test>'); -``` - -should handle the strategy parameter. - -```js -var data = { "foo": "<foo> \\&\"'.,-_?/Ķä€台北[]{}\t\r\n\b\x80" }; -var test_template = twig({data: 'Default: {{ foo|escape }}' }); -test_template.render(data).should.equal("Default: <foo> \\&"'.,-_?/Ķä€台北[]{}\t\r\n\b\x80" ); -var test_template = twig({data: 'html: {{ foo|escape("html") }}' }); -test_template.render(data).should.equal("html: <foo> \\&"'.,-_?/Ķä€台北[]{}\t\r\n\b\x80" ); -var test_template = twig({data: 'js: {{ foo|escape("js") }}' }); -test_template.render(data).should.equal("js: \\x3Cfoo\\x3E\\x20\\x5C\\x26\\x22\\x27.,\\x2D_\\x3F\\x2F\\u0136\\u00E4\\u20AC\\u53F0\\u5317\\x5B\\x5D\\x7B\\x7D\\x9\\xD\\xA\\x8\\u0080" ); -var test_template = twig({data: 'css: {{ foo|escape("css") }}' }); -test_template.render(data).should.equal("css: \\3C foo\\3E \\20 \\5C \\26 \\22 \\27 \\2E \\2C \\2D \\5F \\3F \\2F \\136 \\E4 \\20AC \\53F0 \\5317 \\5B \\5D \\7B \\7D \\9 \\D \\A \\8 \\80 " ); -var test_template = twig({data: 'url: {{ foo|escape("url") }}' }); -test_template.render(data).should.equal("url: %3Cfoo%3E%20%5C%26%22%27.%2C-_%3F%2F%C4%B6%C3%A4%E2%82%AC%E5%8F%B0%E5%8C%97%5B%5D%7B%7D%09%0D%0A%08%C2%80" ); -var test_template = twig({data: 'html_attr: {{ foo|escape("html_attr") }}' }); -test_template.render(data).should.equal("html_attr: <foo> \&"'.,-_?/Ķä€台北[]{}	
�€" ); -``` - -should escape strategy != 'html' if autoescape is on. - -```js -twig({ - autoescape: true, - data: '{{ value|escape("js") }}' -}).render({ - value: "<test>&</test>" -}).should.equal('\\x3Ctest\\x3E\\x26\\x3C\\x2Ftest\\x3E'); -``` - -should not escape twice if autoescape is not html. - -```js -twig({ - autoescape: 'js', - data: '{{ value|escape("js") }}' -}).render({ - value: "<test>&</test>" -}).should.equal('\\x3Ctest\\x3E\\x26\\x3C\\x2Ftest\\x3E'); -``` - -should escape twice if escape strategy is different from autoescape option. - -```js -twig({ - autoescape: 'css', - data: '{{ value|escape("js") }}\n{{ value|escape }}' -}).render({ - value: "<test>&</test>" -}).should.equal('\\5C x3Ctest\\5C x3E\\5C x26\\5C x3C\\5C x2Ftest\\5C x3E\n\\26 lt\\3B test\\26 gt\\3B \\26 amp\\3B \\26 lt\\3B \\2F test\\26 gt\\3B '); -``` - -<a name="twigjs-filters---e--"></a> -## e -> -should alias escape function with e. - -```js -var template = twig({data: '{{ "<p>Test paragraph.</p><!-- Comment --> <a href=\'#fragment\'>Other text</a>"|e }}'}); -template.render().should.equal("<p>Test paragraph.</p><!-- Comment --> <a href='#fragment\'>Other text</a>" ); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|e }}' }); -test_template.render().should.equal("" ); -``` - -should not escape twice if autoescape is on. - -```js -var template = twig({ - autoescape: true, - data: '{{ value|e }}' -}); -template.render({ - value: "<test>&</test>" -}).should.equal('<test>&</test>'); -``` - -<a name="twigjs-filters---nl2br--"></a> -## nl2br -> -should convert newlines into html breaks. - -```js -var template = twig({data: '{{ test|nl2br }}'}); -template.render({ test: 'Line 1\r\nLine 2\nLine 3\rLine 4\n\n' }) - .should.equal("Line 1<br />\nLine 2<br />\nLine 3<br />\nLine 4<br />\n<br />\n"); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|nl2br }}' }); -test_template.render().should.equal("" ); -``` - -should not escape br tags if autoescape is on. - -```js -twig({ - autoescape: true, - data: '{{ test|nl2br }}' -}).render({ - test: '<test>Line 1\nLine2</test>' -}).should.equal("<test>Line 1<br />\nLine2</test>"); -``` - -<a name="twigjs-filters---truncate--"></a> -## truncate -> -should truncate string to default size(20) and add default separator. - -```js -var template = twig({data: '{{ test|truncate }}'}); -template.render({test: '01234567890123456789012345678901234567890123456789'}).should.equal("012345678901234567890123456789..."); -``` - -should truncate string to custom size(10) and add default separator. - -```js -var template = twig({data: '{{ test|truncate(10) }}'}); -template.render({test: '01234567890123456789012345678901234567890123456789'}).should.equal("0123456789..."); -``` - -should truncate string to custom size(15) with preserve and add default separator. - -```js -var template = twig({data: '{{ test|truncate(15, true) }}'}); -template.render({test: '0123456789 0123456789 0123456789 0123456789 0123456789'}).should.equal("0123456789 0123456789..."); -``` - -should truncate string to custom size(15) with preserve and add custom(*) separator. - -```js -var template = twig({data: '{{ test|truncate(15, true, "*") }}'}); -template.render({test: '0123456789 0123456789 0123456789 0123456789 0123456789'}).should.equal("0123456789 0123456789*"); -``` - -<a name="twigjs-filters---trim--"></a> -## trim -> -should trim whitespace from strings. - -```js -var template = twig({data: '{{ test|trim }}'}); -template.render({ test: '\r\n Test\n ' }).should.equal("Test"); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|trim }}' }); -test_template.render().should.equal("" ); -``` - -<a name="twigjs-filters---number_format--"></a> -## number_format -> -should round to nearest integer if no parameters. - -```js -var template = twig({data: '{{ 1234.56|number_format }}'}); -template.render().should.equal("1,235"); -``` - -should have customizable precision. - -```js -var template = twig({data: '{{ 1234.567890123|number_format(4) }}'}); -template.render().should.equal("1,234.5679"); -``` - -should have a customizable decimal seperator. - -```js -var template = twig({data: '{{ 1234.567890123|number_format(2,",") }}'}); -template.render().should.equal("1,234,57"); -``` - -should have a customizable thousands seperator. - -```js -var template = twig({data: '{{ 1234.5678|number_format(2,","," ") }}'}); -template.render().should.equal("1 234,57"); -``` - -should handle blank seperators. - -```js -var template = twig({data: '{{ 1234.5678|number_format(2,"","") }}'}); -template.render().should.equal("123457"); -``` - -should handle undefined. - -```js -var test_template = twig({data: '{{ undef|number_format }}' }); -test_template.render().should.equal("0"); -``` - -<a name="twigjs-filters---slice--"></a> -## slice -> -should slice a string. - -```js -var test_template = twig({data: "{{ '12345'|slice(1, 2) }}" }); -test_template.render().should.equal("23"); -``` - -should slice a string to the end. - -```js -var test_template = twig({data: "{{ '12345'|slice(2) }}" }); -test_template.render().should.equal("345"); -``` - -should slice a string from the start. - -```js -var test_template = twig({data: "{{ '12345'|slice(null, 2) }}" }); -test_template.render().should.equal("12"); -``` - -should slice a string from a negative offset. - -```js -var test_template = twig({data: "{{ '12345'|slice(-2, 1) }}" }); -test_template.render().should.equal("4"); -``` - -should slice a string from a negative offset to end of string. - -```js -var test_template = twig({data: "{{ '12345'|slice(-2) }}" }); -test_template.render().should.equal("45"); -``` - -should slice an array. - -```js -var test_template = twig({data: "{{ [1, 2, 3, 4, 5]|slice(1, 2)|join(',') }}" }); -test_template.render().should.equal("2,3"); -``` - -should slice an array to the end. - -```js -var test_template = twig({data: "{{ [1, 2, 3, 4, 5]|slice(2)|join(',') }}" }); -test_template.render().should.equal("3,4,5"); -``` - -should slice an array from the start. - -```js -var test_template = twig({data: "{{ [1, 2, 3, 4, 5]|slice(null, 2)|join(',') }}" }); -test_template.render().should.equal("1,2"); -``` - -should slice an array from a negative offset. - -```js -var test_template = twig({data: "{{ [1, 2, 3, 4, 5]|slice(-2, 1)|join(',') }}" }); -test_template.render().should.equal("4"); -``` - -should slice an array from a negative offset to the end of the array. - -```js -var test_template = twig({data: "{{ [1, 2, 3, 4, 5]|slice(-4)|join(',') }}" }); -test_template.render().should.equal("2,3,4,5"); -``` - -<a name="twigjs-filters---abs--"></a> -## abs -> -should convert negative numbers to its absolute value. - -```js -var test_template = twig({data: "{{ '-7.365'|abs }}"}); -test_template.render().should.equal("7.365"); -``` - -should not alter absolute numbers. - -```js -var test_template = twig({data: "{{ 95|abs }}"}); -test_template.render().should.equal("95"); -``` - -<a name="twigjs-filters---first--"></a> -## first -> -should return first item in array. - -```js -var test_template = twig({data: "{{ ['a', 'b', 'c', 'd']|first }}"}); -test_template.render().should.equal("a"); -``` - -should return first member of object. - -```js -var test_template = twig({data: "{{ { item1: 'a', item2: 'b', item3: 'c', item4: 'd'}|first }}"}); -test_template.render().should.equal("a"); -``` - -should not fail when passed empty obj, arr or str. - -```js -var test_template = twig({data: "{{ {}|first }}"}); -test_template.render().should.equal(""); -var test_template = twig({data: "{{ []|first }}"}); -test_template.render().should.equal(""); -var test_template = twig({data: "{{ myemptystr|first }}"}); -test_template.render({myemptystr: ""}).should.equal(""); -``` - -should return first character in string. - -```js -var test_template = twig({data: "{{ 'abcde'|first }}"}); -test_template.render().should.equal("a"); -``` - -<a name="twigjs-filters---split--"></a> -## split -> -should split string with a separator. - -```js -var test_template = twig({data: "{{ 'one-two-three'|split('-') }}"}); -test_template.render().should.equal("one,two,three"); -``` - -should split string with a separator and positive limit. - -```js -var test_template = twig({data: "{{ 'one-two-three-four-five'|split('-', 3) }}"}); -test_template.render().should.equal("one,two,three-four-five"); -``` - -should split string with a separator and negative limit. - -```js -var test_template = twig({data: "{{ 'one-two-three-four-five'|split('-', -2) }}"}); -test_template.render().should.equal("one,two,three"); -``` - -should split with empty separator. - -```js -var test_template = twig({data: "{{ '123'|split('') }}"}); -test_template.render().should.equal("1,2,3"); -``` - -should split with empty separator and limit. - -```js -var test_template = twig({data: "{{ 'aabbcc'|split('', 2) }}"}); -test_template.render().should.equal("aa,bb,cc"); -``` - -<a name="twigjs-filters---batch--"></a> -## batch -> -should work with arrays that require filling (with fill specified). - -```js -var test_template = twig({data: "{{ ['a', 'b', 'c', 'd', 'e', 'f', 'g']|batch(3, 'x') }}"}); -test_template.render().should.equal("a,b,c,d,e,f,g,x,x"); -``` - -should work with arrays that require filling (without fill specified). - -```js -var test_template = twig({data: "{{ ['a', 'b', 'c', 'd', 'e', 'f', 'g']|batch(3) }}"}); -test_template.render().should.equal("a,b,c,d,e,f,g"); -``` - -should work with arrays that do not require filling (with fill specified). - -```js -var test_template = twig({data: "{{ ['a', 'b', 'c', 'd', 'e', 'f']|batch(3, 'x') }}"}); -test_template.render().should.equal("a,b,c,d,e,f"); -``` - -should work with arrays that do not require filling (without fill specified). - -```js -var test_template = twig({data: "{{ ['a', 'b', 'c', 'd', 'e', 'f']|batch(3) }}"}); -test_template.render().should.equal("a,b,c,d,e,f"); -``` - -should return an empty result for an empty array. - -```js -var test_template = twig({data: "{{ []|batch(3, 'x') }}"}); -test_template.render().should.equal(""); -``` - -<a name="twigjs-filters---last--"></a> -## last -> -should return last character in string. - -```js -var test_template = twig({data: "{{ 'abcd'|last }}"}); -test_template.render().should.equal("d"); -``` - -should return last item in array. - -```js -var test_template = twig({data: "{{ ['a', 'b', 'c', 'd']|last }}"}); -test_template.render().should.equal("d"); -``` - -should return last item in a sorted object. - -```js -var test_template = twig({data: "{{ {'m':1, 'z':5, 'a':3}|sort|last }}" }); -test_template.render().should.equal("5"); -``` - -<a name="twigjs-filters---raw--"></a> -## raw -> -should output the raw value if autoescape is on. - -```js -var template = twig({ - autoescape: true, - data: '{{ value|raw }}' -}); -template.render({ - value: "<test>&</test>" -}).should.equal('<test>&</test>'); -``` - -should output the raw value if autoescape is off. - -```js -var template = twig({ - autoescape: false, - data: '{{ value|raw }}' -}); -template.render({ - value: "<test>&</test>" -}).should.equal('<test>&</test>'); -``` - -<a name="twigjs-filters---round--"></a> -## round -> -should round up (common). - -```js -var test_template = twig({data: "{{ 2.7|round }}"}); -test_template.render().should.equal("3"); -``` - -should round down (common). - -```js -var test_template = twig({data: "{{ 2.1|round }}"}); -test_template.render().should.equal("2"); -``` - -should truncate input when input decimal places exceeds precision (floor). - -```js -var test_template = twig({data: "{{ 2.1234|round(3, 'floor') }}" }); -test_template.render().should.equal("2.123"); -``` - -should round up (ceil). - -```js -var test_template = twig({data: "{{ 2.1|round(0, 'ceil') }}" }); -test_template.render().should.equal("3"); -``` - -should truncate precision when a negative precision is passed (common). - -```js -var test_template = twig({data: "{{ 21.3|round(-1)}}" }); -test_template.render().should.equal("20"); -``` - -should round up and truncate precision when a negative precision is passed (ceil). - -```js -var test_template = twig({data: "{{ 21.3|round(-1, 'ceil')}}" }); -test_template.render().should.equal("30"); -``` - -should round down and truncate precision when a negative precision is passed (floor). - -```js -var test_template = twig({data: "{{ 21.3|round(-1, 'ceil')}}" }); -test_template.render().should.equal("30"); -``` - -<a name="twigjs-loader--"></a> -# Twig.js Loader -> -should load a template from the filesystem asynchronously. - -```js -twig({ - id: 'fs-node-async', - path: 'test/templates/test.twig', - load: function(template) { - // Render the template - template.render({ - test: "yes", - flag: true - }).should.equal("Test template = yes\n\nFlag set!"); - done(); - } -}); -``` - -should load a template from the filesystem synchronously. - -```js -var template = twig({ - id: 'fs-node-sync', - path: 'test/templates/test.twig', - async: false -}); -// Render the template -template.render({ - test: "yes", - flag: true -}).should.equal("Test template = yes\n\nFlag set!"); -``` - -<a name="twigjs-loader---source--"></a> -## source -> -should load the non-compiled template source code. - -```js -twig({data: '{{ source("test/templates/source.twig") }}'}) - .render() - .should - .equal('{% if isUserNew == true %}\n Hello {{ name }}\n{% else %}\n Welcome back {{ name }}\n{% endif %}\n') -; -``` - -should indicate if there was a problem loading the template if 'ignore_missing' is false. - -```js -twig({data: '{{ source("test/templates/non-existing-source.twig", false) }}'}) - .render() - .should - .equal('Template "test/templates/non-existing-source.twig" is not defined.') -; -``` - -should NOT indicate if there was a problem loading the template if 'ignore_missing' is true. - -```js -twig({data: '{{ source("test/templates/non-existing-source.twig", true) }}'}) - .render() - .should - .equal('') -; -``` - -<a name="twigjs-include--"></a> -# Twig.js Include -> -should load an included template with no context. - -```js -twig({ - id: 'include', - path: 'test/templates/include.twig', - async: false -}); -// Load the template -twig({ref: 'include'}).render({test: 'tst'}).should.equal( "BeforeTest template = tst\n\nAfter" ); -``` - -should load an included template with additional context. - -```js -twig({ - id: 'include-with', - path: 'test/templates/include-with.twig', - async: false -}); -// Load the template -twig({ref: 'include-with'}).render({test: 'tst'}).should.equal( "template: before,tst-mid-template: after,tst" ); -``` - -should load an included template with only additional context. - -```js -twig({ - id: 'include-only', - path: 'test/templates/include-only.twig', - async: false -}); -// Load the template -twig({ref: 'include-only'}).render({test: 'tst'}).should.equal( "template: before,-mid-template: after," ); -``` - -<a name="twigjs-functions--"></a> -# Twig.js Functions -> -should allow you to define a function. - -```js -twig({data: '{{ square(a) }}'}).render({a:4}).should.equal("16"); -``` - -should chain with other expressions. - -```js -twig({data: '{{ square(a) + 4 }}'}).render({a:4}).should.equal("20"); -``` - -should chain with filters. - -```js -twig({data: '{{ echo(a)|default("foo") }}'}).render().should.equal("foo"); -``` - -should work in for loop expressions. - -```js -twig({data: '{% for i in list(1, 2, 3) %}{{ i }},{% endfor %}'}).render().should.equal("1,2,3,"); -``` - -should be able to differentiate between a function and a variable. - -```js -twig({data: '{{ square ( square ) + square }}'}).render({square: 2}).should.equal("6"); -``` - -should work with boolean operations. - -```js -twig({data: '{% if echo(true) or echo(false) %}yes{% endif %}'}).render().should.equal("yes"); -``` - -should execute functions passed as context values. - -```js -twig({ - data: '{{ value }}' -}).render({ - value: function() { - return "test"; - } -}).should.equal("test"); -``` - -should execute functions passed as context values with this mapped to the context. - -```js -twig({ - data: '{{ value }}' -}).render({ - test: "value", - value: function() { - return this.test; - } -}).should.equal("value"); -``` - -should execute functions passed as context values with arguments. - -```js -twig({ - data: '{{ value(1, "test") }}' -}).render({ - value: function(a, b, c) { - return a + "-" + b + "-" + (c===undefined?"true":"false"); - } -}).should.equal("1-test-true"); -``` - -should execute functions passed as context value parameters with this mapped to the context. - -```js -twig({ - data: '{{ value }}' -}).render({ - test: "value", - value: function() { - return this.test; - } -}).should.equal("value"); -``` - -should execute functions passed as context object parameters. - -```js -twig({ - data: '{{ obj.value }}' -}).render({ - obj: { - value: function() { - return "test"; - } - } -}).should.equal("test"); -``` - -should execute functions passed as context object parameters with arguments. - -```js -twig({ - data: '{{ obj.value(1, "test") }}' -}).render({ - obj: { - value: function(a, b, c) { - return a + "-" + b + "-" + (c===undefined?"true":"false"); - } - } -}).should.equal("1-test-true"); -``` - -should execute functions passed as context object parameters. - -```js -twig({ - data: '{{ obj["value"] }}' -}).render({ - obj: { - value: function() { - return "test"; - } - } -}).should.equal("test"); -``` - -should execute functions passed as context object parameters with arguments. - -```js -twig({ - data: '{{ obj["value"](1, "test") }}' -}).render({ - obj: { - value: function(a, b, c) { - return a + "-" + b + "-" + (c===undefined?"true":"false"); - } - } -}).should.equal("1-test-true"); -``` - -<a name="twigjs-functions---built-in-functions--"></a> -## Built-in Functions -> -<a name="twigjs-functions---built-in-functions---range--"></a> -### range -> -should work over a range of numbers. - -```js -twig({data: '{% for i in range(0, 3) %}{{ i }},{% endfor %}'}).render().should.equal("0,1,2,3,"); -``` - -should work over a range of letters. - -```js -twig({data: '{% for i in range("a", "c") %}{{ i }},{% endfor %}'}).render().should.equal("a,b,c,"); -``` - -should work with an interval. - -```js -twig({data: '{% for i in range(1, 15, 3) %}{{ i }},{% endfor %}'}).render().should.equal("1,4,7,10,13,"); -``` - -should work with .. invocation. - -```js -twig({data: '{% for i in 0..3 %}{{ i }},{% endfor %}'}).render().should.equal("0,1,2,3,"); -twig({data: '{% for i in "a" .. "c" %}{{ i }},{% endfor %}'}).render().should.equal("a,b,c,"); -``` - -<a name="twigjs-functions---built-in-functions---cycle--"></a> -### cycle -> -should cycle through an array of values. - -```js -twig({data: '{% for i in range(0, 3) %}{{ cycle(["odd", "even"], i) }};{% endfor %}'}).render().should.equal("odd;even;odd;even;"); -``` - -<a name="twigjs-functions---built-in-functions---date--"></a> -### date -> -should understand timestamps. - -```js -var date = new Date(946706400 * 1000); -twig({data: '{{ date(946706400)|date("d/m/Y @ H:i:s") }}'}).render().should.equal(stringDate(date)); -``` - -should understand relative dates. - -```js -twig({data: '{{ date("+1 day") > date() }}'}).render().should.equal("true"); -twig({data: '{{ date("-1 day") > date() }}'}).render().should.equal("false"); -``` - -should support 'now' as a date parameter. - -```js -twig({data: '{{ date("now") }}' }).render().should.equal(new Date().toString()); -``` - -should understand exact dates. - -```js -var date = new Date("June 20, 2010 UTC"); - -twig({data: '{{ date("June 20, 2010 UTC")|date("d/m/Y @ H:i:s") }}'}).render().should.equal(stringDate(date)); -``` - -<a name="twigjs-functions---built-in-functions---dump--"></a> -### dump -> -should output formatted number. - -```js -twig({data: '{{ dump(test) }}' }).render({ test: 5 }).should.equal('number(5)' + EOL); -``` - -should output formatted string. - -```js -twig({data: '{{ dump(test) }}' }).render({ test: "String" }).should.equal('string(6) "String"' + EOL); -``` - -should output formatted boolean. - -```js -twig({data: '{{ dump(test) }}' }).render({ test: true }).should.equal('bool(true)' + EOL); -``` - -should output formatted null. - -```js -twig({data: '{{ dump(test) }}' }).render({ test: null }).should.equal('NULL' + EOL); -``` - -should output formatted object. - -```js -twig({data: '{{ dump(test) }}' }).render({ test: {} }).should.equal('object(0) {' + EOL + '}' + EOL); -``` - -should output formatted array. - -```js -twig({data: '{{ dump(test) }}' }).render({ test: [] }).should.equal('object(0) {' + EOL + '}' + EOL); -``` - -should output formatted undefined. - -```js -twig({data: '{{ dump(test) }}' }).render({ test: undefined }).should.equal('undefined' + EOL); -``` - -<a name="twigjs-functions---built-in-functions---block--"></a> -### block -> -should render the content of blocks. - -```js -twig({data: '{% block title %}Content - {{ val }}{% endblock %} Title: {{ block("title") }}'}).render({ val: "test" }) - .should.equal("Content - test Title: Content - test"); -``` - -shouldn't escape the content of blocks twice. - -```js -twig({ - autoescape: true, - data: '{% block test %}{{ val }}{% endblock %} {{ block("test") }}' -}).render({ - val: "te&st" -}).should.equal("te&st te&st"); -``` - -<a name="twigjs-functions---built-in-functions---attribute--"></a> -### attribute -> -should access attribute of an object. - -```js -twig({data: '{{ attribute(obj, key) }}' }).render({ - obj: { name: "Twig.js"}, - key: "name" -}) -.should.equal("Twig.js"); -``` - -should call function of attribute of an object. - -```js -twig({data: '{{ attribute(obj, key, params) }}' }).render({ - obj: { - name: function(first, last) { - return first+'.'+last; - } - }, - key: "name", - params: ['Twig', 'js'] - }) - .should.equal("Twig.js"); -``` - -should return undefined for missing attribute of an object. - -```js -twig({data: '{{ attribute(obj, key, params) }}' }).render({ - obj: { - name: function(first, last) { - return first+'.'+last; - } - }, - key: "missing", - params: ['Twig', 'js'] - }) - .should.equal(""); -``` - -should return element of an array. - -```js -twig({data: '{{ attribute(arr, 0) }}' }).render({ - arr: ['Twig', 'js'] - }) - .should.equal("Twig"); -``` - -should return undef for array beyond index size. - -```js -twig({data: '{{ attribute(arr, 100) }}' }).render({ - arr: ['Twig', 'js'] - }) - .should.equal(""); -``` - -<a name="twigjs-functions---built-in-functions---template_from_string--"></a> -### template_from_string -> -should load a template from a string. - -```js -twig({data: '{% include template_from_string("{{ value }}") %}'}).render({ - value: 'test' -}) -.should.equal('test'); -``` - -should load a template from a variable. - -```js -twig({data: '{% include template_from_string(template) %}'}).render({ - template: '{{ value }}', - value: 'test' -}) -.should.equal('test'); -``` - -<a name="twigjs-functions---built-in-functions---random--"></a> -### random -> -should return a random item from a traversable or array. - -```js -var arr = "bcdefghij".split(""); -for (var i = 1; i <= 1000; i++) { - arr.should.containEql(twig({data: '{{ random(arr) }}'}).render({arr: arr})); -} -``` - -should return a random character from a string. - -```js -var str = "abcdefghij"; -for (var i = 1; i <= 1000; i++) { - str.should.containEql(twig({data: '{{ random(str) }}'}).render({str: str})); -} -``` - -should return a random integer between 0 and the integer parameter. - -```js -for (var i = 1; i <= 1000; i++) { - twig({data: '{{ random(10) }}'}).render().should.be.within(0, 10); -} -``` - -should return a random integer between 0 and 2147483647 when no parameters are passed. - -```js -for (var i = 1; i <= 1000; i++) { - twig({data: '{{ random() }}'}).render().should.be.within(0, 2147483647); -} -``` - -<a name="twigjs-functions---built-in-functions---min-max--"></a> -### min, max -> -should support the 'min' function. - -```js -twig({data: '{{ min(2, 1, 3, 5, 4) }}'}).render().should.equal('1'); -twig({data: '{{ min([2, 1, 3, 5, 4]) }}'}).render().should.equal('1'); -twig({data: '{{ min({2:"two", 1:"one", 3:"three", 5:"five", 4:"four"}) }}'}).render().should.equal('five'); -``` - -should support the 'max' function. - -```js -twig({data: '{{ max([2, 1, 3, 5, 4]) }}'}).render().should.equal('5'); -twig({data: '{{ max(2, 1, 3, 5, 4) }}'}).render().should.equal('5'); -twig({data: '{{ max({2:"two", 1:"one", 3:"three", 5:"five", 4:"four"}) }}'}).render().should.equal('two'); -``` - -<a name="twigjs-loaders--"></a> -# Twig.js Loaders -> -<a name="twigjs-loaders---custom-loader--"></a> -## custom loader -> -should define a custom loader. - -```js -Twig.extend(function(Twig) { - var obj = { - templates: { - 'custom_loader_block': '{% block main %}This lets you {% block data %}use blocks{% endblock data %}{% endblock main %}', - 'custom_loader_simple': 'the value is: {{ value }}', - 'custom_loader_include': 'include others from the same loader method - {% include "custom_loader_simple" %}', - 'custom_loader_complex': '{% extends "custom_loader_block" %} {% block data %}extend other templates and {% include "custom_loader_include" %}{% endblock data %}' - }, - loader: function(location, params, callback, error_callback) { - params.data = this.templates[location]; - params.allowInlineIncludes = true; - var template = new Twig.Template(params); - if (typeof callback === 'function') { - callback(template); - } - return template; - } - }; - Twig.Templates.registerLoader('custom', obj.loader, obj); - Twig.Templates.loaders.should.have.property('custom'); -}); -``` - -should load a simple template from a custom loader. - -```js -twig({ - method: 'custom', - name: 'custom_loader_simple' -}).render({value: 'test succeeded'}).should.equal('the value is: test succeeded'); -``` - -should load a template that includes another from a custom loader. - -```js -twig({ - method: 'custom', - name: 'custom_loader_include' -}).render({value: 'test succeeded'}).should.equal('include others from the same loader method - the value is: test succeeded'); -``` - -should load a template that extends another from a custom loader. - -```js -twig({ - method: 'custom', - name: 'custom_loader_complex' -}).render({value: 'test succeeded'}).should.equal('This lets you extend other templates and include others from the same loader method - the value is: test succeeded'); -``` - -should remove a registered loader. - -```js -Twig.extend(function(Twig) { - Twig.Templates.unRegisterLoader('custom'); - Twig.Templates.loaders.should.not.have.property('custom'); -}); -``` - -<a name="twigjs-macro--"></a> -# Twig.js Macro -> -it should load macro. - -```js -twig({ - id: 'macro', - path: 'test/templates/macro.twig', - async: false -}); -// Load the template -twig({ref: 'macro'}).render({ }).should.equal( '' ); -``` - -it should import macro. - -```js -twig({ - id: 'import-macro', - path: 'test/templates/import.twig', - async: false -}); -// Load the template -twig({ref: 'import-macro'}).render({ }).trim().should.equal( "Hello World" ); -``` - -it should run macro with self reference. - -```js -twig({ - id: 'import-macro-self', - path: 'test/templates/macro-self.twig', - async: false -}); -// Load the template -twig({ref: 'import-macro-self'}).render({ }).trim().should.equal( '<p><input type="text" name="username" value="" size="20" /></p>' ); -``` - -it should run wrapped macro with self reference. - -```js -twig({ - id: 'import-wrapped-macro-self', - path: 'test/templates/macro-wrapped.twig', - async: false -}); -// Load the template -twig({ref: 'import-wrapped-macro-self'}).render({ }).trim().should.equal( '<p><div class="field"><input type="text" name="username" value="" size="20" /></div></p>' ); -``` - -it should run wrapped macro with context and self reference. - -```js -twig({ - id: 'import-macro-context-self', - path: 'test/templates/macro-context.twig', - async: false -}); -// Load the template -twig({ref: 'import-macro-context-self'}).render({ 'greetings': 'Howdy' }).trim().should.equal( 'Howdy Twigjs' ); -``` - -it should run wrapped macro inside blocks. - -```js -twig({ - id: 'import-macro-inside-block', - path: 'test/templates/macro-blocks.twig', - async: false -}); -// Load the template -twig({ref: 'import-macro-inside-block'}).render({ }).trim().should.equal( 'Welcome <div class="name">Twig Js</div>' ); -``` - -it should import selected macros from template. - -```js -twig({ - id: 'from-macro-import', - path: 'test/templates/from.twig', - async: false -}); -// Load the template -twig({ref: 'from-macro-import'}).render({ }).trim().should.equal( 'Twig.js<div class="field"><input type="text" name="text" value="" size="20" /></div><div class="field red"><input type="text" name="password" value="" size="20" /></div>' ); -``` - -should support inline includes by ID. - -```js -twig({ - id: 'hello', - data: '{% macro echo(name) %}Hello {{ name }}{% endmacro %}' -}); -var template = twig({ - allowInlineIncludes: true, - data: 'template with {% from "hello" import echo %}{{ echo("Twig.js") }}' - }), - output = template.render() -output.should.equal("template with Twig.js"); -``` - -<a name="twigjs-namespaces--"></a> -# Twig.js Namespaces -> -should support namespaces defined with ::. - -```js -twig({ - namespaces: { 'test': 'test/templates/namespaces/' }, - path: 'test/templates/namespaces_::.twig', - load: function(template) { - // Render the template - template.render({ - test: "yes", - flag: true - }).should.equal("namespaces"); - - done(); - } - }); -``` - -should support namespaces defined with @. - -```js -twig({ - namespaces: { 'test': 'test/templates/namespaces/' }, - path: 'test/templates/namespaces_@.twig', - load: function(template) { - // Render the template - template.render({ - test: "yes", - flag: true - }).should.equal("namespaces"); - - done(); - } - }); -``` - -<a name="twigjs-optional-functionality--"></a> -# Twig.js Optional Functionality -> -should support inline includes by ID. - -```js -twig({ - id: 'other', - data: 'another template' -}); -var template = twig({ - allowInlineIncludes: true, - data: 'template with {% include "other" %}' - }), - output = template.render() -output.should.equal("template with another template"); -``` - -<a name="twigjs-parsers--"></a> -# Twig.js Parsers -> -<a name="twigjs-parsers---custom-parser--"></a> -## custom parser -> -should define a custom parser. - -```js -Twig.extend(function(Twig) { - var parser = function(params) { - return '[CUSTOM PARSER] ' + params.data; - }; - Twig.Templates.registerParser('custom', parser); - Twig.Templates.parsers.should.have.property('custom'); -}); -``` - -should run the data through the custom parser. - -```js -Twig.extend(function(Twig) { - var params = { - data: 'This is a test template.' - }; - var template = Twig.Templates.parsers.custom(params); - template.should.equal('[CUSTOM PARSER] This is a test template.'); -}); -``` - -should remove a registered parser. - -```js -Twig.extend(function(Twig) { - Twig.Templates.unRegisterParser('custom'); - Twig.Templates.parsers.should.not.have.property('custom'); -}); -``` - -<a name="twigjs-path--"></a> -# Twig.js Path -> -<a name="twigjs-path---relativepath--"></a> -## relativePath -> -should throw an error if trying to get a relative path in an inline template. - -```js -(function () { - relativePath({}); -}).should.throw("Cannot extend an inline template."); -``` - -should give the full path to a file when file is passed. - -```js -relativePath({ url: "http://www.test.com/test.twig"}, "templates/myFile.twig").should.equal("http://www.test.com/templates/myFile.twig"); -relativePath({ path: "test/test.twig"}, "templates/myFile.twig").should.equal("test/templates/myFile.twig"); -``` - -should ascend directories. - -```js -relativePath({ url: "http://www.test.com/templates/../test.twig"}, "myFile.twig").should.equal("http://www.test.com/myFile.twig"); -relativePath({ path: "test/templates/../test.twig"}, "myFile.twig").should.equal("test/myFile.twig"); -``` - -should respect relative directories. - -```js -relativePath({ url: "http://www.test.com/templates/./test.twig"}, "myFile.twig").should.equal("http://www.test.com/templates/myFile.twig"); -relativePath({ path: "test/templates/./test.twig"}, "myFile.twig").should.equal("test/templates/myFile.twig"); -``` - -<a name="twigjs-path---relativepath---url--"></a> -### url -> -should use the url if no base is specified. - -```js -relativePath({ url: "http://www.test.com/test.twig"}).should.equal("http://www.test.com/"); -``` - -should use the base if base is specified. - -```js -relativePath({ url: "http://www.test.com/test.twig", base: "myTest" }).should.equal("myTest/"); -``` - -<a name="twigjs-path---relativepath---path--"></a> -### path -> -should use the path if no base is specified. - -```js -relativePath({ path: "test/test.twig"}).should.equal("test/"); -``` - -should use the base if base is specified. - -```js -relativePath({ path: "test/test.twig", base: "myTest" }).should.equal("myTest/"); -``` - -<a name="twigjs-path---parsepath--"></a> -## parsePath -> -should fall back to relativePath if the template has no namespaces defined. - -```js -var relativePathStub = sinon.stub(Twig.path, "relativePath"); -parsePath({ options: {} }); -relativePathStub.should.have.been.called; -``` - -<a name="twigjs-regression-tests--"></a> -# Twig.js Regression Tests -> -#47 should not match variables starting with not. - -```js -// Define and save a template -twig({data: '{% for note in notes %}{{note}}{% endfor %}'}).render({notes:['a', 'b', 'c']}).should.equal("abc"); -``` - -#56 functions work inside parentheses. - -```js -// Define and save a template -Twig.extendFunction('custom', function(value) { - return true; -}); -twig({data: '{% if (custom("val") and custom("val")) %}out{% endif %}'}).render({}).should.equal("out"); -``` - -#83 Support for trailing commas in arrays. - -```js -twig({data: '{{ [1,2,3,4,] }}'}).render().should.equal("1,2,3,4"); -``` - -#83 Support for trailing commas in objects. - -```js -twig({data: '{{ {a:1, b:2, c:3, } }}'}).render(); -``` - -#283 should support quotes between raw tags. - -```js -twig({data: '{% raw %}\n"\n{% endraw %}'}).render().should.equal('"'); -twig({data: "{% raw %}\n'\n{% endraw %}"}).render().should.equal("'"); -``` - -<a name="twigjs-tags--"></a> -# Twig.js Tags -> -should support spaceless. - -```js -twig({ - data: "{% spaceless %}<div>\n <b>b</b> <i>i</i>\n</div>{% endspaceless %}" -}).render().should.equal( - "<div><b>b</b><i>i</i></div>" -); -``` - -<a name="twigjs-tests--"></a> -# Twig.js Tests -> -<a name="twigjs-tests---empty-test--"></a> -## empty test -> -should identify numbers as not empty. - -```js -// number -twig({data: '{{ 1 is empty }}'}).render().should.equal("false" ); -twig({data: '{{ 0 is empty }}'}).render().should.equal("false" ); -``` - -should identify empty strings. - -```js -// String -twig({data: '{{ "" is empty }}'}).render().should.equal("true" ); -twig({data: '{{ "test" is empty }}'}).render().should.equal("false" ); -``` - -should identify empty arrays. - -```js -// Array -twig({data: '{{ [] is empty }}'}).render().should.equal("true" ); -twig({data: '{{ ["1"] is empty }}'}).render().should.equal("false" ); -``` - -should identify empty objects. - -```js -// Object -twig({data: '{{ {} is empty }}'}).render().should.equal("true" ); -twig({data: '{{ {"a":"b"} is empty }}'}).render().should.equal("false" ); -twig({data: '{{ {"a":"b"} is not empty }}'}).render().should.equal("true" ); -``` - -<a name="twigjs-tests---odd-test--"></a> -## odd test -> -should identify a number as odd. - -```js -twig({data: '{{ (1 + 4) is odd }}'}).render().should.equal("true" ); -twig({data: '{{ 6 is odd }}'}).render().should.equal("false" ); -``` - -<a name="twigjs-tests---even-test--"></a> -## even test -> -should identify a number as even. - -```js -twig({data: '{{ (1 + 4) is even }}'}).render().should.equal("false" ); -twig({data: '{{ 6 is even }}'}).render().should.equal("true" ); -``` - -<a name="twigjs-tests---divisibleby-test--"></a> -## divisibleby test -> -should determine if a number is divisible by the given number. - -```js -twig({data: '{{ 5 is divisibleby(3) }}'}).render().should.equal("false" ); -twig({data: '{{ 6 is divisibleby(3) }}'}).render().should.equal("true" ); -``` - -<a name="twigjs-tests---defined-test--"></a> -## defined test -> -should identify a key as defined if it exists in the render context. - -```js -twig({data: '{{ key is defined }}'}).render().should.equal("false" ); -twig({data: '{{ key is defined }}'}).render({key: "test"}).should.equal( "true" ); -var context = { - key: { - foo: "bar", - nothing: null - }, - nothing: null -}; -twig({data: '{{ key.foo is defined }}'}).render(context).should.equal( "true" ); -twig({data: '{{ key.bar is defined }}'}).render(context).should.equal( "false" ); -twig({data: '{{ key.foo.bar is defined }}'}).render(context).should.equal( "false" ); -twig({data: '{{ foo.bar is defined }}'}).render(context).should.equal( "false" ); -twig({data: '{{ nothing is defined }}'}).render(context).should.equal( "true" ); -twig({data: '{{ key.nothing is defined }}'}).render(context).should.equal( "true" ); -``` - -<a name="twigjs-tests---none-test--"></a> -## none test -> -should identify a key as none if it exists in the render context and is null. - -```js -twig({data: '{{ key is none }}'}).render().should.equal("false"); -twig({data: '{{ key is none }}'}).render({key: "test"}).should.equal("false"); -twig({data: '{{ key is none }}'}).render({key: null}).should.equal("true"); -twig({data: '{{ key is null }}'}).render({key: null}).should.equal("true"); -``` - -<a name="twigjs-tests---sameas-test--"></a> -## sameas test -> -should identify the exact same type as true. - -```js -twig({data: '{{ true is sameas(true) }}'}).render().should.equal("true"); -twig({data: '{{ a is sameas(1) }}'}).render({a: 1}).should.equal("true"); -twig({data: '{{ a is sameas("test") }}'}).render({a: "test"}).should.equal("true"); -twig({data: '{{ a is sameas(true) }}'}).render({a: true}).should.equal("true"); -``` - -should identify the different types as false. - -```js -twig({data: '{{ false is sameas(true) }}'}).render().should.equal("false"); -twig({data: '{{ true is sameas(1) }}'}).render().should.equal("false"); -twig({data: '{{ false is sameas("") }}'}).render().should.equal("false"); -twig({data: '{{ a is sameas(1) }}'}).render({a: "1"}).should.equal("false"); -``` - -<a name="twigjs-tests---iterable-test--"></a> -## iterable test -> -should fail on non-iterable data types. - -```js -twig({data: "{{ val is iterable ? 'ok' : 'ko' }}"}).render(data).should.equal("ko"); -twig({data: "{{ val is iterable ? 'ok' : 'ko' }}"}).render({val: null}).should.equal("ko"); -twig({data: "{{ val is iterable ? 'ok' : 'ko' }}"}).render({}).should.equal("ko"); -``` - -should pass on iterable data types. - -```js -twig({data: "{{ foo is iterable ? 'ok' : 'ko' }}"}).render(data).should.equal("ok"); -twig({data: "{{ obj is iterable ? 'ok' : 'ko' }}"}).render(data).should.equal("ok"); -``` - diff --git a/node_modules/twig/docs/twig.html b/node_modules/twig/docs/twig.html deleted file mode 100644 index 687abbd..0000000 --- a/node_modules/twig/docs/twig.html +++ /dev/null @@ -1,11250 +0,0 @@ -<!DOCTYPE html> - -<html> -<head> - <title>twig.js</title> - <meta http-equiv="content-type" content="text/html; charset=UTF-8"> - <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"> - <link rel="stylesheet" media="all" href="docco.css" /> -</head> -<body> - <div id="container"> - <div id="background"></div> - - <ul class="sections"> - - <li id="title"> - <div class="annotation"> - <h1>twig.js</h1> - </div> - </li> - - - - <li id="section-1"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-1">¶</a> - </div> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-comment">/** - * Twig.js 0.8.9 - * - * @copyright 2011-2015 John Roepke and the Twig.js Contributors - * @license Available under the BSD 2-Clause License - * @link https://github.com/justjohn/twig.js - */</span> - -<span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ - - Twig.VERSION = <span class="hljs-string">"0.8.9"</span>; - - <span class="hljs-keyword">return</span> Twig; -})(Twig || {});</pre></div></div> - - </li> - - - <li id="section-2"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-2">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - <div class="content"><div class='highlight'><pre> -<span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> "use strict"</span>;</pre></div></div> - - </li> - - - <li id="section-3"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-3">¶</a> - </div> - <h2 id="twig-core-js">twig.core.js</h2> -<p>This file handles template level tokenizing, compiling and parsing.</p> - - </div> - - <div class="content"><div class='highlight'><pre> - Twig.trace = <span class="hljs-literal">false</span>; - Twig.debug = <span class="hljs-literal">false</span>;</pre></div></div> - - </li> - - - <li id="section-4"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-4">¶</a> - </div> - <p>Default caching to true for the improved performance it offers</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.cache = <span class="hljs-literal">true</span>; - - Twig.placeholders = { - parent: <span class="hljs-string">"{{|PARENT|}}"</span> - }; - - <span class="hljs-comment">/** - * Fallback for Array.indexOf for IE8 et al - */</span> - Twig.indexOf = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">arr, searchElement <span class="hljs-comment">/*, fromIndex */</span> </span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Array</span>.prototype.hasOwnProperty(<span class="hljs-string">"indexOf"</span>)) { - <span class="hljs-keyword">return</span> arr.indexOf(searchElement); - } - <span class="hljs-keyword">if</span> (arr === <span class="hljs-keyword">void</span> <span class="hljs-number">0</span> || arr === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(); - } - <span class="hljs-keyword">var</span> t = <span class="hljs-built_in">Object</span>(arr); - <span class="hljs-keyword">var</span> len = t.length >>> <span class="hljs-number">0</span>; - <span class="hljs-keyword">if</span> (len === <span class="hljs-number">0</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } - <span class="hljs-keyword">var</span> n = <span class="hljs-number">0</span>; - <span class="hljs-keyword">if</span> (<span class="hljs-built_in">arguments</span>.length > <span class="hljs-number">0</span>) { - n = <span class="hljs-built_in">Number</span>(<span class="hljs-built_in">arguments</span>[<span class="hljs-number">1</span>]); - <span class="hljs-keyword">if</span> (n !== n) { <span class="hljs-comment">// shortcut for verifying if it's NaN</span> - n = <span class="hljs-number">0</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (n !== <span class="hljs-number">0</span> && n !== <span class="hljs-literal">Infinity</span> && n !== -<span class="hljs-literal">Infinity</span>) { - n = (n > <span class="hljs-number">0</span> || <span class="hljs-number">-1</span>) * <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.abs(n)); - } - } - <span class="hljs-keyword">if</span> (n >= len) {</pre></div></div> - - </li> - - - <li id="section-5"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-5">¶</a> - </div> - <p>console.log(“indexOf not found1 “, JSON.stringify(searchElement), JSON.stringify(arr));</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } - <span class="hljs-keyword">var</span> k = n >= <span class="hljs-number">0</span> ? n : <span class="hljs-built_in">Math</span>.max(len - <span class="hljs-built_in">Math</span>.abs(n), <span class="hljs-number">0</span>); - <span class="hljs-keyword">for</span> (; k < len; k++) { - <span class="hljs-keyword">if</span> (k <span class="hljs-keyword">in</span> t && t[k] === searchElement) { - <span class="hljs-keyword">return</span> k; - } - } - <span class="hljs-keyword">if</span> (arr == searchElement) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - }</pre></div></div> - - </li> - - - <li id="section-6"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-6">¶</a> - </div> - <p>console.log(“indexOf not found2 “, JSON.stringify(searchElement), JSON.stringify(arr));</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } - - Twig.forEach = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">arr, callback, thisArg</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Array</span>.prototype.forEach ) { - <span class="hljs-keyword">return</span> arr.forEach(callback, thisArg); - } - - <span class="hljs-keyword">var</span> T, k; - - <span class="hljs-keyword">if</span> ( arr == <span class="hljs-literal">null</span> ) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>( <span class="hljs-string">" this is null or not defined"</span> ); - }</pre></div></div> - - </li> - - - <li id="section-7"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-7">¶</a> - </div> - <ol> -<li>Let O be the result of calling ToObject passing the |this| value as the argument.</li> -</ol> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> O = <span class="hljs-built_in">Object</span>(arr);</pre></div></div> - - </li> - - - <li id="section-8"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-8">¶</a> - </div> - <ol> -<li>Let lenValue be the result of calling the Get internal method of O with the argument “length”.</li> -<li>Let len be ToUint32(lenValue).</li> -</ol> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> len = O.length >>> <span class="hljs-number">0</span>; <span class="hljs-comment">// Hack to convert O.length to a UInt32</span></pre></div></div> - - </li> - - - <li id="section-9"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-9">¶</a> - </div> - <ol> -<li>If IsCallable(callback) is false, throw a TypeError exception. -See: <a href="http://es5.github.com/#x9.11">http://es5.github.com/#x9.11</a></li> -</ol> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> ( {}.toString.call(callback) != <span class="hljs-string">"[object Function]"</span> ) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>( callback + <span class="hljs-string">" is not a function"</span> ); - }</pre></div></div> - - </li> - - - <li id="section-10"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-10">¶</a> - </div> - <ol> -<li>If thisArg was supplied, let T be thisArg; else let T be undefined.</li> -</ol> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> ( thisArg ) { - T = thisArg; - }</pre></div></div> - - </li> - - - <li id="section-11"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-11">¶</a> - </div> - <ol> -<li>Let k be 0</li> -</ol> - - </div> - - <div class="content"><div class='highlight'><pre> k = <span class="hljs-number">0</span>;</pre></div></div> - - </li> - - - <li id="section-12"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-12">¶</a> - </div> - <ol> -<li>Repeat, while k < len</li> -</ol> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span>( k < len ) { - - <span class="hljs-keyword">var</span> kValue;</pre></div></div> - - </li> - - - <li id="section-13"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-13">¶</a> - </div> - <p>a. Let Pk be ToString(k). - This is implicit for LHS operands of the in operator -b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. - This step can be combined with c -c. If kPresent is true, then</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> ( k <span class="hljs-keyword">in</span> O ) {</pre></div></div> - - </li> - - - <li id="section-14"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-14">¶</a> - </div> - <p>i. Let kValue be the result of calling the Get internal method of O with argument Pk.</p> - - </div> - - <div class="content"><div class='highlight'><pre> kValue = O[ k ];</pre></div></div> - - </li> - - - <li id="section-15"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-15">¶</a> - </div> - <p>ii. Call the Call internal method of callback with T as the this value and -argument list containing kValue, k, and O.</p> - - </div> - - <div class="content"><div class='highlight'><pre> callback.call( T, kValue, k, O ); - }</pre></div></div> - - </li> - - - <li id="section-16"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-16">¶</a> - </div> - <p>d. Increase k by 1.</p> - - </div> - - <div class="content"><div class='highlight'><pre> k++; - }</pre></div></div> - - </li> - - - <li id="section-17"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-17">¶</a> - </div> - <ol> -<li>return undefined</li> -</ol> - - </div> - - <div class="content"><div class='highlight'><pre> }; - - Twig.merge = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">target, source, onlyChanged</span>) </span>{ - Twig.forEach(<span class="hljs-built_in">Object</span>.keys(source), <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">key</span>) </span>{ - <span class="hljs-keyword">if</span> (onlyChanged && !(key <span class="hljs-keyword">in</span> target)) { - <span class="hljs-keyword">return</span>; - } - - target[key] = source[key] - }); - - <span class="hljs-keyword">return</span> target; - }; - - <span class="hljs-comment">/** - * Exception thrown by twig.js. - */</span> - Twig.Error = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">message</span>) </span>{ - <span class="hljs-keyword">this</span>.message = message; - <span class="hljs-keyword">this</span>.name = <span class="hljs-string">"TwigException"</span>; - <span class="hljs-keyword">this</span>.type = <span class="hljs-string">"TwigException"</span>; - }; - - <span class="hljs-comment">/** - * Get the string representation of a Twig error. - */</span> - Twig.Error.prototype.toString = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">var</span> output = <span class="hljs-keyword">this</span>.name + <span class="hljs-string">": "</span> + <span class="hljs-keyword">this</span>.message; - - <span class="hljs-keyword">return</span> output; - }; - - <span class="hljs-comment">/** - * Wrapper for logging to the console. - */</span> - Twig.log = { - trace: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{<span class="hljs-keyword">if</span> (Twig.trace && <span class="hljs-built_in">console</span>) {<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Array</span>.prototype.slice.call(<span class="hljs-built_in">arguments</span>));}}, - debug: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{<span class="hljs-keyword">if</span> (Twig.debug && <span class="hljs-built_in">console</span>) {<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Array</span>.prototype.slice.call(<span class="hljs-built_in">arguments</span>));}} - }; - - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">console</span> !== <span class="hljs-string">"undefined"</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">console</span>.error !== <span class="hljs-string">"undefined"</span>) { - Twig.log.error = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-built_in">console</span>.error.apply(<span class="hljs-built_in">console</span>, <span class="hljs-built_in">arguments</span>); - } - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">console</span>.log !== <span class="hljs-string">"undefined"</span>) { - Twig.log.error = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-built_in">console</span>.log.apply(<span class="hljs-built_in">console</span>, <span class="hljs-built_in">arguments</span>); - } - } - } <span class="hljs-keyword">else</span> { - Twig.log.error = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>)</span>{}; - } - - <span class="hljs-comment">/** - * Wrapper for child context objects in Twig. - * - * @param {Object} context Values to initialize the context with. - */</span> - Twig.ChildContext = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">context</span>) </span>{ - <span class="hljs-keyword">var</span> ChildContext = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">ChildContext</span>(<span class="hljs-params"></span>) </span>{}; - ChildContext.prototype = context; - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ChildContext(); - }; - - <span class="hljs-comment">/** - * Container for methods related to handling high level template tokens - * (for example: {{ expression }}, {% logic %}, {# comment #}, raw data) - */</span> - Twig.token = {}; - - <span class="hljs-comment">/** - * Token types. - */</span> - Twig.token.type = { - output: <span class="hljs-string">'output'</span>, - logic: <span class="hljs-string">'logic'</span>, - comment: <span class="hljs-string">'comment'</span>, - raw: <span class="hljs-string">'raw'</span>, - output_whitespace_pre: <span class="hljs-string">'output_whitespace_pre'</span>, - output_whitespace_post: <span class="hljs-string">'output_whitespace_post'</span>, - output_whitespace_both: <span class="hljs-string">'output_whitespace_both'</span>, - logic_whitespace_pre: <span class="hljs-string">'logic_whitespace_pre'</span>, - logic_whitespace_post: <span class="hljs-string">'logic_whitespace_post'</span>, - logic_whitespace_both: <span class="hljs-string">'logic_whitespace_both'</span> - }; - - <span class="hljs-comment">/** - * Token syntax definitions. - */</span> - Twig.token.definitions = [ - { - type: Twig.token.type.raw, - open: <span class="hljs-string">'{% raw %}'</span>, - close: <span class="hljs-string">'{% endraw %}'</span> - }, - { - type: Twig.token.type.raw, - open: <span class="hljs-string">'{% verbatim %}'</span>, - close: <span class="hljs-string">'{% endverbatim %}'</span> - },</pre></div></div> - - </li> - - - <li id="section-18"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-18">¶</a> - </div> - <p><em>Whitespace type tokens</em></p> -<p>These typically take the form <code>{{- expression -}}</code> or <code>{{- expression }}</code> or <code>{{ expression -}}</code>.</p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.token.type.output_whitespace_pre, - open: <span class="hljs-string">'{{-'</span>, - close: <span class="hljs-string">'}}'</span> - }, - { - type: Twig.token.type.output_whitespace_post, - open: <span class="hljs-string">'{{'</span>, - close: <span class="hljs-string">'-}}'</span> - }, - { - type: Twig.token.type.output_whitespace_both, - open: <span class="hljs-string">'{{-'</span>, - close: <span class="hljs-string">'-}}'</span> - }, - { - type: Twig.token.type.logic_whitespace_pre, - open: <span class="hljs-string">'{%-'</span>, - close: <span class="hljs-string">'%}'</span> - }, - { - type: Twig.token.type.logic_whitespace_post, - open: <span class="hljs-string">'{%'</span>, - close: <span class="hljs-string">'-%}'</span> - }, - { - type: Twig.token.type.logic_whitespace_both, - open: <span class="hljs-string">'{%-'</span>, - close: <span class="hljs-string">'-%}'</span> - },</pre></div></div> - - </li> - - - <li id="section-19"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-19">¶</a> - </div> - <p><em>Output type tokens</em></p> -<p>These typically take the form <code>{{ expression }}</code>.</p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.token.type.output, - open: <span class="hljs-string">'{{'</span>, - close: <span class="hljs-string">'}}'</span> - },</pre></div></div> - - </li> - - - <li id="section-20"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-20">¶</a> - </div> - <p><em>Logic type tokens</em></p> -<p>These typically take a form like <code>{% if expression %}</code> or <code>{% endif %}</code></p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.token.type.logic, - open: <span class="hljs-string">'{%'</span>, - close: <span class="hljs-string">'%}'</span> - },</pre></div></div> - - </li> - - - <li id="section-21"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-21">¶</a> - </div> - <p><em>Comment type tokens</em></p> -<p>These take the form <code>{# anything #}</code></p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.token.type.comment, - open: <span class="hljs-string">'{#'</span>, - close: <span class="hljs-string">'#}'</span> - } - ]; - - - <span class="hljs-comment">/** - * What characters start "strings" in token definitions. We need this to ignore token close - * strings inside an expression. - */</span> - Twig.token.strings = [<span class="hljs-string">'"'</span>, <span class="hljs-string">"'"</span>]; - - Twig.token.findStart = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">template</span>) </span>{ - <span class="hljs-keyword">var</span> output = { - position: <span class="hljs-literal">null</span>, - close_position: <span class="hljs-literal">null</span>, - def: <span class="hljs-literal">null</span> - }, - i, - token_template, - first_key_position, - close_key_position; - - <span class="hljs-keyword">for</span> (i=<span class="hljs-number">0</span>;i<Twig.token.definitions.length;i++) { - token_template = Twig.token.definitions[i]; - first_key_position = template.indexOf(token_template.open); - close_key_position = template.indexOf(token_template.close); - - Twig.log.trace(<span class="hljs-string">"Twig.token.findStart: "</span>, <span class="hljs-string">"Searching for "</span>, token_template.open, <span class="hljs-string">" found at "</span>, first_key_position);</pre></div></div> - - </li> - - - <li id="section-22"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-22">¶</a> - </div> - <p>Special handling for mismatched tokens</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (first_key_position >= <span class="hljs-number">0</span>) {</pre></div></div> - - </li> - - - <li id="section-23"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-23">¶</a> - </div> - <p>This token matches the template</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (token_template.open.length !== token_template.close.length) {</pre></div></div> - - </li> - - - <li id="section-24"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-24">¶</a> - </div> - <p>This token has mismatched closing and opening tags</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (close_key_position < <span class="hljs-number">0</span>) {</pre></div></div> - - </li> - - - <li id="section-25"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-25">¶</a> - </div> - <p>This token’s closing tag does not match the template</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">continue</span>; - } - } - }</pre></div></div> - - </li> - - - <li id="section-26"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-26">¶</a> - </div> - <p>Does this token occur before any other types?</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (first_key_position >= <span class="hljs-number">0</span> && (output.position === <span class="hljs-literal">null</span> || first_key_position < output.position)) { - output.position = first_key_position; - output.def = token_template; - output.close_position = close_key_position; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (first_key_position >= <span class="hljs-number">0</span> && output.position !== <span class="hljs-literal">null</span> && first_key_position === output.position) { - <span class="hljs-comment">/*This token exactly matches another token, - greedily match to check if this token has a greater specificity*/</span> - <span class="hljs-keyword">if</span> (token_template.open.length > output.def.open.length) {</pre></div></div> - - </li> - - - <li id="section-27"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-27">¶</a> - </div> - <p>This token’s opening tag is more specific than the previous match</p> - - </div> - - <div class="content"><div class='highlight'><pre> output.position = first_key_position; - output.def = token_template; - output.close_position = close_key_position; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (token_template.open.length === output.def.open.length) { - <span class="hljs-keyword">if</span> (token_template.close.length > output.def.close.length) {</pre></div></div> - - </li> - - - <li id="section-28"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-28">¶</a> - </div> - <p>This token’s opening tag is as specific as the previous match, -but the closing tag has greater specificity</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (close_key_position >= <span class="hljs-number">0</span> && close_key_position < output.close_position) {</pre></div></div> - - </li> - - - <li id="section-29"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-29">¶</a> - </div> - <p>This token’s closing tag exists in the template, -and it occurs sooner than the previous match</p> - - </div> - - <div class="content"><div class='highlight'><pre> output.position = first_key_position; - output.def = token_template; - output.close_position = close_key_position; - } - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (close_key_position >= <span class="hljs-number">0</span> && close_key_position < output.close_position) {</pre></div></div> - - </li> - - - <li id="section-30"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-30">¶</a> - </div> - <p>This token’s closing tag is not more specific than the previous match, -but it occurs sooner than the previous match</p> - - </div> - - <div class="content"><div class='highlight'><pre> output.position = first_key_position; - output.def = token_template; - output.close_position = close_key_position; - } - } - } - } - - <span class="hljs-keyword">delete</span> output[<span class="hljs-string">'close_position'</span>]; - - <span class="hljs-keyword">return</span> output; - }; - - Twig.token.findEnd = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">template, token_def, start</span>) </span>{ - <span class="hljs-keyword">var</span> end = <span class="hljs-literal">null</span>, - found = <span class="hljs-literal">false</span>, - offset = <span class="hljs-number">0</span>,</pre></div></div> - - </li> - - - <li id="section-31"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-31">¶</a> - </div> - <p>String position variables</p> - - </div> - - <div class="content"><div class='highlight'><pre> str_pos = <span class="hljs-literal">null</span>, - str_found = <span class="hljs-literal">null</span>, - pos = <span class="hljs-literal">null</span>, - end_offset = <span class="hljs-literal">null</span>, - this_str_pos = <span class="hljs-literal">null</span>, - end_str_pos = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-32"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-32">¶</a> - </div> - <p>For loop variables</p> - - </div> - - <div class="content"><div class='highlight'><pre> i, - l; - - <span class="hljs-keyword">while</span> (!found) { - str_pos = <span class="hljs-literal">null</span>; - str_found = <span class="hljs-literal">null</span>; - pos = template.indexOf(token_def.close, offset); - - <span class="hljs-keyword">if</span> (pos >= <span class="hljs-number">0</span>) { - end = pos; - found = <span class="hljs-literal">true</span>; - } <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-33"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-33">¶</a> - </div> - <p>throw an exception</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to find closing bracket '"</span> + token_def.close + - <span class="hljs-string">"'"</span> + <span class="hljs-string">" opened near template position "</span> + start); - }</pre></div></div> - - </li> - - - <li id="section-34"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-34">¶</a> - </div> - <p>Ignore quotes within comments; just look for the next comment close sequence, -regardless of what comes before it. <a href="https://github.com/justjohn/twig.js/issues/95">https://github.com/justjohn/twig.js/issues/95</a></p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (token_def.type === Twig.token.type.comment) { - <span class="hljs-keyword">break</span>; - }</pre></div></div> - - </li> - - - <li id="section-35"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-35">¶</a> - </div> - <p>Ignore quotes within raw tag -Fixes #283</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (token_def.type === Twig.token.type.raw) { - <span class="hljs-keyword">break</span>; - } - - l = Twig.token.strings.length; - <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < l; i += <span class="hljs-number">1</span>) { - this_str_pos = template.indexOf(Twig.token.strings[i], offset); - - <span class="hljs-keyword">if</span> (this_str_pos > <span class="hljs-number">0</span> && this_str_pos < pos && - (str_pos === <span class="hljs-literal">null</span> || this_str_pos < str_pos)) { - str_pos = this_str_pos; - str_found = Twig.token.strings[i]; - } - }</pre></div></div> - - </li> - - - <li id="section-36"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-36">¶</a> - </div> - <p>We found a string before the end of the token, now find the string’s end and set the search offset to it</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (str_pos !== <span class="hljs-literal">null</span>) { - end_offset = str_pos + <span class="hljs-number">1</span>; - end = <span class="hljs-literal">null</span>; - found = <span class="hljs-literal">false</span>; - <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) { - end_str_pos = template.indexOf(str_found, end_offset); - <span class="hljs-keyword">if</span> (end_str_pos < <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-string">"Unclosed string in template"</span>; - }</pre></div></div> - - </li> - - - <li id="section-37"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-37">¶</a> - </div> - <p>Ignore escaped quotes</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (template.substr(end_str_pos - <span class="hljs-number">1</span>, <span class="hljs-number">1</span>) !== <span class="hljs-string">"\\"</span>) { - offset = end_str_pos + <span class="hljs-number">1</span>; - <span class="hljs-keyword">break</span>; - } <span class="hljs-keyword">else</span> { - end_offset = end_str_pos + <span class="hljs-number">1</span>; - } - } - } - } - <span class="hljs-keyword">return</span> end; - }; - - <span class="hljs-comment">/** - * Convert a template into high-level tokens. - */</span> - Twig.tokenize = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">template</span>) </span>{ - <span class="hljs-keyword">var</span> tokens = [],</pre></div></div> - - </li> - - - <li id="section-38"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-38">¶</a> - </div> - <p>An offset for reporting errors locations in the template.</p> - - </div> - - <div class="content"><div class='highlight'><pre> error_offset = <span class="hljs-number">0</span>,</pre></div></div> - - </li> - - - <li id="section-39"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-39">¶</a> - </div> - <p>The start and type of the first token found in the template.</p> - - </div> - - <div class="content"><div class='highlight'><pre> found_token = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-40"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-40">¶</a> - </div> - <p>The end position of the matched token.</p> - - </div> - - <div class="content"><div class='highlight'><pre> end = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">while</span> (template.length > <span class="hljs-number">0</span>) {</pre></div></div> - - </li> - - - <li id="section-41"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-41">¶</a> - </div> - <p>Find the first occurance of any token type in the template</p> - - </div> - - <div class="content"><div class='highlight'><pre> found_token = Twig.token.findStart(template); - - Twig.log.trace(<span class="hljs-string">"Twig.tokenize: "</span>, <span class="hljs-string">"Found token: "</span>, found_token); - - <span class="hljs-keyword">if</span> (found_token.position !== <span class="hljs-literal">null</span>) {</pre></div></div> - - </li> - - - <li id="section-42"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-42">¶</a> - </div> - <p>Add a raw type token for anything before the start of the token</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (found_token.position > <span class="hljs-number">0</span>) { - tokens.push({ - type: Twig.token.type.raw, - value: template.substring(<span class="hljs-number">0</span>, found_token.position) - }); - } - template = template.substr(found_token.position + found_token.def.open.length); - error_offset += found_token.position + found_token.def.open.length;</pre></div></div> - - </li> - - - <li id="section-43"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-43">¶</a> - </div> - <p>Find the end of the token</p> - - </div> - - <div class="content"><div class='highlight'><pre> end = Twig.token.findEnd(template, found_token.def, error_offset); - - Twig.log.trace(<span class="hljs-string">"Twig.tokenize: "</span>, <span class="hljs-string">"Token ends at "</span>, end); - - tokens.push({ - type: found_token.def.type, - value: template.substring(<span class="hljs-number">0</span>, end).trim() - }); - - <span class="hljs-keyword">if</span> (template.substr( end + found_token.def.close.length, <span class="hljs-number">1</span> ) === <span class="hljs-string">"\n"</span>) { - <span class="hljs-keyword">switch</span> (found_token.def.type) { - <span class="hljs-keyword">case</span> <span class="hljs-string">"logic_whitespace_pre"</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">"logic_whitespace_post"</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">"logic_whitespace_both"</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">"logic"</span>:</pre></div></div> - - </li> - - - <li id="section-44"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-44">¶</a> - </div> - <p>Newlines directly after logic tokens are ignored</p> - - </div> - - <div class="content"><div class='highlight'><pre> end += <span class="hljs-number">1</span>; - <span class="hljs-keyword">break</span>; - } - } - - template = template.substr(end + found_token.def.close.length);</pre></div></div> - - </li> - - - <li id="section-45"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-45">¶</a> - </div> - <p>Increment the position in the template</p> - - </div> - - <div class="content"><div class='highlight'><pre> error_offset += end + found_token.def.close.length; - - } <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-46"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-46">¶</a> - </div> - <p>No more tokens -> add the rest of the template as a raw-type token</p> - - </div> - - <div class="content"><div class='highlight'><pre> tokens.push({ - type: Twig.token.type.raw, - value: template - }); - template = <span class="hljs-string">''</span>; - } - } - - <span class="hljs-keyword">return</span> tokens; - }; - - - Twig.compile = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">tokens</span>) </span>{ - <span class="hljs-keyword">try</span> {</pre></div></div> - - </li> - - - <li id="section-47"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-47">¶</a> - </div> - <p>Output and intermediate stacks</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> output = [], - stack = [],</pre></div></div> - - </li> - - - <li id="section-48"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-48">¶</a> - </div> - <p>The tokens between open and close tags</p> - - </div> - - <div class="content"><div class='highlight'><pre> intermediate_output = [], - - token = <span class="hljs-literal">null</span>, - logic_token = <span class="hljs-literal">null</span>, - unclosed_token = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-49"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-49">¶</a> - </div> - <p>Temporary previous token.</p> - - </div> - - <div class="content"><div class='highlight'><pre> prev_token = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-50"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-50">¶</a> - </div> - <p>Temporary previous output.</p> - - </div> - - <div class="content"><div class='highlight'><pre> prev_output = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-51"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-51">¶</a> - </div> - <p>Temporary previous intermediate output.</p> - - </div> - - <div class="content"><div class='highlight'><pre> prev_intermediate_output = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-52"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-52">¶</a> - </div> - <p>The previous token’s template</p> - - </div> - - <div class="content"><div class='highlight'><pre> prev_template = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-53"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-53">¶</a> - </div> - <p>Token lookahead</p> - - </div> - - <div class="content"><div class='highlight'><pre> next_token = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-54"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-54">¶</a> - </div> - <p>The output token</p> - - </div> - - <div class="content"><div class='highlight'><pre> tok_output = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-55"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-55">¶</a> - </div> - <p>Logic Token values</p> - - </div> - - <div class="content"><div class='highlight'><pre> type = <span class="hljs-literal">null</span>, - open = <span class="hljs-literal">null</span>, - next = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">var</span> compile_output = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token</span>) </span>{ - Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [token]); - <span class="hljs-keyword">if</span> (stack.length > <span class="hljs-number">0</span>) { - intermediate_output.push(token); - } <span class="hljs-keyword">else</span> { - output.push(token); - } - }; - - <span class="hljs-keyword">var</span> compile_logic = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-56"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-56">¶</a> - </div> - <p>Compile the logic token</p> - - </div> - - <div class="content"><div class='highlight'><pre> logic_token = Twig.logic.compile.apply(<span class="hljs-keyword">this</span>, [token]); - - type = logic_token.type; - open = Twig.logic.handler[type].open; - next = Twig.logic.handler[type].next; - - Twig.log.trace(<span class="hljs-string">"Twig.compile: "</span>, <span class="hljs-string">"Compiled logic token to "</span>, logic_token, - <span class="hljs-string">" next is: "</span>, next, <span class="hljs-string">" open is : "</span>, open);</pre></div></div> - - </li> - - - <li id="section-57"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-57">¶</a> - </div> - <p>Not a standalone token, check logic stack to see if this is expected</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (open !== <span class="hljs-literal">undefined</span> && !open) { - prev_token = stack.pop(); - prev_template = Twig.logic.handler[prev_token.type]; - - <span class="hljs-keyword">if</span> (Twig.indexOf(prev_template.next, type) < <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(type + <span class="hljs-string">" not expected after a "</span> + prev_token.type); - } - - prev_token.output = prev_token.output || []; - - prev_token.output = prev_token.output.concat(intermediate_output); - intermediate_output = []; - - tok_output = { - type: Twig.token.type.logic, - token: prev_token - }; - <span class="hljs-keyword">if</span> (stack.length > <span class="hljs-number">0</span>) { - intermediate_output.push(tok_output); - } <span class="hljs-keyword">else</span> { - output.push(tok_output); - } - }</pre></div></div> - - </li> - - - <li id="section-58"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-58">¶</a> - </div> - <p>This token requires additional tokens to complete the logic structure.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (next !== <span class="hljs-literal">undefined</span> && next.length > <span class="hljs-number">0</span>) { - Twig.log.trace(<span class="hljs-string">"Twig.compile: "</span>, <span class="hljs-string">"Pushing "</span>, logic_token, <span class="hljs-string">" to logic stack."</span>); - - <span class="hljs-keyword">if</span> (stack.length > <span class="hljs-number">0</span>) {</pre></div></div> - - </li> - - - <li id="section-59"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-59">¶</a> - </div> - <p>Put any currently held output into the output list of the logic operator -currently at the head of the stack before we push a new one on.</p> - - </div> - - <div class="content"><div class='highlight'><pre> prev_token = stack.pop(); - prev_token.output = prev_token.output || []; - prev_token.output = prev_token.output.concat(intermediate_output); - stack.push(prev_token); - intermediate_output = []; - }</pre></div></div> - - </li> - - - <li id="section-60"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-60">¶</a> - </div> - <p>Push the new logic token onto the logic stack</p> - - </div> - - <div class="content"><div class='highlight'><pre> stack.push(logic_token); - - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (open !== <span class="hljs-literal">undefined</span> && open) { - tok_output = { - type: Twig.token.type.logic, - token: logic_token - };</pre></div></div> - - </li> - - - <li id="section-61"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-61">¶</a> - </div> - <p>Standalone token (like {% set … %}</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (stack.length > <span class="hljs-number">0</span>) { - intermediate_output.push(tok_output); - } <span class="hljs-keyword">else</span> { - output.push(tok_output); - } - } - }; - - <span class="hljs-keyword">while</span> (tokens.length > <span class="hljs-number">0</span>) { - token = tokens.shift(); - prev_output = output[output.length - <span class="hljs-number">1</span>]; - prev_intermediate_output = intermediate_output[intermediate_output.length - <span class="hljs-number">1</span>]; - next_token = tokens[<span class="hljs-number">0</span>]; - Twig.log.trace(<span class="hljs-string">"Compiling token "</span>, token); - <span class="hljs-keyword">switch</span> (token.type) { - <span class="hljs-keyword">case</span> Twig.token.type.raw: - <span class="hljs-keyword">if</span> (stack.length > <span class="hljs-number">0</span>) { - intermediate_output.push(token); - } <span class="hljs-keyword">else</span> { - output.push(token); - } - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> Twig.token.type.logic: - compile_logic.call(<span class="hljs-keyword">this</span>, token); - <span class="hljs-keyword">break</span>;</pre></div></div> - - </li> - - - <li id="section-62"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-62">¶</a> - </div> - <p>Do nothing, comments should be ignored</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> Twig.token.type.comment: - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> Twig.token.type.output: - compile_output.call(<span class="hljs-keyword">this</span>, token); - <span class="hljs-keyword">break</span>;</pre></div></div> - - </li> - - - <li id="section-63"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-63">¶</a> - </div> - <p>Kill whitespace ahead and behind this token</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> Twig.token.type.logic_whitespace_pre: - <span class="hljs-keyword">case</span> Twig.token.type.logic_whitespace_post: - <span class="hljs-keyword">case</span> Twig.token.type.logic_whitespace_both: - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_pre: - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_post: - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_both: - <span class="hljs-keyword">if</span> (token.type !== Twig.token.type.output_whitespace_post && token.type !== Twig.token.type.logic_whitespace_post) { - <span class="hljs-keyword">if</span> (prev_output) {</pre></div></div> - - </li> - - - <li id="section-64"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-64">¶</a> - </div> - <p>If the previous output is raw, pop it off</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (prev_output.type === Twig.token.type.raw) { - output.pop();</pre></div></div> - - </li> - - - <li id="section-65"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-65">¶</a> - </div> - <p>If the previous output is not just whitespace, trim it</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (prev_output.value.match(<span class="hljs-regexp">/^\s*$/</span>) === <span class="hljs-literal">null</span>) { - prev_output.value = prev_output.value.trim();</pre></div></div> - - </li> - - - <li id="section-66"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-66">¶</a> - </div> - <p>Repush the previous output</p> - - </div> - - <div class="content"><div class='highlight'><pre> output.push(prev_output); - } - } - } - - <span class="hljs-keyword">if</span> (prev_intermediate_output) {</pre></div></div> - - </li> - - - <li id="section-67"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-67">¶</a> - </div> - <p>If the previous intermediate output is raw, pop it off</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (prev_intermediate_output.type === Twig.token.type.raw) { - intermediate_output.pop();</pre></div></div> - - </li> - - - <li id="section-68"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-68">¶</a> - </div> - <p>If the previous output is not just whitespace, trim it</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (prev_intermediate_output.value.match(<span class="hljs-regexp">/^\s*$/</span>) === <span class="hljs-literal">null</span>) { - prev_intermediate_output.value = prev_intermediate_output.value.trim();</pre></div></div> - - </li> - - - <li id="section-69"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-69">¶</a> - </div> - <p>Repush the previous intermediate output</p> - - </div> - - <div class="content"><div class='highlight'><pre> intermediate_output.push(prev_intermediate_output); - } - } - } - }</pre></div></div> - - </li> - - - <li id="section-70"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-70">¶</a> - </div> - <p>Compile this token</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">switch</span> (token.type) { - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_pre: - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_post: - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_both: - compile_output.call(<span class="hljs-keyword">this</span>, token); - <span class="hljs-keyword">break</span>; - <span class="hljs-keyword">case</span> Twig.token.type.logic_whitespace_pre: - <span class="hljs-keyword">case</span> Twig.token.type.logic_whitespace_post: - <span class="hljs-keyword">case</span> Twig.token.type.logic_whitespace_both: - compile_logic.call(<span class="hljs-keyword">this</span>, token); - <span class="hljs-keyword">break</span>; - } - - <span class="hljs-keyword">if</span> (token.type !== Twig.token.type.output_whitespace_pre && token.type !== Twig.token.type.logic_whitespace_pre) { - <span class="hljs-keyword">if</span> (next_token) {</pre></div></div> - - </li> - - - <li id="section-71"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-71">¶</a> - </div> - <p>If the next token is raw, shift it out</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (next_token.type === Twig.token.type.raw) { - tokens.shift();</pre></div></div> - - </li> - - - <li id="section-72"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-72">¶</a> - </div> - <p>If the next token is not just whitespace, trim it</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (next_token.value.match(<span class="hljs-regexp">/^\s*$/</span>) === <span class="hljs-literal">null</span>) { - next_token.value = next_token.value.trim();</pre></div></div> - - </li> - - - <li id="section-73"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-73">¶</a> - </div> - <p>Unshift the next token</p> - - </div> - - <div class="content"><div class='highlight'><pre> tokens.unshift(next_token); - } - } - } - } - - <span class="hljs-keyword">break</span>; - } - - Twig.log.trace(<span class="hljs-string">"Twig.compile: "</span>, <span class="hljs-string">" Output: "</span>, output, - <span class="hljs-string">" Logic Stack: "</span>, stack, - <span class="hljs-string">" Pending Output: "</span>, intermediate_output ); - }</pre></div></div> - - </li> - - - <li id="section-74"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-74">¶</a> - </div> - <p>Verify that there are no logic tokens left in the stack.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (stack.length > <span class="hljs-number">0</span>) { - unclosed_token = stack.pop(); - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"Unable to find an end tag for "</span> + unclosed_token.type + - <span class="hljs-string">", expecting one of "</span> + unclosed_token.next); - } - <span class="hljs-keyword">return</span> output; - } <span class="hljs-keyword">catch</span> (ex) { - Twig.log.error(<span class="hljs-string">"Error compiling twig template "</span> + <span class="hljs-keyword">this</span>.id + <span class="hljs-string">": "</span>); - <span class="hljs-keyword">if</span> (ex.stack) { - Twig.log.error(ex.stack); - } <span class="hljs-keyword">else</span> { - Twig.log.error(ex.toString()); - } - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.options.rethrow) <span class="hljs-keyword">throw</span> ex; - } - }; - - <span class="hljs-comment">/** - * Parse a compiled template. - * - * @param {Array} tokens The compiled tokens. - * @param {Object} context The render context. - * - * @return {string} The parsed template. - */</span> - Twig.parse = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">tokens, context</span>) </span>{ - <span class="hljs-keyword">try</span> { - <span class="hljs-keyword">var</span> output = [],</pre></div></div> - - </li> - - - <li id="section-75"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-75">¶</a> - </div> - <p>Track logic chains</p> - - </div> - - <div class="content"><div class='highlight'><pre> chain = <span class="hljs-literal">true</span>, - that = <span class="hljs-keyword">this</span>; - - Twig.forEach(tokens, <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">parseToken</span>(<span class="hljs-params">token</span>) </span>{ - Twig.log.debug(<span class="hljs-string">"Twig.parse: "</span>, <span class="hljs-string">"Parsing token: "</span>, token); - - <span class="hljs-keyword">switch</span> (token.type) { - <span class="hljs-keyword">case</span> Twig.token.type.raw: - output.push(Twig.filters.raw(token.value)); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> Twig.token.type.logic: - <span class="hljs-keyword">var</span> logic_token = token.token, - logic = Twig.logic.parse.apply(that, [logic_token, context, chain]); - - <span class="hljs-keyword">if</span> (logic.chain !== <span class="hljs-literal">undefined</span>) { - chain = logic.chain; - } - <span class="hljs-keyword">if</span> (logic.context !== <span class="hljs-literal">undefined</span>) { - context = logic.context; - } - <span class="hljs-keyword">if</span> (logic.output !== <span class="hljs-literal">undefined</span>) { - output.push(logic.output); - } - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> Twig.token.type.comment:</pre></div></div> - - </li> - - - <li id="section-76"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-76">¶</a> - </div> - <p>Do nothing, comments should be ignored</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">break</span>;</pre></div></div> - - </li> - - - <li id="section-77"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-77">¶</a> - </div> - <p>Fall through whitespace to output</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_pre: - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_post: - <span class="hljs-keyword">case</span> Twig.token.type.output_whitespace_both: - <span class="hljs-keyword">case</span> Twig.token.type.output: - Twig.log.debug(<span class="hljs-string">"Twig.parse: "</span>, <span class="hljs-string">"Output token: "</span>, token.stack);</pre></div></div> - - </li> - - - <li id="section-78"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-78">¶</a> - </div> - <p>Parse the given expression in the given context</p> - - </div> - - <div class="content"><div class='highlight'><pre> output.push(Twig.expression.parse.apply(that, [token.stack, context])); - <span class="hljs-keyword">break</span>; - } - }); - <span class="hljs-keyword">return</span> Twig.output.apply(<span class="hljs-keyword">this</span>, [output]); - } <span class="hljs-keyword">catch</span> (ex) { - Twig.log.error(<span class="hljs-string">"Error parsing twig template "</span> + <span class="hljs-keyword">this</span>.id + <span class="hljs-string">": "</span>); - <span class="hljs-keyword">if</span> (ex.stack) { - Twig.log.error(ex.stack); - } <span class="hljs-keyword">else</span> { - Twig.log.error(ex.toString()); - } - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.options.rethrow) <span class="hljs-keyword">throw</span> ex; - - <span class="hljs-keyword">if</span> (Twig.debug) { - <span class="hljs-keyword">return</span> ex.toString(); - } - } - }; - - <span class="hljs-comment">/** - * Tokenize and compile a string template. - * - * @param {string} data The template. - * - * @return {Array} The compiled tokens. - */</span> - Twig.prepare = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">data</span>) </span>{ - <span class="hljs-keyword">var</span> tokens, raw_tokens;</pre></div></div> - - </li> - - - <li id="section-79"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-79">¶</a> - </div> - <p>Tokenize</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.log.debug(<span class="hljs-string">"Twig.prepare: "</span>, <span class="hljs-string">"Tokenizing "</span>, data); - raw_tokens = Twig.tokenize.apply(<span class="hljs-keyword">this</span>, [data]);</pre></div></div> - - </li> - - - <li id="section-80"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-80">¶</a> - </div> - <p>Compile</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.log.debug(<span class="hljs-string">"Twig.prepare: "</span>, <span class="hljs-string">"Compiling "</span>, raw_tokens); - tokens = Twig.compile.apply(<span class="hljs-keyword">this</span>, [raw_tokens]); - - Twig.log.debug(<span class="hljs-string">"Twig.prepare: "</span>, <span class="hljs-string">"Compiled "</span>, tokens); - - <span class="hljs-keyword">return</span> tokens; - }; - - <span class="hljs-comment">/** - * Join the output token's stack and escape it if needed - * - * @param {Array} Output token's stack - * - * @return {string|String} Autoescaped output - */</span> - Twig.output = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">output</span>) </span>{ - <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.options.autoescape) { - <span class="hljs-keyword">return</span> output.join(<span class="hljs-string">""</span>); - } - - <span class="hljs-keyword">var</span> strategy = <span class="hljs-string">'html'</span>; - <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> <span class="hljs-keyword">this</span>.options.autoescape == <span class="hljs-string">'string'</span>) - strategy = <span class="hljs-keyword">this</span>.options.autoescape;</pre></div></div> - - </li> - - - <li id="section-81"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-81">¶</a> - </div> - <p>[].map would be better but it’s not supported by IE8-</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> escaped_output = []; - Twig.forEach(output, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">str</span>) </span>{ - <span class="hljs-keyword">if</span> (str && (str.twig_markup !== <span class="hljs-literal">true</span> && str.twig_markup != strategy)) { - str = Twig.filters.escape(str, [ strategy ]); - } - escaped_output.push(str); - }); - <span class="hljs-keyword">return</span> Twig.Markup(escaped_output.join(<span class="hljs-string">""</span>)); - }</pre></div></div> - - </li> - - - <li id="section-82"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-82">¶</a> - </div> - <p>Namespace for template storage and retrieval</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.Templates = { - <span class="hljs-comment">/** - * Registered template loaders - use Twig.Templates.registerLoader to add supported loaders - * @type {Object} - */</span> - loaders: {}, - - <span class="hljs-comment">/** - * Registered template parsers - use Twig.Templates.registerParser to add supported parsers - * @type {Object} - */</span> - parsers: {}, - - <span class="hljs-comment">/** - * Cached / loaded templates - * @type {Object} - */</span> - registry: {} - }; - - <span class="hljs-comment">/** - * Is this id valid for a twig template? - * - * @param {string} id The ID to check. - * - * @throws {Twig.Error} If the ID is invalid or used. - * @return {boolean} True if the ID is valid. - */</span> - Twig.validateId = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">id</span>) </span>{ - <span class="hljs-keyword">if</span> (id === <span class="hljs-string">"prototype"</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(id + <span class="hljs-string">" is not a valid twig identifier"</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Twig.cache && Twig.Templates.registry.hasOwnProperty(id)) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"There is already a template with the ID "</span> + id); - } - <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; - } - - <span class="hljs-comment">/** - * Register a template loader - * - * @example - * Twig.extend(function(Twig) { - * Twig.Templates.registerLoader('custom_loader', function(location, params, callback, error_callback) { - * // ... load the template ... - * params.data = loadedTemplateData; - * // create and return the template - * var template = new Twig.Template(params); - * if (typeof callback === 'function') { - * callback(template); - * } - * return template; - * }); - * }); - * - * @param {String} method_name The method this loader is intended for (ajax, fs) - * @param {Function} func The function to execute when loading the template - * @param {Object|undefined} scope Optional scope parameter to bind func to - * - * @throws Twig.Error - * - * @return {void} - */</span> - Twig.Templates.registerLoader = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">method_name, func, scope</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> func !== <span class="hljs-string">'function'</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">'Unable to add loader for '</span> + method_name + <span class="hljs-string">': Invalid function reference given.'</span>); - } - <span class="hljs-keyword">if</span> (scope) { - func = func.bind(scope); - } - <span class="hljs-keyword">this</span>.loaders[method_name] = func; - }; - - <span class="hljs-comment">/** - * Remove a registered loader - * - * @param {String} method_name The method name for the loader you wish to remove - * - * @return {void} - */</span> - Twig.Templates.unRegisterLoader = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">method_name</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.isRegisteredLoader(method_name)) { - <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>.loaders[method_name]; - } - }; - - <span class="hljs-comment">/** - * See if a loader is registered by its method name - * - * @param {String} method_name The name of the loader you are looking for - * - * @return {boolean} - */</span> - Twig.Templates.isRegisteredLoader = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">method_name</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.loaders.hasOwnProperty(method_name); - }; - - <span class="hljs-comment">/** - * Register a template parser - * - * @example - * Twig.extend(function(Twig) { - * Twig.Templates.registerParser('custom_parser', function(params) { - * // this template source can be accessed in params.data - * var template = params.data - * - * // ... custom process that modifies the template - * - * // return the parsed template - * return template; - * }); - * }); - * - * @param {String} method_name The method this parser is intended for (twig, source) - * @param {Function} func The function to execute when parsing the template - * @param {Object|undefined} scope Optional scope parameter to bind func to - * - * @throws Twig.Error - * - * @return {void} - */</span> - Twig.Templates.registerParser = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">method_name, func, scope</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> func !== <span class="hljs-string">'function'</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">'Unable to add parser for '</span> + method_name + <span class="hljs-string">': Invalid function regerence given.'</span>); - } - - <span class="hljs-keyword">if</span> (scope) { - func = func.bind(scope); - } - - <span class="hljs-keyword">this</span>.parsers[method_name] = func; - }; - - <span class="hljs-comment">/** - * Remove a registered parser - * - * @param {String} method_name The method name for the parser you wish to remove - * - * @return {void} - */</span> - Twig.Templates.unRegisterParser = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">method_name</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.isRegisteredParser(method_name)) { - <span class="hljs-keyword">delete</span> <span class="hljs-keyword">this</span>.parsers[method_name]; - } - }; - - <span class="hljs-comment">/** - * See if a parser is registered by its method name - * - * @param {String} method_name The name of the parser you are looking for - * - * @return {boolean} - */</span> - Twig.Templates.isRegisteredParser = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">method_name</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.parsers.hasOwnProperty(method_name); - }; - - <span class="hljs-comment">/** - * Save a template object to the store. - * - * @param {Twig.Template} template The twig.js template to store. - */</span> - Twig.Templates.save = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">template</span>) </span>{ - <span class="hljs-keyword">if</span> (template.id === <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to save template with no id"</span>); - } - Twig.Templates.registry[template.id] = template; - }; - - <span class="hljs-comment">/** - * Load a previously saved template from the store. - * - * @param {string} id The ID of the template to load. - * - * @return {Twig.Template} A twig.js template stored with the provided ID. - */</span> - Twig.Templates.load = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">id</span>) </span>{ - <span class="hljs-keyword">if</span> (!Twig.Templates.registry.hasOwnProperty(id)) { - <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; - } - <span class="hljs-keyword">return</span> Twig.Templates.registry[id]; - }; - - <span class="hljs-comment">/** - * Load a template from a remote location using AJAX and saves in with the given ID. - * - * Available parameters: - * - * async: Should the HTTP request be performed asynchronously. - * Defaults to true. - * method: What method should be used to load the template - * (fs or ajax) - * parser: What method should be used to parse the template - * (twig or source) - * precompiled: Has the template already been compiled. - * - * @param {string} location The remote URL to load as a template. - * @param {Object} params The template parameters. - * @param {function} callback A callback triggered when the template finishes loading. - * @param {function} error_callback A callback triggered if an error occurs loading the template. - * - * - */</span> - Twig.Templates.loadRemote = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">location, params, callback, error_callback</span>) </span>{ - <span class="hljs-keyword">var</span> loader;</pre></div></div> - - </li> - - - <li id="section-83"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-83">¶</a> - </div> - <p>Default to async</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (params.async === <span class="hljs-literal">undefined</span>) { - params.async = <span class="hljs-literal">true</span>; - }</pre></div></div> - - </li> - - - <li id="section-84"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-84">¶</a> - </div> - <p>Default to the URL so the template is cached.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (params.id === <span class="hljs-literal">undefined</span>) { - params.id = location; - }</pre></div></div> - - </li> - - - <li id="section-85"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-85">¶</a> - </div> - <p>Check for existing template</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (Twig.cache && Twig.Templates.registry.hasOwnProperty(params.id)) {</pre></div></div> - - </li> - - - <li id="section-86"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-86">¶</a> - </div> - <p>A template is already saved with the given id.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> callback === <span class="hljs-string">'function'</span>) { - callback(Twig.Templates.registry[params.id]); - }</pre></div></div> - - </li> - - - <li id="section-87"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-87">¶</a> - </div> - <p>TODO: if async, return deferred promise</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> Twig.Templates.registry[params.id]; - }</pre></div></div> - - </li> - - - <li id="section-88"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-88">¶</a> - </div> - <p>if the parser name hasn’t been set, default it to twig</p> - - </div> - - <div class="content"><div class='highlight'><pre> params.parser = params.parser || <span class="hljs-string">'twig'</span>;</pre></div></div> - - </li> - - - <li id="section-89"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-89">¶</a> - </div> - <p>Assume ‘fs’ if the loader is not defined</p> - - </div> - - <div class="content"><div class='highlight'><pre> loader = <span class="hljs-keyword">this</span>.loaders[params.method] || <span class="hljs-keyword">this</span>.loaders.fs; - <span class="hljs-keyword">return</span> loader.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>); - };</pre></div></div> - - </li> - - - <li id="section-90"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-90">¶</a> - </div> - <p>Determine object type</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">is</span>(<span class="hljs-params">type, obj</span>) </span>{ - <span class="hljs-keyword">var</span> clas = <span class="hljs-built_in">Object</span>.prototype.toString.call(obj).slice(<span class="hljs-number">8</span>, <span class="hljs-number">-1</span>); - <span class="hljs-keyword">return</span> obj !== <span class="hljs-literal">undefined</span> && obj !== <span class="hljs-literal">null</span> && clas === type; - } - - <span class="hljs-comment">/** - * Create a new twig.js template. - * - * Parameters: { - * data: The template, either pre-compiled tokens or a string template - * id: The name of this template - * blocks: Any pre-existing block from a child template - * } - * - * @param {Object} params The template parameters. - */</span> - Twig.Template = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"> params </span>) </span>{ - <span class="hljs-keyword">var</span> data = params.data, - id = params.id, - blocks = params.blocks, - macros = params.macros || {}, - base = params.base, - path = params.path, - url = params.url, - name = params.name, - method = params.method,</pre></div></div> - - </li> - - - <li id="section-91"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-91">¶</a> - </div> - <p>parser options</p> - - </div> - - <div class="content"><div class='highlight'><pre> options = params.options;</pre></div></div> - - </li> - - - <li id="section-92"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-92">¶</a> - </div> - <h1 id="what-is-stored-in-a-twig-template">What is stored in a Twig.Template</h1> -<p>The Twig Template hold several chucks of data.</p> -<pre><code>{ - id: The token ID (<span class="hljs-keyword">if</span> any) - tokens: The list <span class="hljs-keyword">of</span> tokens that makes up <span class="hljs-keyword">this</span> template. - blocks: The list <span class="hljs-keyword">of</span> block <span class="hljs-keyword">this</span> template contains. - base: The base template (<span class="hljs-keyword">if</span> any) - options: { - Compiler/parser options - - strict_variables: <span class="hljs-literal">true</span>/<span class="hljs-literal">false</span> - Should missing variable/keys emit an error message. If <span class="hljs-literal">false</span>, they <span class="hljs-keyword">default</span> to <span class="hljs-literal">null</span>. - } -} -</code></pre> - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">this</span>.id = id; - <span class="hljs-keyword">this</span>.method = method; - <span class="hljs-keyword">this</span>.base = base; - <span class="hljs-keyword">this</span>.path = path; - <span class="hljs-keyword">this</span>.url = url; - <span class="hljs-keyword">this</span>.name = name; - <span class="hljs-keyword">this</span>.macros = macros; - <span class="hljs-keyword">this</span>.options = options; - - <span class="hljs-keyword">this</span>.reset(blocks); - - <span class="hljs-keyword">if</span> (is(<span class="hljs-string">'String'</span>, data)) { - <span class="hljs-keyword">this</span>.tokens = Twig.prepare.apply(<span class="hljs-keyword">this</span>, [data]); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">this</span>.tokens = data; - } - - <span class="hljs-keyword">if</span> (id !== <span class="hljs-literal">undefined</span>) { - Twig.Templates.save(<span class="hljs-keyword">this</span>); - } - }; - - Twig.Template.prototype.reset = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">blocks</span>) </span>{ - Twig.log.debug(<span class="hljs-string">"Twig.Template.reset"</span>, <span class="hljs-string">"Reseting template "</span> + <span class="hljs-keyword">this</span>.id); - <span class="hljs-keyword">this</span>.blocks = {}; - <span class="hljs-keyword">this</span>.importedBlocks = []; - <span class="hljs-keyword">this</span>.originalBlockTokens = {}; - <span class="hljs-keyword">this</span>.child = { - blocks: blocks || {} - }; - <span class="hljs-keyword">this</span>.extend = <span class="hljs-literal">null</span>; - }; - - Twig.Template.prototype.render = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">context, params</span>) </span>{ - params = params || {}; - - <span class="hljs-keyword">var</span> output, - url; - - <span class="hljs-keyword">this</span>.context = context || {};</pre></div></div> - - </li> - - - <li id="section-93"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-93">¶</a> - </div> - <p>Clear any previous state</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.reset(); - <span class="hljs-keyword">if</span> (params.blocks) { - <span class="hljs-keyword">this</span>.blocks = params.blocks; - } - <span class="hljs-keyword">if</span> (params.macros) { - <span class="hljs-keyword">this</span>.macros = params.macros; - } - - output = Twig.parse.apply(<span class="hljs-keyword">this</span>, [<span class="hljs-keyword">this</span>.tokens, <span class="hljs-keyword">this</span>.context]);</pre></div></div> - - </li> - - - <li id="section-94"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-94">¶</a> - </div> - <p>Does this template extend another</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.extend) { - <span class="hljs-keyword">var</span> ext_template;</pre></div></div> - - </li> - - - <li id="section-95"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-95">¶</a> - </div> - <p>check if the template is provided inline</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.options.allowInlineIncludes ) { - ext_template = Twig.Templates.load(<span class="hljs-keyword">this</span>.extend); - <span class="hljs-keyword">if</span> ( ext_template ) { - ext_template.options = <span class="hljs-keyword">this</span>.options; - } - }</pre></div></div> - - </li> - - - <li id="section-96"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-96">¶</a> - </div> - <p>check for the template file via include</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!ext_template) { - url = Twig.path.parsePath(<span class="hljs-keyword">this</span>, <span class="hljs-keyword">this</span>.extend); - - ext_template = Twig.Templates.loadRemote(url, { - method: <span class="hljs-keyword">this</span>.getLoaderMethod(), - base: <span class="hljs-keyword">this</span>.base, - <span class="hljs-keyword">async</span>: <span class="hljs-literal">false</span>, - id: url, - options: <span class="hljs-keyword">this</span>.options - }); - } - - <span class="hljs-keyword">this</span>.parent = ext_template; - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.parent.render(<span class="hljs-keyword">this</span>.context, { - blocks: <span class="hljs-keyword">this</span>.blocks - }); - } - - <span class="hljs-keyword">if</span> (params.output == <span class="hljs-string">'blocks'</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.blocks; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (params.output == <span class="hljs-string">'macros'</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.macros; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> output; - } - }; - - Twig.Template.prototype.importFile = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">file</span>) </span>{ - <span class="hljs-keyword">var</span> url, sub_template; - <span class="hljs-keyword">if</span> (!<span class="hljs-keyword">this</span>.url && <span class="hljs-keyword">this</span>.options.allowInlineIncludes) { - file = <span class="hljs-keyword">this</span>.path ? <span class="hljs-keyword">this</span>.path + <span class="hljs-string">'/'</span> + file : file; - sub_template = Twig.Templates.load(file); - - <span class="hljs-keyword">if</span> (!sub_template) { - sub_template = Twig.Templates.loadRemote(url, { - id: file, - method: <span class="hljs-keyword">this</span>.getLoaderMethod(), - <span class="hljs-keyword">async</span>: <span class="hljs-literal">false</span>, - options: <span class="hljs-keyword">this</span>.options - }); - - <span class="hljs-keyword">if</span> (!sub_template) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to find the template "</span> + file); - } - } - - sub_template.options = <span class="hljs-keyword">this</span>.options; - - <span class="hljs-keyword">return</span> sub_template; - } - - url = Twig.path.parsePath(<span class="hljs-keyword">this</span>, file);</pre></div></div> - - </li> - - - <li id="section-97"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-97">¶</a> - </div> - <p>Load blocks from an external file</p> - - </div> - - <div class="content"><div class='highlight'><pre> sub_template = Twig.Templates.loadRemote(url, { - method: <span class="hljs-keyword">this</span>.getLoaderMethod(), - base: <span class="hljs-keyword">this</span>.base, - <span class="hljs-keyword">async</span>: <span class="hljs-literal">false</span>, - options: <span class="hljs-keyword">this</span>.options, - id: url - }); - - <span class="hljs-keyword">return</span> sub_template; - }; - - Twig.Template.prototype.importBlocks = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">file, override</span>) </span>{ - <span class="hljs-keyword">var</span> sub_template = <span class="hljs-keyword">this</span>.importFile(file), - context = <span class="hljs-keyword">this</span>.context, - that = <span class="hljs-keyword">this</span>, - key; - - override = override || <span class="hljs-literal">false</span>; - - sub_template.render(context);</pre></div></div> - - </li> - - - <li id="section-98"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-98">¶</a> - </div> - <p>Mixin blocks</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.forEach(<span class="hljs-built_in">Object</span>.keys(sub_template.blocks), <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key</span>) </span>{ - <span class="hljs-keyword">if</span> (override || that.blocks[key] === <span class="hljs-literal">undefined</span>) { - that.blocks[key] = sub_template.blocks[key]; - that.importedBlocks.push(key); - } - }); - }; - - Twig.Template.prototype.importMacros = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">file</span>) </span>{ - <span class="hljs-keyword">var</span> url = Twig.path.parsePath(<span class="hljs-keyword">this</span>, file);</pre></div></div> - - </li> - - - <li id="section-99"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-99">¶</a> - </div> - <p>load remote template</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> remoteTemplate = Twig.Templates.loadRemote(url, { - method: <span class="hljs-keyword">this</span>.getLoaderMethod(), - <span class="hljs-keyword">async</span>: <span class="hljs-literal">false</span>, - id: url - }); - - <span class="hljs-keyword">return</span> remoteTemplate; - }; - - Twig.Template.prototype.getLoaderMethod = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.path) { - <span class="hljs-keyword">return</span> <span class="hljs-string">'fs'</span>; - } - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.url) { - <span class="hljs-keyword">return</span> <span class="hljs-string">'ajax'</span>; - } - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.method || <span class="hljs-string">'fs'</span>; - }; - - Twig.Template.prototype.compile = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">options</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-100"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-100">¶</a> - </div> - <p>compile the template into raw JS</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> Twig.compiler.compile(<span class="hljs-keyword">this</span>, options); - }; - - <span class="hljs-comment">/** - * Create safe output - * - * @param {string} Content safe to output - * - * @return {String} Content wrapped into a String - */</span> - - Twig.Markup = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">content, strategy</span>) </span>{ - <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> strategy == <span class="hljs-string">'undefined'</span>) { - strategy = <span class="hljs-literal">true</span>; - } - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> content === <span class="hljs-string">'string'</span> && content.length > <span class="hljs-number">0</span>) { - content = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(content); - content.twig_markup = strategy; - } - <span class="hljs-keyword">return</span> content; - }; - - <span class="hljs-keyword">return</span> Twig; - -}) (Twig || { }); - -(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> - 'use strict'</span>; - - Twig.Templates.registerLoader(<span class="hljs-string">'ajax'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">location, params, callback, error_callback</span>) </span>{ - <span class="hljs-keyword">var</span> template, - xmlhttp, - precompiled = params.precompiled, - parser = <span class="hljs-keyword">this</span>.parsers[params.parser] || <span class="hljs-keyword">this</span>.parser.twig; - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> XMLHttpRequest === <span class="hljs-string">"undefined"</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">'Unsupported platform: Unable to do ajax requests '</span> + - <span class="hljs-string">'because there is no "XMLHTTPRequest" implementation'</span>); - } - - xmlhttp = <span class="hljs-keyword">new</span> XMLHttpRequest(); - xmlhttp.onreadystatechange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">var</span> data = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">if</span>(xmlhttp.readyState === <span class="hljs-number">4</span>) { - <span class="hljs-keyword">if</span> (xmlhttp.status === <span class="hljs-number">200</span> || (<span class="hljs-built_in">window</span>.cordova && xmlhttp.status == <span class="hljs-number">0</span>)) { - Twig.log.debug(<span class="hljs-string">"Got template "</span>, xmlhttp.responseText); - - <span class="hljs-keyword">if</span> (precompiled === <span class="hljs-literal">true</span>) { - data = <span class="hljs-built_in">JSON</span>.parse(xmlhttp.responseText); - } <span class="hljs-keyword">else</span> { - data = xmlhttp.responseText; - } - - params.url = location; - params.data = data; - - template = parser.call(<span class="hljs-keyword">this</span>, params); - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> callback === <span class="hljs-string">'function'</span>) { - callback(template); - } - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> error_callback === <span class="hljs-string">'function'</span>) { - error_callback(xmlhttp); - } - } - } - }; - xmlhttp.open(<span class="hljs-string">"GET"</span>, location, !!params.async); - xmlhttp.send(); - - <span class="hljs-keyword">if</span> (params.async) {</pre></div></div> - - </li> - - - <li id="section-101"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-101">¶</a> - </div> - <p>TODO: return deferred promise</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> template; - } - }); - -}(Twig));(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> 'use strict'</span>; - - <span class="hljs-keyword">var</span> fs, path; - - <span class="hljs-keyword">try</span> {</pre></div></div> - - </li> - - - <li id="section-102"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-102">¶</a> - </div> - <p>require lib dependencies at runtime</p> - - </div> - - <div class="content"><div class='highlight'><pre> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>); - path = <span class="hljs-built_in">require</span>(<span class="hljs-string">'path'</span>); - } <span class="hljs-keyword">catch</span> (e) {</pre></div></div> - - </li> - - - <li id="section-103"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-103">¶</a> - </div> - <p>NOTE: this is in a try/catch to avoid errors cross platform</p> - - </div> - - <div class="content"><div class='highlight'><pre> } - - Twig.Templates.registerLoader(<span class="hljs-string">'fs'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">location, params, callback, error_callback</span>) </span>{ - <span class="hljs-keyword">var</span> template, - data = <span class="hljs-literal">null</span>, - precompiled = params.precompiled, - parser = <span class="hljs-keyword">this</span>.parsers[params.parser] || <span class="hljs-keyword">this</span>.parser.twig; - - <span class="hljs-keyword">if</span> (!fs || !path) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">'Unsupported platform: Unable to load from file '</span> + - <span class="hljs-string">'because there is no "fs" or "path" implementation'</span>); - } - - <span class="hljs-keyword">var</span> loadTemplateFn = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">err, data</span>) </span>{ - <span class="hljs-keyword">if</span> (err) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> error_callback === <span class="hljs-string">'function'</span>) { - error_callback(err); - } - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">if</span> (precompiled === <span class="hljs-literal">true</span>) { - data = <span class="hljs-built_in">JSON</span>.parse(data); - } - - params.data = data; - params.path = params.path || location;</pre></div></div> - - </li> - - - <li id="section-104"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-104">¶</a> - </div> - <p>template is in data</p> - - </div> - - <div class="content"><div class='highlight'><pre> template = parser.call(<span class="hljs-keyword">this</span>, params); - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> callback === <span class="hljs-string">'function'</span>) { - callback(template); - } - }; - params.path = params.path || location; - - <span class="hljs-keyword">if</span> (params.async) { - fs.stat(params.path, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">err, stats</span>) </span>{ - <span class="hljs-keyword">if</span> (err || !stats.isFile()) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">'Unable to find template file '</span> + location); - } - fs.readFile(params.path, <span class="hljs-string">'utf8'</span>, loadTemplateFn); - });</pre></div></div> - - </li> - - - <li id="section-105"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-105">¶</a> - </div> - <p>TODO: return deferred promise</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">if</span> (!fs.statSync(params.path).isFile()) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">'Unable to find template file '</span> + location); - } - data = fs.readFileSync(params.path, <span class="hljs-string">'utf8'</span>); - loadTemplateFn(<span class="hljs-literal">undefined</span>, data); - <span class="hljs-keyword">return</span> template - } - }); - -}(Twig));(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">Twig</span>)</span>{ -<span class="hljs-meta"> 'use strict'</span>; - - Twig.Templates.registerParser(<span class="hljs-string">'source'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">params</span>) </span>{ - <span class="hljs-keyword">return</span> params.data || <span class="hljs-string">''</span>; - }); -})(Twig); -(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">Twig</span>)</span>{ -<span class="hljs-meta"> 'use strict'</span>; - - Twig.Templates.registerParser(<span class="hljs-string">'twig'</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">params</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Twig.Template(params); - }); -})(Twig);</pre></div></div> - - </li> - - - <li id="section-106"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-106">¶</a> - </div> - <p>The following methods are from MDN and are available under a -<a href="http://www.opensource.org/licenses/mit-license.php">MIT License</a> or are -<a href="https://developer.mozilla.org/Project:Copyrights">Public Domain</a>.</p> -<p>See:</p> -<ul> -<li><a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys">Object.keys - MDN</a></li> -</ul> - - </div> - - </li> - - - <li id="section-107"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-107">¶</a> - </div> - <h2 id="twig-fills-js">twig.fills.js</h2> -<p>This file contains fills for backwards compatability.</p> - - </div> - - <div class="content"><div class='highlight'><pre>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ -<span class="hljs-meta"> "use strict"</span>;</pre></div></div> - - </li> - - - <li id="section-108"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-108">¶</a> - </div> - <p>Handle methods that don’t yet exist in every browser</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">String</span>.prototype.trim) { - <span class="hljs-built_in">String</span>.prototype.trim = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.replace(<span class="hljs-regexp">/^\s+|\s+$/g</span>,<span class="hljs-string">''</span>); - } - }; - - <span class="hljs-keyword">if</span>(!<span class="hljs-built_in">Object</span>.keys) <span class="hljs-built_in">Object</span>.keys = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">o</span>)</span>{ - <span class="hljs-keyword">if</span> (o !== <span class="hljs-built_in">Object</span>(o)) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(<span class="hljs-string">'Object.keys called on non-object'</span>); - } - <span class="hljs-keyword">var</span> ret = [], p; - <span class="hljs-keyword">for</span> (p <span class="hljs-keyword">in</span> o) <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.prototype.hasOwnProperty.call(o, p)) ret.push(p); - <span class="hljs-keyword">return</span> ret; - } - -})();</pre></div></div> - - </li> - - - <li id="section-109"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-109">¶</a> - </div> - <h2 id="twig-lib-js">twig.lib.js</h2> -<p>This file contains 3rd party libraries used within twig.</p> -<p>Copies of the licenses for the code included here can be found in the -LICENSES.md file.</p> - - </div> - - <div class="content"><div class='highlight'><pre> -<span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">Twig</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-110"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-110">¶</a> - </div> - <p>Namespace for libraries</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.lib = { }; - - <span class="hljs-comment">/** - sprintf() for JavaScript 1.0.3 - https://github.com/alexei/sprintf.js - **/</span> - <span class="hljs-keyword">var</span> sprintfLib = (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">var</span> re = { - not_string: <span class="hljs-regexp">/[^s]/</span>, - number: <span class="hljs-regexp">/[diefg]/</span>, - json: <span class="hljs-regexp">/[j]/</span>, - not_json: <span class="hljs-regexp">/[^j]/</span>, - text: <span class="hljs-regexp">/^[^\x25]+/</span>, - modulo: <span class="hljs-regexp">/^\x25{2}/</span>, - placeholder: <span class="hljs-regexp">/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-gijosuxX])/</span>, - key: <span class="hljs-regexp">/^([a-z_][a-z_\d]*)/i</span>, - key_access: <span class="hljs-regexp">/^\.([a-z_][a-z_\d]*)/i</span>, - index_access: <span class="hljs-regexp">/^\[(\d+)\]/</span>, - sign: <span class="hljs-regexp">/^[\+\-]/</span> - } - - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sprintf</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">var</span> key = <span class="hljs-built_in">arguments</span>[<span class="hljs-number">0</span>], cache = sprintf.cache - <span class="hljs-keyword">if</span> (!(cache[key] && cache.hasOwnProperty(key))) { - cache[key] = sprintf.parse(key) - } - <span class="hljs-keyword">return</span> sprintf.format.call(<span class="hljs-literal">null</span>, cache[key], <span class="hljs-built_in">arguments</span>) - } - - sprintf.format = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">parse_tree, argv</span>) </span>{ - <span class="hljs-keyword">var</span> cursor = <span class="hljs-number">1</span>, tree_length = parse_tree.length, node_type = <span class="hljs-string">""</span>, arg, output = [], i, k, match, pad, pad_character, pad_length, is_positive = <span class="hljs-literal">true</span>, sign = <span class="hljs-string">""</span> - <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>; i < tree_length; i++) { - node_type = get_type(parse_tree[i]) - <span class="hljs-keyword">if</span> (node_type === <span class="hljs-string">"string"</span>) { - output[output.length] = parse_tree[i] - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (node_type === <span class="hljs-string">"array"</span>) { - match = parse_tree[i] <span class="hljs-comment">// convenience purposes only</span> - <span class="hljs-keyword">if</span> (match[<span class="hljs-number">2</span>]) { <span class="hljs-comment">// keyword argument</span> - arg = argv[cursor] - <span class="hljs-keyword">for</span> (k = <span class="hljs-number">0</span>; k < match[<span class="hljs-number">2</span>].length; k++) { - <span class="hljs-keyword">if</span> (!arg.hasOwnProperty(match[<span class="hljs-number">2</span>][k])) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(sprintf(<span class="hljs-string">"[sprintf] property '%s' does not exist"</span>, match[<span class="hljs-number">2</span>][k])) - } - arg = arg[match[<span class="hljs-number">2</span>][k]] - } - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">1</span>]) { <span class="hljs-comment">// positional argument (explicit)</span> - arg = argv[match[<span class="hljs-number">1</span>]] - } - <span class="hljs-keyword">else</span> { <span class="hljs-comment">// positional argument (implicit)</span> - arg = argv[cursor++] - } - - <span class="hljs-keyword">if</span> (get_type(arg) == <span class="hljs-string">"function"</span>) { - arg = arg() - } - - <span class="hljs-keyword">if</span> (re.not_string.test(match[<span class="hljs-number">8</span>]) && re.not_json.test(match[<span class="hljs-number">8</span>]) && (get_type(arg) != <span class="hljs-string">"number"</span> && <span class="hljs-built_in">isNaN</span>(arg))) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">TypeError</span>(sprintf(<span class="hljs-string">"[sprintf] expecting number but found %s"</span>, get_type(arg))) - } - - <span class="hljs-keyword">if</span> (re.number.test(match[<span class="hljs-number">8</span>])) { - is_positive = arg >= <span class="hljs-number">0</span> - } - - <span class="hljs-keyword">switch</span> (match[<span class="hljs-number">8</span>]) { - <span class="hljs-keyword">case</span> <span class="hljs-string">"b"</span>: - arg = arg.toString(<span class="hljs-number">2</span>) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"c"</span>: - arg = <span class="hljs-built_in">String</span>.fromCharCode(arg) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"d"</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">"i"</span>: - arg = <span class="hljs-built_in">parseInt</span>(arg, <span class="hljs-number">10</span>) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"j"</span>: - arg = <span class="hljs-built_in">JSON</span>.stringify(arg, <span class="hljs-literal">null</span>, match[<span class="hljs-number">6</span>] ? <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">6</span>]) : <span class="hljs-number">0</span>) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"e"</span>: - arg = match[<span class="hljs-number">7</span>] ? arg.toExponential(match[<span class="hljs-number">7</span>]) : arg.toExponential() - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"f"</span>: - arg = match[<span class="hljs-number">7</span>] ? <span class="hljs-built_in">parseFloat</span>(arg).toFixed(match[<span class="hljs-number">7</span>]) : <span class="hljs-built_in">parseFloat</span>(arg) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"g"</span>: - arg = match[<span class="hljs-number">7</span>] ? <span class="hljs-built_in">parseFloat</span>(arg).toPrecision(match[<span class="hljs-number">7</span>]) : <span class="hljs-built_in">parseFloat</span>(arg) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"o"</span>: - arg = arg.toString(<span class="hljs-number">8</span>) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"s"</span>: - arg = ((arg = <span class="hljs-built_in">String</span>(arg)) && match[<span class="hljs-number">7</span>] ? arg.substring(<span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>]) : arg) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"u"</span>: - arg = arg >>> <span class="hljs-number">0</span> - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"x"</span>: - arg = arg.toString(<span class="hljs-number">16</span>) - <span class="hljs-keyword">break</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">"X"</span>: - arg = arg.toString(<span class="hljs-number">16</span>).toUpperCase() - <span class="hljs-keyword">break</span> - } - <span class="hljs-keyword">if</span> (re.json.test(match[<span class="hljs-number">8</span>])) { - output[output.length] = arg - } - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">if</span> (re.number.test(match[<span class="hljs-number">8</span>]) && (!is_positive || match[<span class="hljs-number">3</span>])) { - sign = is_positive ? <span class="hljs-string">"+"</span> : <span class="hljs-string">"-"</span> - arg = arg.toString().replace(re.sign, <span class="hljs-string">""</span>) - } - <span class="hljs-keyword">else</span> { - sign = <span class="hljs-string">""</span> - } - pad_character = match[<span class="hljs-number">4</span>] ? match[<span class="hljs-number">4</span>] === <span class="hljs-string">"0"</span> ? <span class="hljs-string">"0"</span> : match[<span class="hljs-number">4</span>].charAt(<span class="hljs-number">1</span>) : <span class="hljs-string">" "</span> - pad_length = match[<span class="hljs-number">6</span>] - (sign + arg).length - pad = match[<span class="hljs-number">6</span>] ? (pad_length > <span class="hljs-number">0</span> ? str_repeat(pad_character, pad_length) : <span class="hljs-string">""</span>) : <span class="hljs-string">""</span> - output[output.length] = match[<span class="hljs-number">5</span>] ? sign + arg + pad : (pad_character === <span class="hljs-string">"0"</span> ? sign + pad + arg : pad + sign + arg) - } - } - } - <span class="hljs-keyword">return</span> output.join(<span class="hljs-string">""</span>) - } - - sprintf.cache = {} - - sprintf.parse = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fmt</span>) </span>{ - <span class="hljs-keyword">var</span> _fmt = fmt, match = [], parse_tree = [], arg_names = <span class="hljs-number">0</span> - <span class="hljs-keyword">while</span> (_fmt) { - <span class="hljs-keyword">if</span> ((match = re.text.exec(_fmt)) !== <span class="hljs-literal">null</span>) { - parse_tree[parse_tree.length] = match[<span class="hljs-number">0</span>] - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ((match = re.modulo.exec(_fmt)) !== <span class="hljs-literal">null</span>) { - parse_tree[parse_tree.length] = <span class="hljs-string">"%"</span> - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ((match = re.placeholder.exec(_fmt)) !== <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">if</span> (match[<span class="hljs-number">2</span>]) { - arg_names |= <span class="hljs-number">1</span> - <span class="hljs-keyword">var</span> field_list = [], replacement_field = match[<span class="hljs-number">2</span>], field_match = [] - <span class="hljs-keyword">if</span> ((field_match = re.key.exec(replacement_field)) !== <span class="hljs-literal">null</span>) { - field_list[field_list.length] = field_match[<span class="hljs-number">1</span>] - <span class="hljs-keyword">while</span> ((replacement_field = replacement_field.substring(field_match[<span class="hljs-number">0</span>].length)) !== <span class="hljs-string">""</span>) { - <span class="hljs-keyword">if</span> ((field_match = re.key_access.exec(replacement_field)) !== <span class="hljs-literal">null</span>) { - field_list[field_list.length] = field_match[<span class="hljs-number">1</span>] - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ((field_match = re.index_access.exec(replacement_field)) !== <span class="hljs-literal">null</span>) { - field_list[field_list.length] = field_match[<span class="hljs-number">1</span>] - } - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">SyntaxError</span>(<span class="hljs-string">"[sprintf] failed to parse named argument key"</span>) - } - } - } - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">SyntaxError</span>(<span class="hljs-string">"[sprintf] failed to parse named argument key"</span>) - } - match[<span class="hljs-number">2</span>] = field_list - } - <span class="hljs-keyword">else</span> { - arg_names |= <span class="hljs-number">2</span> - } - <span class="hljs-keyword">if</span> (arg_names === <span class="hljs-number">3</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"[sprintf] mixing positional and named placeholders is not (yet) supported"</span>) - } - parse_tree[parse_tree.length] = match - } - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">SyntaxError</span>(<span class="hljs-string">"[sprintf] unexpected placeholder"</span>) - } - _fmt = _fmt.substring(match[<span class="hljs-number">0</span>].length) - } - <span class="hljs-keyword">return</span> parse_tree - } - - <span class="hljs-keyword">var</span> vsprintf = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fmt, argv, _argv</span>) </span>{ - _argv = (argv || []).slice(<span class="hljs-number">0</span>) - _argv.splice(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, fmt) - <span class="hljs-keyword">return</span> sprintf.apply(<span class="hljs-literal">null</span>, _argv) - } - - <span class="hljs-comment">/** - * helpers - */</span> - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">get_type</span>(<span class="hljs-params">variable</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.prototype.toString.call(variable).slice(<span class="hljs-number">8</span>, <span class="hljs-number">-1</span>).toLowerCase() - } - - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">str_repeat</span>(<span class="hljs-params">input, multiplier</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-built_in">Array</span>(multiplier + <span class="hljs-number">1</span>).join(input) - } - - <span class="hljs-comment">/** - * export - */</span> - <span class="hljs-keyword">return</span> { - sprintf: sprintf, - vsprintf: vsprintf - } - })(); - - <span class="hljs-keyword">var</span> sprintf = sprintfLib.sprintf; - <span class="hljs-keyword">var</span> vsprintf = sprintfLib.vsprintf;</pre></div></div> - - </li> - - - <li id="section-111"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-111">¶</a> - </div> - <p>Expose to Twig</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.lib.sprintf = sprintf; - Twig.lib.vsprintf = vsprintf; - - - <span class="hljs-comment">/** - * jPaq - A fully customizable JavaScript/JScript library - * http://jpaq.org/ - * - * Copyright (c) 2011 Christopher West - * Licensed under the MIT license. - * http://jpaq.org/license/ - * - * Version: 1.0.6.0000W - * Revised: April 6, 2011 - */</span> - ; (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">var</span> shortDays = <span class="hljs-string">"Sun,Mon,Tue,Wed,Thu,Fri,Sat"</span>.split(<span class="hljs-string">","</span>); - <span class="hljs-keyword">var</span> fullDays = <span class="hljs-string">"Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday"</span>.split(<span class="hljs-string">","</span>); - <span class="hljs-keyword">var</span> shortMonths = <span class="hljs-string">"Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec"</span>.split(<span class="hljs-string">","</span>); - <span class="hljs-keyword">var</span> fullMonths = <span class="hljs-string">"January,February,March,April,May,June,July,August,September,October,November,December"</span>.split(<span class="hljs-string">","</span>); - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getOrdinalFor</span>(<span class="hljs-params">intNum</span>) </span>{ - <span class="hljs-keyword">return</span> (((intNum = <span class="hljs-built_in">Math</span>.abs(intNum) % <span class="hljs-number">100</span>) % <span class="hljs-number">10</span> == <span class="hljs-number">1</span> && intNum != <span class="hljs-number">11</span>) ? <span class="hljs-string">"st"</span> - : (intNum % <span class="hljs-number">10</span> == <span class="hljs-number">2</span> && intNum != <span class="hljs-number">12</span>) ? <span class="hljs-string">"nd"</span> : (intNum % <span class="hljs-number">10</span> == <span class="hljs-number">3</span> - && intNum != <span class="hljs-number">13</span>) ? <span class="hljs-string">"rd"</span> : <span class="hljs-string">"th"</span>); - } - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getISO8601Year</span>(<span class="hljs-params">aDate</span>) </span>{ - <span class="hljs-keyword">var</span> d = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(aDate.getFullYear() + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">4</span>); - <span class="hljs-keyword">if</span>((d - aDate) / <span class="hljs-number">86400000</span> < <span class="hljs-number">7</span> && (aDate.getDay() + <span class="hljs-number">6</span>) % <span class="hljs-number">7</span> < (d.getDay() + <span class="hljs-number">6</span>) % <span class="hljs-number">7</span>) - <span class="hljs-keyword">return</span> d.getFullYear(); - <span class="hljs-keyword">if</span>(aDate.getMonth() > <span class="hljs-number">0</span> || aDate.getDate() >= <span class="hljs-number">4</span>) - <span class="hljs-keyword">return</span> aDate.getFullYear(); - <span class="hljs-keyword">return</span> aDate.getFullYear() - (((aDate.getDay() + <span class="hljs-number">6</span>) % <span class="hljs-number">7</span> - aDate.getDate() > <span class="hljs-number">2</span>) ? <span class="hljs-number">1</span> : <span class="hljs-number">0</span>); - } - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getISO8601Week</span>(<span class="hljs-params">aDate</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-112"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-112">¶</a> - </div> - <p>Get a day during the first week of the year.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> d = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(getISO8601Year(aDate), <span class="hljs-number">0</span>, <span class="hljs-number">4</span>);</pre></div></div> - - </li> - - - <li id="section-113"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-113">¶</a> - </div> - <p>Get the first monday of the year.</p> - - </div> - - <div class="content"><div class='highlight'><pre> d.setDate(d.getDate() - (d.getDay() + <span class="hljs-number">6</span>) % <span class="hljs-number">7</span>); - <span class="hljs-keyword">return</span> <span class="hljs-built_in">parseInt</span>((aDate - d) / <span class="hljs-number">604800000</span>) + <span class="hljs-number">1</span>; - } - Twig.lib.formatDate = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">date, format</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-114"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-114">¶</a> - </div> - <p>/ <summary> -/ Gets a string for this date, formatted according to the given format -/ string. -/ </summary> -/ <param name="format" type="String"> -/ The format of the output date string. The format string works in a -/ nearly identical way to the PHP date function which is highlighted here: -/ <a href="http://php.net/manual/en/function.date.php">http://php.net/manual/en/function.date.php</a>. -/ The only difference is the fact that “u” signifies milliseconds -/ instead of microseconds. The following characters are recognized in -/ the format parameter string: -/ d - Day of the month, 2 digits with leading zeros -/ D - A textual representation of a day, three letters -/ j - Day of the month without leading zeros -/ l (lowercase ‘L’) - A full textual representation of the day of the week -/ N - ISO-8601 numeric representation of the day of the week (starting from 1) -/ S - English ordinal suffix for the day of the month, 2 characters st, -/ nd, rd or th. Works well with j. -/ w - Numeric representation of the day of the week (starting from 0) -/ z - The day of the year (starting from 0) -/ W - ISO-8601 week number of year, weeks starting on Monday -/ F - A full textual representation of a month, such as January or March -/ m - Numeric representation of a month, with leading zeros -/ M - A short textual representation of a month, three letters -/ n - Numeric representation of a month, without leading zeros -/ t - Number of days in the given month -/ L - Whether it’s a leap year -/ o - ISO-8601 year number. This has the same value as Y, except that if -/ the ISO week number (W) belongs to the previous or next year, that -/ year is used instead. -/ Y - A full numeric representation of a year, 4 digits -/ y - A two digit representation of a year -/ a - Lowercase Ante meridiem and Post meridiem -/ A - Uppercase Ante meridiem and Post meridiem -/ B - Swatch Internet time -/ g - 12-hour format of an hour without leading zeros -/ G - 24-hour format of an hour without leading zeros -/ h - 12-hour format of an hour with leading zeros -/ H - 24-hour format of an hour with leading zeros -/ i - Minutes with leading zeros -/ s - Seconds, with leading zeros -/ u - Milliseconds -/ U - Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) -/ </param> -/ <returns type="String"> -/ Returns the string for this date, formatted according to the given -/ format string. -/ </returns> -If the format was not passed, use the default toString method.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> format !== <span class="hljs-string">"string"</span> || <span class="hljs-regexp">/^\s*$/</span>.test(format)) - <span class="hljs-keyword">return</span> date + <span class="hljs-string">""</span>; - <span class="hljs-keyword">var</span> jan1st = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(date.getFullYear(), <span class="hljs-number">0</span>, <span class="hljs-number">1</span>); - <span class="hljs-keyword">var</span> me = date; - <span class="hljs-keyword">return</span> format.replace(<span class="hljs-regexp">/[dDjlNSwzWFmMntLoYyaABgGhHisuU]/g</span>, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">option</span>) </span>{ - <span class="hljs-keyword">switch</span>(option) {</pre></div></div> - - </li> - - - <li id="section-115"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-115">¶</a> - </div> - <p>Day of the month, 2 digits with leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"d"</span>: <span class="hljs-keyword">return</span> (<span class="hljs-string">"0"</span> + me.getDate()).replace(<span class="hljs-regexp">/^.+(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-116"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-116">¶</a> - </div> - <p>A textual representation of a day, three letters</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"D"</span>: <span class="hljs-keyword">return</span> shortDays[me.getDay()];</pre></div></div> - - </li> - - - <li id="section-117"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-117">¶</a> - </div> - <p>Day of the month without leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"j"</span>: <span class="hljs-keyword">return</span> me.getDate();</pre></div></div> - - </li> - - - <li id="section-118"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-118">¶</a> - </div> - <p>A full textual representation of the day of the week</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"l"</span>: <span class="hljs-keyword">return</span> fullDays[me.getDay()];</pre></div></div> - - </li> - - - <li id="section-119"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-119">¶</a> - </div> - <p>ISO-8601 numeric representation of the day of the week</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"N"</span>: <span class="hljs-keyword">return</span> (me.getDay() + <span class="hljs-number">6</span>) % <span class="hljs-number">7</span> + <span class="hljs-number">1</span>;</pre></div></div> - - </li> - - - <li id="section-120"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-120">¶</a> - </div> - <p>English ordinal suffix for the day of the month, 2 characters</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"S"</span>: <span class="hljs-keyword">return</span> getOrdinalFor(me.getDate());</pre></div></div> - - </li> - - - <li id="section-121"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-121">¶</a> - </div> - <p>Numeric representation of the day of the week</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"w"</span>: <span class="hljs-keyword">return</span> me.getDay();</pre></div></div> - - </li> - - - <li id="section-122"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-122">¶</a> - </div> - <p>The day of the year (starting from 0)</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"z"</span>: <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.ceil((jan1st - me) / <span class="hljs-number">86400000</span>);</pre></div></div> - - </li> - - - <li id="section-123"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-123">¶</a> - </div> - <p>ISO-8601 week number of year, weeks starting on Monday</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"W"</span>: <span class="hljs-keyword">return</span> (<span class="hljs-string">"0"</span> + getISO8601Week(me)).replace(<span class="hljs-regexp">/^.(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-124"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-124">¶</a> - </div> - <p>A full textual representation of a month, such as January or March</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"F"</span>: <span class="hljs-keyword">return</span> fullMonths[me.getMonth()];</pre></div></div> - - </li> - - - <li id="section-125"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-125">¶</a> - </div> - <p>Numeric representation of a month, with leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"m"</span>: <span class="hljs-keyword">return</span> (<span class="hljs-string">"0"</span> + (me.getMonth() + <span class="hljs-number">1</span>)).replace(<span class="hljs-regexp">/^.+(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-126"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-126">¶</a> - </div> - <p>A short textual representation of a month, three letters</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"M"</span>: <span class="hljs-keyword">return</span> shortMonths[me.getMonth()];</pre></div></div> - - </li> - - - <li id="section-127"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-127">¶</a> - </div> - <p>Numeric representation of a month, without leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"n"</span>: <span class="hljs-keyword">return</span> me.getMonth() + <span class="hljs-number">1</span>;</pre></div></div> - - </li> - - - <li id="section-128"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-128">¶</a> - </div> - <p>Number of days in the given month</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"t"</span>: <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(me.getFullYear(), me.getMonth() + <span class="hljs-number">1</span>, <span class="hljs-number">-1</span>).getDate();</pre></div></div> - - </li> - - - <li id="section-129"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-129">¶</a> - </div> - <p>Whether it’s a leap year</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"L"</span>: <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(me.getFullYear(), <span class="hljs-number">1</span>, <span class="hljs-number">29</span>).getDate() == <span class="hljs-number">29</span> ? <span class="hljs-number">1</span> : <span class="hljs-number">0</span>;</pre></div></div> - - </li> - - - <li id="section-130"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-130">¶</a> - </div> - <p>ISO-8601 year number. This has the same value as Y, except that if the -ISO week number (W) belongs to the previous or next year, that year is -used instead.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"o"</span>: <span class="hljs-keyword">return</span> getISO8601Year(me);</pre></div></div> - - </li> - - - <li id="section-131"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-131">¶</a> - </div> - <p>A full numeric representation of a year, 4 digits</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"Y"</span>: <span class="hljs-keyword">return</span> me.getFullYear();</pre></div></div> - - </li> - - - <li id="section-132"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-132">¶</a> - </div> - <p>A two digit representation of a year</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"y"</span>: <span class="hljs-keyword">return</span> (me.getFullYear() + <span class="hljs-string">""</span>).replace(<span class="hljs-regexp">/^.+(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-133"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-133">¶</a> - </div> - <p>Lowercase Ante meridiem and Post meridiem</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"a"</span>: <span class="hljs-keyword">return</span> me.getHours() < <span class="hljs-number">12</span> ? <span class="hljs-string">"am"</span> : <span class="hljs-string">"pm"</span>;</pre></div></div> - - </li> - - - <li id="section-134"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-134">¶</a> - </div> - <p>Uppercase Ante meridiem and Post meridiem</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"A"</span>: <span class="hljs-keyword">return</span> me.getHours() < <span class="hljs-number">12</span> ? <span class="hljs-string">"AM"</span> : <span class="hljs-string">"PM"</span>;</pre></div></div> - - </li> - - - <li id="section-135"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-135">¶</a> - </div> - <p>Swatch Internet time</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"B"</span>: <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.floor((((me.getUTCHours() + <span class="hljs-number">1</span>) % <span class="hljs-number">24</span>) + me.getUTCMinutes() / <span class="hljs-number">60</span> + me.getUTCSeconds() / <span class="hljs-number">3600</span>) * <span class="hljs-number">1000</span> / <span class="hljs-number">24</span>);</pre></div></div> - - </li> - - - <li id="section-136"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-136">¶</a> - </div> - <p>12-hour format of an hour without leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"g"</span>: <span class="hljs-keyword">return</span> me.getHours() % <span class="hljs-number">12</span> != <span class="hljs-number">0</span> ? me.getHours() % <span class="hljs-number">12</span> : <span class="hljs-number">12</span>;</pre></div></div> - - </li> - - - <li id="section-137"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-137">¶</a> - </div> - <p>24-hour format of an hour without leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"G"</span>: <span class="hljs-keyword">return</span> me.getHours();</pre></div></div> - - </li> - - - <li id="section-138"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-138">¶</a> - </div> - <p>12-hour format of an hour with leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"h"</span>: <span class="hljs-keyword">return</span> (<span class="hljs-string">"0"</span> + (me.getHours() % <span class="hljs-number">12</span> != <span class="hljs-number">0</span> ? me.getHours() % <span class="hljs-number">12</span> : <span class="hljs-number">12</span>)).replace(<span class="hljs-regexp">/^.+(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-139"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-139">¶</a> - </div> - <p>24-hour format of an hour with leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"H"</span>: <span class="hljs-keyword">return</span> (<span class="hljs-string">"0"</span> + me.getHours()).replace(<span class="hljs-regexp">/^.+(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-140"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-140">¶</a> - </div> - <p>Minutes with leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"i"</span>: <span class="hljs-keyword">return</span> (<span class="hljs-string">"0"</span> + me.getMinutes()).replace(<span class="hljs-regexp">/^.+(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-141"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-141">¶</a> - </div> - <p>Seconds, with leading zeros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"s"</span>: <span class="hljs-keyword">return</span> (<span class="hljs-string">"0"</span> + me.getSeconds()).replace(<span class="hljs-regexp">/^.+(..)$/</span>, <span class="hljs-string">"$1"</span>);</pre></div></div> - - </li> - - - <li id="section-142"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-142">¶</a> - </div> - <p>Milliseconds</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"u"</span>: <span class="hljs-keyword">return</span> me.getMilliseconds();</pre></div></div> - - </li> - - - <li id="section-143"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-143">¶</a> - </div> - <p>Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT)</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">"U"</span>: <span class="hljs-keyword">return</span> me.getTime() / <span class="hljs-number">1000</span>; - } - }); - }; - })(); - - Twig.lib.strip_tags = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">input, allowed</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-144"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-144">¶</a> - </div> - <p>Strips HTML and PHP tags from a string</p> -<p>version: 1109.2015 -discuss at: <a href="http://phpjs.org/functions/strip_tags">http://phpjs.org/functions/strip_tags</a></p> -<ul> -<li>original by: Kevin van Zonneveld (<a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a>)</li> -<li>improved by: Luke Godfrey</li> -<li>input by: Pul</li> -<li>bugfixed by: Kevin van Zonneveld (<a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a>)</li> -<li>bugfixed by: Onno Marsman</li> -<li>input by: Alex</li> -<li>bugfixed by: Kevin van Zonneveld (<a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a>)</li> -<li>input by: Marc Palau</li> -<li>improved by: Kevin van Zonneveld (<a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a>)</li> -<li>input by: Brett Zamir (<a href="http://brett-zamir.me">http://brett-zamir.me</a>)</li> -<li>bugfixed by: Kevin van Zonneveld (<a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a>)</li> -<li>bugfixed by: Eric Nagel</li> -<li>input by: Bobby Drake</li> -<li>bugfixed by: Kevin van Zonneveld (<a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a>)</li> -<li>bugfixed by: Tomasz Wesolowski</li> -<li>input by: Evertjan Garretsen</li> -<li>revised by: Rafał Kukawski (<a href="http://blog.kukawski.pl/">http://blog.kukawski.pl/</a>)</li> -<li>example 1: strip_tags(‘<p>Kevin</p> <b>van</b> <i>Zonneveld</i>‘, ‘<i><b>‘);</li> -<li>returns 1: ‘Kevin <b>van</b> <i>Zonneveld</i>‘</li> -<li>example 2: strip_tags(‘<p>Kevin <img src="someimage.png" onmouseover="someFunction()">van <i>Zonneveld</i></p>‘, ‘<p>‘);</li> -<li>returns 2: ‘<p>Kevin van Zonneveld</p>‘</li> -<li>example 3: strip_tags(“<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>“, “<a>“);</li> -<li>returns 3: ‘<a href='http://kevin.vanzonneveld.net'>Kevin van Zonneveld</a>‘</li> -<li>example 4: strip_tags(‘1 < 5 5 > 1’);</li> -<li>returns 4: ‘1 < 5 5 > 1’</li> -<li>example 5: strip_tags(‘1 <br/> 1’);</li> -<li>returns 5: ‘1 1’</li> -<li>example 6: strip_tags(‘1 <br/> 1’, ‘<br>‘);</li> -<li>returns 6: ‘1 1’</li> -<li>example 7: strip_tags(‘1 <br/> 1’, ‘<br><br/>‘);</li> -<li>returns 7: ‘1 <br/> 1’</li> -</ul> - - </div> - - <div class="content"><div class='highlight'><pre> allowed = (((allowed || <span class="hljs-string">""</span>) + <span class="hljs-string">""</span>).toLowerCase().match(<span class="hljs-regexp">/<[a-z][a-z0-9]*>/g</span>) || []).join(<span class="hljs-string">''</span>); <span class="hljs-comment">// making sure the allowed arg is a string containing only tags in lowercase (<a><b><c>)</span> - <span class="hljs-keyword">var</span> tags = <span class="hljs-regexp">/<\/?([a-z][a-z0-9]*)\b[^>]*>/gi</span>, - commentsAndPhpTags = <span class="hljs-regexp">/<!--[\s\S]*?-->|<\?(?:php)?[\s\S]*?\?>/gi</span>; - <span class="hljs-keyword">return</span> input.replace(commentsAndPhpTags, <span class="hljs-string">''</span>).replace(tags, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">$0, $1</span>) </span>{ - <span class="hljs-keyword">return</span> allowed.indexOf(<span class="hljs-string">'<'</span> + $<span class="hljs-number">1.</span>toLowerCase() + <span class="hljs-string">'>'</span>) > <span class="hljs-number">-1</span> ? $<span class="hljs-number">0</span> : <span class="hljs-string">''</span>; - }); - } - - Twig.lib.parseISO8601Date = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">s</span>)</span>{</pre></div></div> - - </li> - - - <li id="section-145"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-145">¶</a> - </div> - <p>Taken from <a href="http://n8v.enteuxis.org/2010/12/parsing-iso-8601-dates-in-javascript/">http://n8v.enteuxis.org/2010/12/parsing-iso-8601-dates-in-javascript/</a> -parenthese matches: -year month day hours minutes seconds<br>dotmilliseconds -tzstring plusminus hours minutes</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> re = <span class="hljs-regexp">/(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d+)?(Z|([+-])(\d\d):(\d\d))/</span>; - - <span class="hljs-keyword">var</span> d = []; - d = s.match(re);</pre></div></div> - - </li> - - - <li id="section-146"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-146">¶</a> - </div> - <p>“2010-12-07T11:00:00.000-09:00” parses to: - [“2010-12-07T11:00:00.000-09:00”, “2010”, “12”, “07”, “11”, - “00”, “00”, “.000”, “-09:00”, “-“, “09”, “00”] -“2010-12-07T11:00:00.000Z” parses to: - [“2010-12-07T11:00:00.000Z”, “2010”, “12”, “07”, “11”, - “00”, “00”, “.000”, “Z”, undefined, undefined, undefined]</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">if</span> (! d) { - <span class="hljs-keyword">throw</span> <span class="hljs-string">"Couldn't parse ISO 8601 date string '"</span> + s + <span class="hljs-string">"'"</span>; - }</pre></div></div> - - </li> - - - <li id="section-147"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-147">¶</a> - </div> - <p>parse strings, leading zeros into proper ints</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> a = [<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>,<span class="hljs-number">4</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6</span>,<span class="hljs-number">10</span>,<span class="hljs-number">11</span>]; - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i <span class="hljs-keyword">in</span> a) { - d[a[i]] = <span class="hljs-built_in">parseInt</span>(d[a[i]], <span class="hljs-number">10</span>); - } - d[<span class="hljs-number">7</span>] = <span class="hljs-built_in">parseFloat</span>(d[<span class="hljs-number">7</span>]);</pre></div></div> - - </li> - - - <li id="section-148"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-148">¶</a> - </div> - <p>Date.UTC(year, month[, date[, hrs[, min[, sec[, ms]]]]]) -note that month is 0-11, not 1-12 -see <a href="https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/UTC">https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/UTC</a></p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> ms = <span class="hljs-built_in">Date</span>.UTC(d[<span class="hljs-number">1</span>], d[<span class="hljs-number">2</span>] - <span class="hljs-number">1</span>, d[<span class="hljs-number">3</span>], d[<span class="hljs-number">4</span>], d[<span class="hljs-number">5</span>], d[<span class="hljs-number">6</span>]);</pre></div></div> - - </li> - - - <li id="section-149"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-149">¶</a> - </div> - <p>if there are milliseconds, add them</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (d[<span class="hljs-number">7</span>] > <span class="hljs-number">0</span>) { - ms += <span class="hljs-built_in">Math</span>.round(d[<span class="hljs-number">7</span>] * <span class="hljs-number">1000</span>); - }</pre></div></div> - - </li> - - - <li id="section-150"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-150">¶</a> - </div> - <p>if there’s a timezone, calculate it</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (d[<span class="hljs-number">8</span>] != <span class="hljs-string">"Z"</span> && d[<span class="hljs-number">10</span>]) { - <span class="hljs-keyword">var</span> offset = d[<span class="hljs-number">10</span>] * <span class="hljs-number">60</span> * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>; - <span class="hljs-keyword">if</span> (d[<span class="hljs-number">11</span>]) { - offset += d[<span class="hljs-number">11</span>] * <span class="hljs-number">60</span> * <span class="hljs-number">1000</span>; - } - <span class="hljs-keyword">if</span> (d[<span class="hljs-number">9</span>] == <span class="hljs-string">"-"</span>) { - ms -= offset; - } - <span class="hljs-keyword">else</span> { - ms += offset; - } - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(ms); - }; - - Twig.lib.strtotime = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">text, now</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-151"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-151">¶</a> - </div> - <p> discuss at: <a href="http://phpjs.org/functions/strtotime/">http://phpjs.org/functions/strtotime/</a> - version: 1109.2016 -original by: Caio Ariede (<a href="http://caioariede.com">http://caioariede.com</a>) -improved by: Kevin van Zonneveld (<a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a>) -improved by: Caio Ariede (<a href="http://caioariede.com">http://caioariede.com</a>) -improved by: A. Matías Quezada (<a href="http://amatiasq.com">http://amatiasq.com</a>) -improved by: preuter -improved by: Brett Zamir (<a href="http://brett-zamir.me">http://brett-zamir.me</a>) -improved by: Mirko Faber - input by: David -bugfixed by: Wagner B. Soares -bugfixed by: Artur Tchernychev -bugfixed by: Stephan Bösch-Plepelits (<a href="http://github.com/plepe">http://github.com/plepe</a>) - note: Examples all have a fixed timestamp to prevent tests to fail because of variable time(zones) - example 1: strtotime(‘+1 day’, 1129633200); - returns 1: 1129719600 - example 2: strtotime(‘+1 week 2 days 4 hours 2 seconds’, 1129633200); - returns 2: 1130425202 - example 3: strtotime(‘last month’, 1129633200); - returns 3: 1127041200 - example 4: strtotime(‘2009-05-04 08:30:00 GMT’); - returns 4: 1241425800 - example 5: strtotime(‘2009-05-04 08:30:00+00’); - returns 5: 1241425800 - example 6: strtotime(‘2009-05-04 08:30:00+02:00’); - returns 6: 1241418600 - example 7: strtotime(‘2009-05-04T08:30:00Z’); - returns 7: 1241425800</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">var</span> parsed, match, today, year, date, days, ranges, len, times, regex, i, fail = <span class="hljs-literal">false</span>; - - <span class="hljs-keyword">if</span> (!text) { - <span class="hljs-keyword">return</span> fail; - }</pre></div></div> - - </li> - - - <li id="section-152"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-152">¶</a> - </div> - <p>Unecessary spaces</p> - - </div> - - <div class="content"><div class='highlight'><pre> text = text.replace(<span class="hljs-regexp">/^\s+|\s+$/g</span>, <span class="hljs-string">''</span>) - .replace(<span class="hljs-regexp">/\s{2,}/g</span>, <span class="hljs-string">' '</span>) - .replace(<span class="hljs-regexp">/[\t\r\n]/g</span>, <span class="hljs-string">''</span>) - .toLowerCase();</pre></div></div> - - </li> - - - <li id="section-153"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-153">¶</a> - </div> - <p>in contrast to php, js Date.parse function interprets: -dates given as yyyy-mm-dd as in timezone: UTC, -dates with “.” or “-“ as MDY instead of DMY -dates with two-digit years differently -etc…etc… -…therefore we manually parse lots of common date formats</p> - - </div> - - <div class="content"><div class='highlight'><pre> match = text.match( - <span class="hljs-regexp">/^(\d{1,4})([\-\.\/\:])(\d{1,2})([\-\.\/\:])(\d{1,4})(?:\s(\d{1,2}):(\d{2})?:?(\d{2})?)?(?:\s([A-Z]+)?)?$/</span>); - - <span class="hljs-keyword">if</span> (match && match[<span class="hljs-number">2</span>] === match[<span class="hljs-number">4</span>]) { - <span class="hljs-keyword">if</span> (match[<span class="hljs-number">1</span>] > <span class="hljs-number">1901</span>) { - <span class="hljs-keyword">switch</span> (match[<span class="hljs-number">2</span>]) { - <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>: - {</pre></div></div> - - </li> - - - <li id="section-154"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-154">¶</a> - </div> - <p>YYYY-M-D</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">3</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">5</span>] > <span class="hljs-number">31</span>) { - <span class="hljs-keyword">return</span> fail; - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(match[<span class="hljs-number">1</span>], <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">3</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">5</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - <span class="hljs-keyword">case</span> <span class="hljs-string">'.'</span>: - {</pre></div></div> - - </li> - - - <li id="section-155"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-155">¶</a> - </div> - <p>YYYY.M.D is not parsed by strtotime()</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> fail; - } - <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>: - {</pre></div></div> - - </li> - - - <li id="section-156"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-156">¶</a> - </div> - <p>YYYY/M/D</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">3</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">5</span>] > <span class="hljs-number">31</span>) { - <span class="hljs-keyword">return</span> fail; - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(match[<span class="hljs-number">1</span>], <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">3</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">5</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - } - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">5</span>] > <span class="hljs-number">1901</span>) { - <span class="hljs-keyword">switch</span> (match[<span class="hljs-number">2</span>]) { - <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>: - {</pre></div></div> - - </li> - - - <li id="section-157"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-157">¶</a> - </div> - <p>D-M-YYYY</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">3</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">1</span>] > <span class="hljs-number">31</span>) { - <span class="hljs-keyword">return</span> fail; - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(match[<span class="hljs-number">5</span>], <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">3</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">1</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - <span class="hljs-keyword">case</span> <span class="hljs-string">'.'</span>: - {</pre></div></div> - - </li> - - - <li id="section-158"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-158">¶</a> - </div> - <p>D.M.YYYY</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">3</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">1</span>] > <span class="hljs-number">31</span>) { - <span class="hljs-keyword">return</span> fail; - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(match[<span class="hljs-number">5</span>], <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">3</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">1</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>: - {</pre></div></div> - - </li> - - - <li id="section-159"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-159">¶</a> - </div> - <p>M/D/YYYY</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">1</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">3</span>] > <span class="hljs-number">31</span>) { - <span class="hljs-keyword">return</span> fail; - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(match[<span class="hljs-number">5</span>], <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">1</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">3</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - } - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">switch</span> (match[<span class="hljs-number">2</span>]) { - <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>: - {</pre></div></div> - - </li> - - - <li id="section-160"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-160">¶</a> - </div> - <p>YY-M-D</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">3</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">5</span>] > <span class="hljs-number">31</span> || (match[<span class="hljs-number">1</span>] < <span class="hljs-number">70</span> && match[<span class="hljs-number">1</span>] > <span class="hljs-number">38</span>)) { - <span class="hljs-keyword">return</span> fail; - } - - year = match[<span class="hljs-number">1</span>] >= <span class="hljs-number">0</span> && match[<span class="hljs-number">1</span>] <= <span class="hljs-number">38</span> ? +match[<span class="hljs-number">1</span>] + <span class="hljs-number">2000</span> : match[<span class="hljs-number">1</span>]; - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(year, <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">3</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">5</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - <span class="hljs-keyword">case</span> <span class="hljs-string">'.'</span>: - {</pre></div></div> - - </li> - - - <li id="section-161"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-161">¶</a> - </div> - <p>D.M.YY or H.MM.SS</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">5</span>] >= <span class="hljs-number">70</span>) {</pre></div></div> - - </li> - - - <li id="section-162"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-162">¶</a> - </div> - <p>D.M.YY</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">3</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">1</span>] > <span class="hljs-number">31</span>) { - <span class="hljs-keyword">return</span> fail; - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(match[<span class="hljs-number">5</span>], <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">3</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">1</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - <span class="hljs-keyword">if</span> (match[<span class="hljs-number">5</span>] < <span class="hljs-number">60</span> && !match[<span class="hljs-number">6</span>]) {</pre></div></div> - - </li> - - - <li id="section-163"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-163">¶</a> - </div> - <p>H.MM.SS</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">1</span>] > <span class="hljs-number">23</span> || match[<span class="hljs-number">3</span>] > <span class="hljs-number">59</span>) { - <span class="hljs-keyword">return</span> fail; - } - - today = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(); - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(today.getFullYear(), today.getMonth(), today.getDate(), - match[<span class="hljs-number">1</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">3</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">5</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - }</pre></div></div> - - </li> - - - <li id="section-164"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-164">¶</a> - </div> - <p>invalid format, cannot be parsed</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> fail; - } - <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>: - {</pre></div></div> - - </li> - - - <li id="section-165"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-165">¶</a> - </div> - <p>M/D/YY</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">1</span>] > <span class="hljs-number">12</span> || match[<span class="hljs-number">3</span>] > <span class="hljs-number">31</span> || (match[<span class="hljs-number">5</span>] < <span class="hljs-number">70</span> && match[<span class="hljs-number">5</span>] > <span class="hljs-number">38</span>)) { - <span class="hljs-keyword">return</span> fail; - } - - year = match[<span class="hljs-number">5</span>] >= <span class="hljs-number">0</span> && match[<span class="hljs-number">5</span>] <= <span class="hljs-number">38</span> ? +match[<span class="hljs-number">5</span>] + <span class="hljs-number">2000</span> : match[<span class="hljs-number">5</span>]; - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(year, <span class="hljs-built_in">parseInt</span>(match[<span class="hljs-number">1</span>], <span class="hljs-number">10</span>) - <span class="hljs-number">1</span>, match[<span class="hljs-number">3</span>], - match[<span class="hljs-number">6</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">7</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">8</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">9</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - <span class="hljs-keyword">case</span> <span class="hljs-string">':'</span>: - {</pre></div></div> - - </li> - - - <li id="section-166"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-166">¶</a> - </div> - <p>HH:MM:SS</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">1</span>] > <span class="hljs-number">23</span> || match[<span class="hljs-number">3</span>] > <span class="hljs-number">59</span> || match[<span class="hljs-number">5</span>] > <span class="hljs-number">59</span>) { - <span class="hljs-keyword">return</span> fail; - } - - today = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(); - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(today.getFullYear(), today.getMonth(), today.getDate(), - match[<span class="hljs-number">1</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">3</span>] || <span class="hljs-number">0</span>, match[<span class="hljs-number">5</span>] || <span class="hljs-number">0</span>) / <span class="hljs-number">1000</span>; - } - } - } - }</pre></div></div> - - </li> - - - <li id="section-167"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-167">¶</a> - </div> - <p>other formats and “now” should be parsed by Date.parse()</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (text === <span class="hljs-string">'now'</span>) { - <span class="hljs-keyword">return</span> now === <span class="hljs-literal">null</span> || <span class="hljs-built_in">isNaN</span>(now) ? <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>() - .getTime() / <span class="hljs-number">1000</span> | <span class="hljs-number">0</span> : now | <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">isNaN</span>(parsed = <span class="hljs-built_in">Date</span>.parse(text))) { - <span class="hljs-keyword">return</span> parsed / <span class="hljs-number">1000</span> | <span class="hljs-number">0</span>; - }</pre></div></div> - - </li> - - - <li id="section-168"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-168">¶</a> - </div> - <p>Browsers != Chrome have problems parsing ISO 8601 date strings, as they do -not accept lower case characters, space, or shortened time zones. -Therefore, fix these problems and try again. -Examples: - 2015-04-15 20:33:59+02 - 2015-04-15 20:33:59z - 2015-04-15t20:33:59+02:00</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match = text.match(<span class="hljs-regexp">/^([0-9]{4}-[0-9]{2}-[0-9]{2})[ t]([0-9]{2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?)([\+-][0-9]{2}(:[0-9]{2})?|z)/</span>)) {</pre></div></div> - - </li> - - - <li id="section-169"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-169">¶</a> - </div> - <p>fix time zone information</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">4</span>] == <span class="hljs-string">'z'</span>) { - match[<span class="hljs-number">4</span>] = <span class="hljs-string">'Z'</span>; - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (match[<span class="hljs-number">4</span>].match(<span class="hljs-regexp">/^([\+-][0-9]{2})$/</span>)) { - match[<span class="hljs-number">4</span>] = match[<span class="hljs-number">4</span>] + <span class="hljs-string">':00'</span>; - } - - <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">isNaN</span>(parsed = <span class="hljs-built_in">Date</span>.parse(match[<span class="hljs-number">1</span>] + <span class="hljs-string">'T'</span> + match[<span class="hljs-number">2</span>] + match[<span class="hljs-number">4</span>]))) { - <span class="hljs-keyword">return</span> parsed / <span class="hljs-number">1000</span> | <span class="hljs-number">0</span>; - } - } - - date = now ? <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(now * <span class="hljs-number">1000</span>) : <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(); - days = { - <span class="hljs-string">'sun'</span>: <span class="hljs-number">0</span>, - <span class="hljs-string">'mon'</span>: <span class="hljs-number">1</span>, - <span class="hljs-string">'tue'</span>: <span class="hljs-number">2</span>, - <span class="hljs-string">'wed'</span>: <span class="hljs-number">3</span>, - <span class="hljs-string">'thu'</span>: <span class="hljs-number">4</span>, - <span class="hljs-string">'fri'</span>: <span class="hljs-number">5</span>, - <span class="hljs-string">'sat'</span>: <span class="hljs-number">6</span> - }; - ranges = { - <span class="hljs-string">'yea'</span>: <span class="hljs-string">'FullYear'</span>, - <span class="hljs-string">'mon'</span>: <span class="hljs-string">'Month'</span>, - <span class="hljs-string">'day'</span>: <span class="hljs-string">'Date'</span>, - <span class="hljs-string">'hou'</span>: <span class="hljs-string">'Hours'</span>, - <span class="hljs-string">'min'</span>: <span class="hljs-string">'Minutes'</span>, - <span class="hljs-string">'sec'</span>: <span class="hljs-string">'Seconds'</span> - }; - - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">lastNext</span>(<span class="hljs-params">type, range, modifier</span>) </span>{ - <span class="hljs-keyword">var</span> diff, day = days[range]; - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> day !== <span class="hljs-string">'undefined'</span>) { - diff = day - date.getDay(); - - <span class="hljs-keyword">if</span> (diff === <span class="hljs-number">0</span>) { - diff = <span class="hljs-number">7</span> * modifier; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (diff > <span class="hljs-number">0</span> && type === <span class="hljs-string">'last'</span>) { - diff -= <span class="hljs-number">7</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (diff < <span class="hljs-number">0</span> && type === <span class="hljs-string">'next'</span>) { - diff += <span class="hljs-number">7</span>; - } - - date.setDate(date.getDate() + diff); - } - } - - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">process</span>(<span class="hljs-params">val</span>) </span>{ - <span class="hljs-keyword">var</span> splt = val.split(<span class="hljs-string">' '</span>), <span class="hljs-comment">// Todo: Reconcile this with regex using \s, taking into account browser issues with split and regexes</span> - type = splt[<span class="hljs-number">0</span>], - range = splt[<span class="hljs-number">1</span>].substring(<span class="hljs-number">0</span>, <span class="hljs-number">3</span>), - typeIsNumber = <span class="hljs-regexp">/\d+/</span>.test(type), - ago = splt[<span class="hljs-number">2</span>] === <span class="hljs-string">'ago'</span>, - num = (type === <span class="hljs-string">'last'</span> ? <span class="hljs-number">-1</span> : <span class="hljs-number">1</span>) * (ago ? <span class="hljs-number">-1</span> : <span class="hljs-number">1</span>); - - <span class="hljs-keyword">if</span> (typeIsNumber) { - num *= <span class="hljs-built_in">parseInt</span>(type, <span class="hljs-number">10</span>); - } - - <span class="hljs-keyword">if</span> (ranges.hasOwnProperty(range) && !splt[<span class="hljs-number">1</span>].match(<span class="hljs-regexp">/^mon(day|\.)?$/i</span>)) { - <span class="hljs-keyword">return</span> date[<span class="hljs-string">'set'</span> + ranges[range]](date[<span class="hljs-string">'get'</span> + ranges[range]]() + num); - } - - <span class="hljs-keyword">if</span> (range === <span class="hljs-string">'wee'</span>) { - <span class="hljs-keyword">return</span> date.setDate(date.getDate() + (num * <span class="hljs-number">7</span>)); - } - - <span class="hljs-keyword">if</span> (type === <span class="hljs-string">'next'</span> || type === <span class="hljs-string">'last'</span>) { - lastNext(type, range, num); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (!typeIsNumber) { - <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; - } - - <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; - } - - times = <span class="hljs-string">'(years?|months?|weeks?|days?|hours?|minutes?|min|seconds?|sec'</span> + - <span class="hljs-string">'|sunday|sun\\.?|monday|mon\\.?|tuesday|tue\\.?|wednesday|wed\\.?'</span> + - <span class="hljs-string">'|thursday|thu\\.?|friday|fri\\.?|saturday|sat\\.?)'</span>; - regex = <span class="hljs-string">'([+-]?\\d+\\s'</span> + times + <span class="hljs-string">'|'</span> + <span class="hljs-string">'(last|next)\\s'</span> + times + <span class="hljs-string">')(\\sago)?'</span>; - - match = text.match(<span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(regex, <span class="hljs-string">'gi'</span>)); - <span class="hljs-keyword">if</span> (!match) { - <span class="hljs-keyword">return</span> fail; - } - - <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>, len = match.length; i < len; i++) { - <span class="hljs-keyword">if</span> (!process(match[i])) { - <span class="hljs-keyword">return</span> fail; - } - }</pre></div></div> - - </li> - - - <li id="section-170"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-170">¶</a> - </div> - <p>ECMAScript 5 only -if (!match.every(process)) - return false;</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">return</span> (date.getTime() / <span class="hljs-number">1000</span>); - }; - - Twig.lib.is = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">type, obj</span>) </span>{ - <span class="hljs-keyword">var</span> clas = <span class="hljs-built_in">Object</span>.prototype.toString.call(obj).slice(<span class="hljs-number">8</span>, <span class="hljs-number">-1</span>); - <span class="hljs-keyword">return</span> obj !== <span class="hljs-literal">undefined</span> && obj !== <span class="hljs-literal">null</span> && clas === type; - };</pre></div></div> - - </li> - - - <li id="section-171"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-171">¶</a> - </div> - <p>shallow-copy an object</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.lib.copy = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">src</span>) </span>{ - <span class="hljs-keyword">var</span> target = {}, - key; - <span class="hljs-keyword">for</span> (key <span class="hljs-keyword">in</span> src) - target[key] = src[key]; - - <span class="hljs-keyword">return</span> target; - }; - - Twig.lib.replaceAll = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">string, search, replace</span>) </span>{ - <span class="hljs-keyword">return</span> string.split(search).join(replace); - };</pre></div></div> - - </li> - - - <li id="section-172"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-172">¶</a> - </div> - <p>chunk an array (arr) into arrays of (size) items, returns an array of arrays, or an empty array on invalid input</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.lib.chunkArray = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">arr, size</span>) </span>{ - <span class="hljs-keyword">var</span> returnVal = [], - x = <span class="hljs-number">0</span>, - len = arr.length; - - <span class="hljs-keyword">if</span> (size < <span class="hljs-number">1</span> || !Twig.lib.is(<span class="hljs-string">"Array"</span>, arr)) { - <span class="hljs-keyword">return</span> []; - } - - <span class="hljs-keyword">while</span> (x < len) { - returnVal.push(arr.slice(x, x += size)); - } - - <span class="hljs-keyword">return</span> returnVal; - }; - - Twig.lib.round = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">round</span>(<span class="hljs-params">value, precision, mode</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-173"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-173">¶</a> - </div> - <p> discuss at: <a href="http://phpjs.org/functions/round/">http://phpjs.org/functions/round/</a> -original by: Philip Peterson - revised by: Onno Marsman - revised by: T.Wild - revised by: Rafał Kukawski (<a href="http://blog.kukawski.pl/">http://blog.kukawski.pl/</a>) - input by: Greenseed - input by: meo - input by: William - input by: Josep Sanz (<a href="http://www.ws3.es/">http://www.ws3.es/</a>) -bugfixed by: Brett Zamir (<a href="http://brett-zamir.me">http://brett-zamir.me</a>) - note: Great work. Ideas for improvement: - note: - code more compliant with developer guidelines - note: - for implementing PHP constant arguments look at - note: the pathinfo() function, it offers the greatest - note: flexibility & compatibility possible - example 1: round(1241757, -3); - returns 1: 1242000 - example 2: round(3.6); - returns 2: 4 - example 3: round(2.835, 2); - returns 3: 2.84 - example 4: round(1.1749999999999, 2); - returns 4: 1.17 - example 5: round(58551.799999999996, 2); - returns 5: 58551.8</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">var</span> m, f, isHalf, sgn; <span class="hljs-comment">// helper variables</span> - precision |= <span class="hljs-number">0</span>; <span class="hljs-comment">// making sure precision is integer</span> - m = <span class="hljs-built_in">Math</span>.pow(<span class="hljs-number">10</span>, precision); - value *= m; - sgn = (value > <span class="hljs-number">0</span>) | -(value < <span class="hljs-number">0</span>); <span class="hljs-comment">// sign of the number</span> - isHalf = value % <span class="hljs-number">1</span> === <span class="hljs-number">0.5</span> * sgn; - f = <span class="hljs-built_in">Math</span>.floor(value); - - <span class="hljs-keyword">if</span> (isHalf) { - <span class="hljs-keyword">switch</span> (mode) { - <span class="hljs-keyword">case</span> <span class="hljs-string">'PHP_ROUND_HALF_DOWN'</span>: - value = f + (sgn < <span class="hljs-number">0</span>); <span class="hljs-comment">// rounds .5 toward zero</span> - <span class="hljs-keyword">break</span>; - <span class="hljs-keyword">case</span> <span class="hljs-string">'PHP_ROUND_HALF_EVEN'</span>: - value = f + (f % <span class="hljs-number">2</span> * sgn); <span class="hljs-comment">// rouds .5 towards the next even integer</span> - <span class="hljs-keyword">break</span>; - <span class="hljs-keyword">case</span> <span class="hljs-string">'PHP_ROUND_HALF_ODD'</span>: - value = f + !(f % <span class="hljs-number">2</span>); <span class="hljs-comment">// rounds .5 towards the next odd integer</span> - <span class="hljs-keyword">break</span>; - <span class="hljs-keyword">default</span>: - value = f + (sgn > <span class="hljs-number">0</span>); <span class="hljs-comment">// rounds .5 away from zero</span> - } - } - - <span class="hljs-keyword">return</span> (isHalf ? value : <span class="hljs-built_in">Math</span>.round(value)) / m; - }; - - Twig.lib.max = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">max</span>(<span class="hljs-params"></span>) </span>{</pre></div></div> - - </li> - - - <li id="section-174"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-174">¶</a> - </div> - <p> discuss at: <a href="http://phpjs.org/functions/max/">http://phpjs.org/functions/max/</a> -original by: Onno Marsman - revised by: Onno Marsman -improved by: Jack - note: Long code cause we’re aiming for maximum PHP compatibility - example 1: max(1, 3, 5, 6, 7); - returns 1: 7 - example 2: max([2, 4, 5]); - returns 2: 5 - example 3: max(0, ‘hello’); - returns 3: 0 - example 4: max(‘hello’, 0); - returns 4: ‘hello’ - example 5: max(-1, ‘hello’); - returns 5: ‘hello’ - example 6: max([2, 4, 8], [2, 5, 7]); - returns 6: [2, 5, 7]</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">var</span> ar, retVal, i = <span class="hljs-number">0</span>, - n = <span class="hljs-number">0</span>, - argv = <span class="hljs-built_in">arguments</span>, - argc = argv.length, - _obj2Array = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.prototype.toString.call(obj) === <span class="hljs-string">'[object Array]'</span>) { - <span class="hljs-keyword">return</span> obj; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">var</span> ar = []; - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i <span class="hljs-keyword">in</span> obj) { - <span class="hljs-keyword">if</span> (obj.hasOwnProperty(i)) { - ar.push(obj[i]); - } - } - <span class="hljs-keyword">return</span> ar; - } - }, <span class="hljs-comment">//function _obj2Array</span> - _compare = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">current, next</span>) </span>{ - <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, - n = <span class="hljs-number">0</span>, - tmp = <span class="hljs-number">0</span>, - nl = <span class="hljs-number">0</span>, - cl = <span class="hljs-number">0</span>; - - <span class="hljs-keyword">if</span> (current === next) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> current === <span class="hljs-string">'object'</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> next === <span class="hljs-string">'object'</span>) { - current = _obj2Array(current); - next = _obj2Array(next); - cl = current.length; - nl = next.length; - <span class="hljs-keyword">if</span> (nl > cl) { - <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (nl < cl) { - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } - <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>, n = cl; i < n; ++i) { - tmp = _compare(current[i], next[i]); - <span class="hljs-keyword">if</span> (tmp == <span class="hljs-number">1</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (tmp == <span class="hljs-number">-1</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } - } - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> next === <span class="hljs-string">'object'</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(next) && !<span class="hljs-built_in">isNaN</span>(current)) { - <span class="hljs-keyword">if</span> (current == <span class="hljs-number">0</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> (current < <span class="hljs-number">0</span> ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(current) && !<span class="hljs-built_in">isNaN</span>(next)) { - <span class="hljs-keyword">if</span> (next == <span class="hljs-number">0</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> (next > <span class="hljs-number">0</span> ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>); - } - - <span class="hljs-keyword">if</span> (next == current) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> (next > current ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>); - }; <span class="hljs-comment">//function _compare</span> - <span class="hljs-keyword">if</span> (argc === <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'At least one value should be passed to max()'</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (argc === <span class="hljs-number">1</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> argv[<span class="hljs-number">0</span>] === <span class="hljs-string">'object'</span>) { - ar = _obj2Array(argv[<span class="hljs-number">0</span>]); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Wrong parameter count for max()'</span>); - } - <span class="hljs-keyword">if</span> (ar.length === <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Array must contain at least one element for max()'</span>); - } - } <span class="hljs-keyword">else</span> { - ar = argv; - } - - retVal = ar[<span class="hljs-number">0</span>]; - <span class="hljs-keyword">for</span> (i = <span class="hljs-number">1</span>, n = ar.length; i < n; ++i) { - <span class="hljs-keyword">if</span> (_compare(retVal, ar[i]) == <span class="hljs-number">1</span>) { - retVal = ar[i]; - } - } - - <span class="hljs-keyword">return</span> retVal; - }; - - Twig.lib.min = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">min</span>(<span class="hljs-params"></span>) </span>{</pre></div></div> - - </li> - - - <li id="section-175"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-175">¶</a> - </div> - <p> discuss at: <a href="http://phpjs.org/functions/min/">http://phpjs.org/functions/min/</a> -original by: Onno Marsman - revised by: Onno Marsman -improved by: Jack - note: Long code cause we’re aiming for maximum PHP compatibility - example 1: min(1, 3, 5, 6, 7); - returns 1: 1 - example 2: min([2, 4, 5]); - returns 2: 2 - example 3: min(0, ‘hello’); - returns 3: 0 - example 4: min(‘hello’, 0); - returns 4: ‘hello’ - example 5: min(-1, ‘hello’); - returns 5: -1 - example 6: min([2, 4, 8], [2, 5, 7]); - returns 6: [2, 4, 8]</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">var</span> ar, retVal, i = <span class="hljs-number">0</span>, - n = <span class="hljs-number">0</span>, - argv = <span class="hljs-built_in">arguments</span>, - argc = argv.length, - _obj2Array = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.prototype.toString.call(obj) === <span class="hljs-string">'[object Array]'</span>) { - <span class="hljs-keyword">return</span> obj; - } - <span class="hljs-keyword">var</span> ar = []; - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i <span class="hljs-keyword">in</span> obj) { - <span class="hljs-keyword">if</span> (obj.hasOwnProperty(i)) { - ar.push(obj[i]); - } - } - <span class="hljs-keyword">return</span> ar; - }, <span class="hljs-comment">//function _obj2Array</span> - _compare = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">current, next</span>) </span>{ - <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, - n = <span class="hljs-number">0</span>, - tmp = <span class="hljs-number">0</span>, - nl = <span class="hljs-number">0</span>, - cl = <span class="hljs-number">0</span>; - - <span class="hljs-keyword">if</span> (current === next) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> current === <span class="hljs-string">'object'</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> next === <span class="hljs-string">'object'</span>) { - current = _obj2Array(current); - next = _obj2Array(next); - cl = current.length; - nl = next.length; - <span class="hljs-keyword">if</span> (nl > cl) { - <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (nl < cl) { - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } - <span class="hljs-keyword">for</span> (i = <span class="hljs-number">0</span>, n = cl; i < n; ++i) { - tmp = _compare(current[i], next[i]); - <span class="hljs-keyword">if</span> (tmp == <span class="hljs-number">1</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (tmp == <span class="hljs-number">-1</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } - } - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> next === <span class="hljs-string">'object'</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(next) && !<span class="hljs-built_in">isNaN</span>(current)) { - <span class="hljs-keyword">if</span> (current == <span class="hljs-number">0</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> (current < <span class="hljs-number">0</span> ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(current) && !<span class="hljs-built_in">isNaN</span>(next)) { - <span class="hljs-keyword">if</span> (next == <span class="hljs-number">0</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> (next > <span class="hljs-number">0</span> ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>); - } - - <span class="hljs-keyword">if</span> (next == current) { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">return</span> (next > current ? <span class="hljs-number">1</span> : <span class="hljs-number">-1</span>); - }; <span class="hljs-comment">//function _compare</span> - - <span class="hljs-keyword">if</span> (argc === <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'At least one value should be passed to min()'</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (argc === <span class="hljs-number">1</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> argv[<span class="hljs-number">0</span>] === <span class="hljs-string">'object'</span>) { - ar = _obj2Array(argv[<span class="hljs-number">0</span>]); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Wrong parameter count for min()'</span>); - } - - <span class="hljs-keyword">if</span> (ar.length === <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Array must contain at least one element for min()'</span>); - } - } <span class="hljs-keyword">else</span> { - ar = argv; - } - - retVal = ar[<span class="hljs-number">0</span>]; - - <span class="hljs-keyword">for</span> (i = <span class="hljs-number">1</span>, n = ar.length; i < n; ++i) { - <span class="hljs-keyword">if</span> (_compare(retVal, ar[i]) == <span class="hljs-number">-1</span>) { - retVal = ar[i]; - } - } - - <span class="hljs-keyword">return</span> retVal; - }; - - <span class="hljs-keyword">return</span> Twig; - -})(Twig || { });</pre></div></div> - - </li> - - - <li id="section-176"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-176">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-177"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-177">¶</a> - </div> - <h2 id="twig-logic-js">twig.logic.js</h2> -<p>This file handles tokenizing, compiling and parsing logic tokens. {% … %}</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> "use strict"</span>; - - <span class="hljs-comment">/** - * Namespace for logic handling. - */</span> - Twig.logic = {}; - - <span class="hljs-comment">/** - * Logic token types. - */</span> - Twig.logic.type = { - if_: <span class="hljs-string">'Twig.logic.type.if'</span>, - endif: <span class="hljs-string">'Twig.logic.type.endif'</span>, - for_: <span class="hljs-string">'Twig.logic.type.for'</span>, - endfor: <span class="hljs-string">'Twig.logic.type.endfor'</span>, - else_: <span class="hljs-string">'Twig.logic.type.else'</span>, - elseif: <span class="hljs-string">'Twig.logic.type.elseif'</span>, - set: <span class="hljs-string">'Twig.logic.type.set'</span>, - setcapture:<span class="hljs-string">'Twig.logic.type.setcapture'</span>, - endset: <span class="hljs-string">'Twig.logic.type.endset'</span>, - filter: <span class="hljs-string">'Twig.logic.type.filter'</span>, - endfilter: <span class="hljs-string">'Twig.logic.type.endfilter'</span>, - shortblock: <span class="hljs-string">'Twig.logic.type.shortblock'</span>, - block: <span class="hljs-string">'Twig.logic.type.block'</span>, - endblock: <span class="hljs-string">'Twig.logic.type.endblock'</span>, - extends_: <span class="hljs-string">'Twig.logic.type.extends'</span>, - use: <span class="hljs-string">'Twig.logic.type.use'</span>, - include: <span class="hljs-string">'Twig.logic.type.include'</span>, - spaceless: <span class="hljs-string">'Twig.logic.type.spaceless'</span>, - endspaceless: <span class="hljs-string">'Twig.logic.type.endspaceless'</span>, - macro: <span class="hljs-string">'Twig.logic.type.macro'</span>, - endmacro: <span class="hljs-string">'Twig.logic.type.endmacro'</span>, - import_: <span class="hljs-string">'Twig.logic.type.import'</span>, - <span class="hljs-keyword">from</span>: <span class="hljs-string">'Twig.logic.type.from'</span>, - embed: <span class="hljs-string">'Twig.logic.type.embed'</span>, - endembed: <span class="hljs-string">'Twig.logic.type.endembed'</span> - };</pre></div></div> - - </li> - - - <li id="section-178"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-178">¶</a> - </div> - <p>Regular expressions for handling logic tokens.</p> -<p>Properties:</p> -<pre><code> type: The type of expression this matches - - regex: A regular expression that matches the format of the token - - next: What logic tokens (if any) pop this token off the logic stack. If empty, the - logic token is assumed to not require an end tag and isn't push onto the stack. - - open: Does this tag open a logic expression or is it standalone. For example, - {% endif %} cannot exist without an opening {% if ... %} tag, so open = false. -</code></pre><p> Functions:</p> -<pre><code> compile: A <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">that</span> <span class="hljs-title">handles</span> <span class="hljs-title">compiling</span> <span class="hljs-title">the</span> <span class="hljs-title">token</span> <span class="hljs-title">into</span> <span class="hljs-title">an</span> <span class="hljs-title">output</span> <span class="hljs-title">token</span> <span class="hljs-title">ready</span> <span class="hljs-title">for</span> - <span class="hljs-title">parsing</span> <span class="hljs-title">with</span> <span class="hljs-title">the</span> <span class="hljs-title">parse</span> <span class="hljs-title">function</span>. - - <span class="hljs-title">parse</span>: <span class="hljs-title">A</span> <span class="hljs-title">function</span> <span class="hljs-title">that</span> <span class="hljs-title">parses</span> <span class="hljs-title">the</span> <span class="hljs-title">compiled</span> <span class="hljs-title">token</span> <span class="hljs-title">into</span> <span class="hljs-title">output</span> (<span class="hljs-params">HTML / whatever the - template represents</span>).</span> -</code></pre> - </div> - - <div class="content"><div class='highlight'><pre> Twig.logic.definitions = [ - { - <span class="hljs-comment">/** - * If type logic tokens. - * - * Format: {% if expression %} - */</span> - type: Twig.logic.type.if_, - regex: <span class="hljs-regexp">/^if\s+([\s\S]+)$/</span>, - next: [ - Twig.logic.type.else_, - Twig.logic.type.elseif, - Twig.logic.type.endif - ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = token.match[<span class="hljs-number">1</span>];</pre></div></div> - - </li> - - - <li id="section-179"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-179">¶</a> - </div> - <p>Compile the expression.</p> - - </div> - - <div class="content"><div class='highlight'><pre> token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> output = <span class="hljs-string">''</span>,</pre></div></div> - - </li> - - - <li id="section-180"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-180">¶</a> - </div> - <p>Parse the expression</p> - - </div> - - <div class="content"><div class='highlight'><pre> result = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, context]);</pre></div></div> - - </li> - - - <li id="section-181"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-181">¶</a> - </div> - <p>Start a new logic chain</p> - - </div> - - <div class="content"><div class='highlight'><pre> chain = <span class="hljs-literal">true</span>; - - <span class="hljs-keyword">if</span> (result) { - chain = <span class="hljs-literal">false</span>;</pre></div></div> - - </li> - - - <li id="section-182"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-182">¶</a> - </div> - <p>parse if output</p> - - </div> - - <div class="content"><div class='highlight'><pre> output = Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]); - } - <span class="hljs-keyword">return</span> { - chain: chain, - output: output - }; - } - }, - { - <span class="hljs-comment">/** - * Else if type logic tokens. - * - * Format: {% elseif expression %} - */</span> - type: Twig.logic.type.elseif, - regex: <span class="hljs-regexp">/^elseif\s+([^\s].*)$/</span>, - next: [ - Twig.logic.type.else_, - Twig.logic.type.elseif, - Twig.logic.type.endif - ], - open: <span class="hljs-literal">false</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = token.match[<span class="hljs-number">1</span>];</pre></div></div> - - </li> - - - <li id="section-183"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-183">¶</a> - </div> - <p>Compile the expression.</p> - - </div> - - <div class="content"><div class='highlight'><pre> token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> output = <span class="hljs-string">''</span>; - - <span class="hljs-keyword">if</span> (chain && Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, context]) === <span class="hljs-literal">true</span>) { - chain = <span class="hljs-literal">false</span>;</pre></div></div> - - </li> - - - <li id="section-184"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-184">¶</a> - </div> - <p>parse if output</p> - - </div> - - <div class="content"><div class='highlight'><pre> output = Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]); - } - - <span class="hljs-keyword">return</span> { - chain: chain, - output: output - }; - } - }, - { - <span class="hljs-comment">/** - * Else if type logic tokens. - * - * Format: {% elseif expression %} - */</span> - type: Twig.logic.type.else_, - regex: <span class="hljs-regexp">/^else$/</span>, - next: [ - Twig.logic.type.endif, - Twig.logic.type.endfor - ], - open: <span class="hljs-literal">false</span>, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> output = <span class="hljs-string">''</span>; - <span class="hljs-keyword">if</span> (chain) { - output = Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]); - } - <span class="hljs-keyword">return</span> { - chain: chain, - output: output - }; - } - }, - { - <span class="hljs-comment">/** - * End if type logic tokens. - * - * Format: {% endif %} - */</span> - type: Twig.logic.type.endif, - regex: <span class="hljs-regexp">/^endif$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - }, - { - <span class="hljs-comment">/** - * For type logic tokens. - * - * Format: {% for expression %} - */</span> - type: Twig.logic.type.for_, - regex: <span class="hljs-regexp">/^for\s+([a-zA-Z0-9_,\s]+)\s+in\s+([^\s].*?)(?:\s+if\s+([^\s].*))?$/</span>, - next: [ - Twig.logic.type.else_, - Twig.logic.type.endfor - ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> key_value = token.match[<span class="hljs-number">1</span>], - expression = token.match[<span class="hljs-number">2</span>], - conditional = token.match[<span class="hljs-number">3</span>], - kv_split = <span class="hljs-literal">null</span>; - - token.key_var = <span class="hljs-literal">null</span>; - token.value_var = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">if</span> (key_value.indexOf(<span class="hljs-string">","</span>) >= <span class="hljs-number">0</span>) { - kv_split = key_value.split(<span class="hljs-string">','</span>); - <span class="hljs-keyword">if</span> (kv_split.length === <span class="hljs-number">2</span>) { - token.key_var = kv_split[<span class="hljs-number">0</span>].trim(); - token.value_var = kv_split[<span class="hljs-number">1</span>].trim(); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Invalid expression in for loop: "</span> + key_value); - } - } <span class="hljs-keyword">else</span> { - token.value_var = key_value; - }</pre></div></div> - - </li> - - - <li id="section-185"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-185">¶</a> - </div> - <p>Valid expressions for a for loop - for item in expression - for key,item in expression</p> - - </div> - - </li> - - - <li id="section-186"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-186">¶</a> - </div> - <p>Compile the expression.</p> - - </div> - - <div class="content"><div class='highlight'><pre> token.expression = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack;</pre></div></div> - - </li> - - - <li id="section-187"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-187">¶</a> - </div> - <p>Compile the conditional (if available)</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (conditional) { - token.conditional = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: conditional - }]).stack; - } - - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, continue_chain</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-188"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-188">¶</a> - </div> - <p>Parse expression</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> result = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.expression, context]), - output = [], - len, - index = <span class="hljs-number">0</span>, - keyset, - that = <span class="hljs-keyword">this</span>, - conditional = token.conditional, - buildLoop = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">index, len</span>) </span>{ - <span class="hljs-keyword">var</span> isConditional = conditional !== <span class="hljs-literal">undefined</span>; - <span class="hljs-keyword">return</span> { - index: index+<span class="hljs-number">1</span>, - index0: index, - revindex: isConditional?<span class="hljs-literal">undefined</span>:len-index, - revindex0: isConditional?<span class="hljs-literal">undefined</span>:len-index<span class="hljs-number">-1</span>, - first: (index === <span class="hljs-number">0</span>), - last: isConditional?<span class="hljs-literal">undefined</span>:(index === len<span class="hljs-number">-1</span>), - length: isConditional?<span class="hljs-literal">undefined</span>:len, - parent: context - }; - },</pre></div></div> - - </li> - - - <li id="section-189"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-189">¶</a> - </div> - <p>run once for each iteration of the loop</p> - - </div> - - <div class="content"><div class='highlight'><pre> loop = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key, value</span>) </span>{ - <span class="hljs-keyword">var</span> inner_context = Twig.ChildContext(context); - - inner_context[token.value_var] = value; - - <span class="hljs-keyword">if</span> (token.key_var) { - inner_context[token.key_var] = key; - }</pre></div></div> - - </li> - - - <li id="section-190"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-190">¶</a> - </div> - <p>Loop object</p> - - </div> - - <div class="content"><div class='highlight'><pre> inner_context.loop = buildLoop(index, len); - - <span class="hljs-keyword">if</span> (conditional === <span class="hljs-literal">undefined</span> || - Twig.expression.parse.apply(that, [conditional, inner_context])) - { - output.push(Twig.parse.apply(that, [token.output, inner_context])); - index += <span class="hljs-number">1</span>; - }</pre></div></div> - - </li> - - - <li id="section-191"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-191">¶</a> - </div> - <p>Delete loop-related variables from the context</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">delete</span> inner_context[<span class="hljs-string">'loop'</span>]; - <span class="hljs-keyword">delete</span> inner_context[token.value_var]; - <span class="hljs-keyword">delete</span> inner_context[token.key_var];</pre></div></div> - - </li> - - - <li id="section-192"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-192">¶</a> - </div> - <p>Merge in values that exist in context but have changed -in inner_context.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.merge(context, inner_context, <span class="hljs-literal">true</span>); - }; - - - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">'Array'</span>, result)) { - len = result.length; - Twig.forEach(result, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">var</span> key = index; - - loop(key, value); - }); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">'Object'</span>, result)) { - <span class="hljs-keyword">if</span> (result._keys !== <span class="hljs-literal">undefined</span>) { - keyset = result._keys; - } <span class="hljs-keyword">else</span> { - keyset = <span class="hljs-built_in">Object</span>.keys(result); - } - len = keyset.length; - Twig.forEach(keyset, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-193"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-193">¶</a> - </div> - <p>Ignore the _keys property, it’s internal to twig.js</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (key === <span class="hljs-string">"_keys"</span>) <span class="hljs-keyword">return</span>; - - loop(key, result[key]); - }); - }</pre></div></div> - - </li> - - - <li id="section-194"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-194">¶</a> - </div> - <p>Only allow else statements if no output was generated</p> - - </div> - - <div class="content"><div class='highlight'><pre> continue_chain = (output.length === <span class="hljs-number">0</span>); - - <span class="hljs-keyword">return</span> { - chain: continue_chain, - output: Twig.output.apply(<span class="hljs-keyword">this</span>, [output]) - }; - } - }, - { - <span class="hljs-comment">/** - * End if type logic tokens. - * - * Format: {% endif %} - */</span> - type: Twig.logic.type.endfor, - regex: <span class="hljs-regexp">/^endfor$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - }, - { - <span class="hljs-comment">/** - * Set type logic tokens. - * - * Format: {% set key = expression %} - */</span> - type: Twig.logic.type.set, - regex: <span class="hljs-regexp">/^set\s+([a-zA-Z0-9_,\s]+)\s*=\s*([\s\S]+)$/</span>, - next: [ ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> key = token.match[<span class="hljs-number">1</span>].trim(), - expression = token.match[<span class="hljs-number">2</span>],</pre></div></div> - - </li> - - - <li id="section-195"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-195">¶</a> - </div> - <p>Compile the expression.</p> - - </div> - - <div class="content"><div class='highlight'><pre> expression_stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - token.key = key; - token.expression = expression_stack; - - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, continue_chain</span>) </span>{ - <span class="hljs-keyword">var</span> value = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.expression, context]), - key = token.key; - - context[key] = value; - - <span class="hljs-keyword">return</span> { - chain: continue_chain, - context: context - }; - } - }, - { - <span class="hljs-comment">/** - * Set capture type logic tokens. - * - * Format: {% set key %} - */</span> - type: Twig.logic.type.setcapture, - regex: <span class="hljs-regexp">/^set\s+([a-zA-Z0-9_,\s]+)$/</span>, - next: [ - Twig.logic.type.endset - ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> key = token.match[<span class="hljs-number">1</span>].trim(); - - token.key = key; - - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, continue_chain</span>) </span>{ - - <span class="hljs-keyword">var</span> value = Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]), - key = token.key;</pre></div></div> - - </li> - - - <li id="section-196"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-196">¶</a> - </div> - <p>set on both the global and local context</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.context[key] = value; - context[key] = value; - - <span class="hljs-keyword">return</span> { - chain: continue_chain, - context: context - }; - } - }, - { - <span class="hljs-comment">/** - * End set type block logic tokens. - * - * Format: {% endset %} - */</span> - type: Twig.logic.type.endset, - regex: <span class="hljs-regexp">/^endset$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - }, - { - <span class="hljs-comment">/** - * Filter logic tokens. - * - * Format: {% filter upper %} or {% filter lower|escape %} - */</span> - type: Twig.logic.type.filter, - regex: <span class="hljs-regexp">/^filter\s+(.+)$/</span>, - next: [ - Twig.logic.type.endfilter - ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = <span class="hljs-string">"|"</span> + token.match[<span class="hljs-number">1</span>].trim();</pre></div></div> - - </li> - - - <li id="section-197"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-197">¶</a> - </div> - <p>Compile the expression.</p> - - </div> - - <div class="content"><div class='highlight'><pre> token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> unfiltered = Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]), - stack = [{ - type: Twig.expression.type.string, - value: unfiltered - }].concat(token.stack); - - <span class="hljs-keyword">var</span> output = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [stack, context]); - - <span class="hljs-keyword">return</span> { - chain: chain, - output: output - }; - } - }, - { - <span class="hljs-comment">/** - * End filter logic tokens. - * - * Format: {% endfilter %} - */</span> - type: Twig.logic.type.endfilter, - regex: <span class="hljs-regexp">/^endfilter$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - }, - { - <span class="hljs-comment">/** - * Block logic tokens. - * - * Format: {% block title %} - */</span> - type: Twig.logic.type.block, - regex: <span class="hljs-regexp">/^block\s+([a-zA-Z0-9_]+)$/</span>, - next: [ - Twig.logic.type.endblock - ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - token.block = token.match[<span class="hljs-number">1</span>].trim(); - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> block_output, - output, - isImported = Twig.indexOf(<span class="hljs-keyword">this</span>.importedBlocks, token.block) > <span class="hljs-number">-1</span>, - hasParent = <span class="hljs-keyword">this</span>.blocks[token.block] && Twig.indexOf(<span class="hljs-keyword">this</span>.blocks[token.block], Twig.placeholders.parent) > <span class="hljs-number">-1</span>;</pre></div></div> - - </li> - - - <li id="section-198"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-198">¶</a> - </div> - <p>Don’t override previous blocks unless they’re imported with “use” -Loops should be exempted as well.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.blocks[token.block] === <span class="hljs-literal">undefined</span> || isImported || hasParent || context.loop || token.overwrite) { - <span class="hljs-keyword">if</span> (token.expression) {</pre></div></div> - - </li> - - - <li id="section-199"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-199">¶</a> - </div> - <p>Short blocks have output as an expression on the open tag (no body)</p> - - </div> - - <div class="content"><div class='highlight'><pre> block_output = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.string, - value: Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]) - }, context]); - } <span class="hljs-keyword">else</span> { - block_output = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.string, - value: Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]) - }, context]); - } - - <span class="hljs-keyword">if</span> (isImported) {</pre></div></div> - - </li> - - - <li id="section-200"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-200">¶</a> - </div> - <p>once the block is overridden, remove it from the list of imported blocks</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.importedBlocks.splice(<span class="hljs-keyword">this</span>.importedBlocks.indexOf(token.block), <span class="hljs-number">1</span>); - } - - <span class="hljs-keyword">if</span> (hasParent) { - <span class="hljs-keyword">this</span>.blocks[token.block] = Twig.Markup(<span class="hljs-keyword">this</span>.blocks[token.block].replace(Twig.placeholders.parent, block_output)); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">this</span>.blocks[token.block] = block_output; - } - - <span class="hljs-keyword">this</span>.originalBlockTokens[token.block] = { - type: token.type, - block: token.block, - output: token.output, - overwrite: <span class="hljs-literal">true</span> - }; - }</pre></div></div> - - </li> - - - <li id="section-201"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-201">¶</a> - </div> - <p>Check if a child block has been set from a template extending this one.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.child.blocks[token.block]) { - output = <span class="hljs-keyword">this</span>.child.blocks[token.block]; - } <span class="hljs-keyword">else</span> { - output = <span class="hljs-keyword">this</span>.blocks[token.block]; - } - - <span class="hljs-keyword">return</span> { - chain: chain, - output: output - }; - } - }, - { - <span class="hljs-comment">/** - * Block shorthand logic tokens. - * - * Format: {% block title expression %} - */</span> - type: Twig.logic.type.shortblock, - regex: <span class="hljs-regexp">/^block\s+([a-zA-Z0-9_]+)\s+(.+)$/</span>, - next: [ ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - token.expression = token.match[<span class="hljs-number">2</span>].trim(); - - token.output = Twig.expression.compile({ - type: Twig.expression.type.expression, - value: token.expression - }).stack; - - token.block = token.match[<span class="hljs-number">1</span>].trim(); - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">return</span> Twig.logic.handler[Twig.logic.type.block].parse.apply(<span class="hljs-keyword">this</span>, <span class="hljs-built_in">arguments</span>); - } - }, - { - <span class="hljs-comment">/** - * End block logic tokens. - * - * Format: {% endblock %} - */</span> - type: Twig.logic.type.endblock, - regex: <span class="hljs-regexp">/^endblock(?:\s+([a-zA-Z0-9_]+))?$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - }, - { - <span class="hljs-comment">/** - * Block logic tokens. - * - * Format: {% extends "template.twig" %} - */</span> - type: Twig.logic.type.extends_, - regex: <span class="hljs-regexp">/^extends\s+(.+)$/</span>, - next: [ ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = token.match[<span class="hljs-number">1</span>].trim(); - <span class="hljs-keyword">delete</span> token.match; - - token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-202"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-202">¶</a> - </div> - <p>Resolve filename</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> file = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, context]);</pre></div></div> - - </li> - - - <li id="section-203"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-203">¶</a> - </div> - <p>Set parent template</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.extend = file; - - <span class="hljs-keyword">return</span> { - chain: chain, - output: <span class="hljs-string">''</span> - }; - } - }, - { - <span class="hljs-comment">/** - * Block logic tokens. - * - * Format: {% use "template.twig" %} - */</span> - type: Twig.logic.type.use, - regex: <span class="hljs-regexp">/^use\s+(.+)$/</span>, - next: [ ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = token.match[<span class="hljs-number">1</span>].trim(); - <span class="hljs-keyword">delete</span> token.match; - - token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-204"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-204">¶</a> - </div> - <p>Resolve filename</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> file = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, context]);</pre></div></div> - - </li> - - - <li id="section-205"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-205">¶</a> - </div> - <p>Import blocks</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.importBlocks(file); - - <span class="hljs-keyword">return</span> { - chain: chain, - output: <span class="hljs-string">''</span> - }; - } - }, - { - <span class="hljs-comment">/** - * Block logic tokens. - * - * Format: {% includes "template.twig" [with {some: 'values'} only] %} - */</span> - type: Twig.logic.type.include, - regex: <span class="hljs-regexp">/^include\s+(ignore missing\s+)?(.+?)\s*(?:with\s+([\S\s]+?))?\s*(only)?$/</span>, - next: [ ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> match = token.match, - includeMissing = match[<span class="hljs-number">1</span>] !== <span class="hljs-literal">undefined</span>, - expression = match[<span class="hljs-number">2</span>].trim(), - withContext = match[<span class="hljs-number">3</span>], - only = ((match[<span class="hljs-number">4</span>] !== <span class="hljs-literal">undefined</span>) && match[<span class="hljs-number">4</span>].length); - - <span class="hljs-keyword">delete</span> token.match; - - token.only = only; - token.includeMissing = includeMissing; - - token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - <span class="hljs-keyword">if</span> (withContext !== <span class="hljs-literal">undefined</span>) { - token.withStack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: withContext.trim() - }]).stack; - } - - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-206"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-206">¶</a> - </div> - <p>Resolve filename</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> innerContext = {}, - withContext, - i, - template; - - <span class="hljs-keyword">if</span> (!token.only) { - innerContext = Twig.ChildContext(context); - } - - <span class="hljs-keyword">if</span> (token.withStack !== <span class="hljs-literal">undefined</span>) { - withContext = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.withStack, context]); - - <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> withContext) { - <span class="hljs-keyword">if</span> (withContext.hasOwnProperty(i)) - innerContext[i] = withContext[i]; - } - } - - <span class="hljs-keyword">var</span> file = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, innerContext]); - - <span class="hljs-keyword">if</span> (file <span class="hljs-keyword">instanceof</span> Twig.Template) { - template = file; - } <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-207"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-207">¶</a> - </div> - <p>Import file</p> - - </div> - - <div class="content"><div class='highlight'><pre> template = <span class="hljs-keyword">this</span>.importFile(file); - } - - <span class="hljs-keyword">return</span> { - chain: chain, - output: template.render(innerContext) - }; - } - }, - { - type: Twig.logic.type.spaceless, - regex: <span class="hljs-regexp">/^spaceless$/</span>, - next: [ - Twig.logic.type.endspaceless - ], - open: <span class="hljs-literal">true</span>,</pre></div></div> - - </li> - - - <li id="section-208"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-208">¶</a> - </div> - <p>Parse the html and return it without any spaces between tags</p> - - </div> - - <div class="content"><div class='highlight'><pre> parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> <span class="hljs-comment">// Parse the output without any filter</span> - unfiltered = Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, context]),</pre></div></div> - - </li> - - - <li id="section-209"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-209">¶</a> - </div> - <p>A regular expression to find closing and opening tags with spaces between them</p> - - </div> - - <div class="content"><div class='highlight'><pre> rBetweenTagSpaces = <span class="hljs-regexp">/>\s+</g</span>,</pre></div></div> - - </li> - - - <li id="section-210"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-210">¶</a> - </div> - <p>Replace all space between closing and opening html tags</p> - - </div> - - <div class="content"><div class='highlight'><pre> output = unfiltered.replace(rBetweenTagSpaces,<span class="hljs-string">'><'</span>).trim(); - - <span class="hljs-keyword">return</span> { - chain: chain, - output: output - }; - } - },</pre></div></div> - - </li> - - - <li id="section-211"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-211">¶</a> - </div> - <p>Add the {% endspaceless %} token</p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.logic.type.endspaceless, - regex: <span class="hljs-regexp">/^endspaceless$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - }, - { - <span class="hljs-comment">/** - * Macro logic tokens. - * - * Format: {% maro input(name, value, type, size) %} - * - */</span> - type: Twig.logic.type.macro, - regex: <span class="hljs-regexp">/^macro\s+([a-zA-Z0-9_]+)\s*\(\s*((?:[a-zA-Z0-9_]+(?:,\s*)?)*)\s*\)$/</span>, - next: [ - Twig.logic.type.endmacro - ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> macroName = token.match[<span class="hljs-number">1</span>], - parameters = token.match[<span class="hljs-number">2</span>].split(<span class="hljs-regexp">/[\s,]+/</span>);</pre></div></div> - - </li> - - - <li id="section-212"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-212">¶</a> - </div> - <p>TODO: Clean up duplicate check</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>; i<parameters.length; i++) { - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> j=<span class="hljs-number">0</span>; j<parameters.length; j++){ - <span class="hljs-keyword">if</span> (parameters[i] === parameters[j] && i !== j) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Duplicate arguments for parameter: "</span>+ parameters[i]); - } - } - } - - token.macroName = macroName; - token.parameters = parameters; - - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> template = <span class="hljs-keyword">this</span>; - <span class="hljs-keyword">this</span>.macros[token.macroName] = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{</pre></div></div> - - </li> - - - <li id="section-213"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-213">¶</a> - </div> - <p>Pass global context and other macros</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> macroContext = { - _self: template.macros - }</pre></div></div> - - </li> - - - <li id="section-214"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-214">¶</a> - </div> - <p>Add parameters from context to macroContext</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>; i<token.parameters.length; i++) { - <span class="hljs-keyword">var</span> prop = token.parameters[i]; - <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">arguments</span>[i] !== <span class="hljs-string">'undefined'</span>) { - macroContext[prop] = <span class="hljs-built_in">arguments</span>[i]; - } <span class="hljs-keyword">else</span> { - macroContext[prop] = <span class="hljs-literal">undefined</span>; - } - }</pre></div></div> - - </li> - - - <li id="section-215"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-215">¶</a> - </div> - <p>Render</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> Twig.parse.apply(template, [token.output, macroContext]) - }; - - <span class="hljs-keyword">return</span> { - chain: chain, - output: <span class="hljs-string">''</span> - }; - - } - }, - { - <span class="hljs-comment">/** - * End macro logic tokens. - * - * Format: {% endmacro %} - */</span> - type: Twig.logic.type.endmacro, - regex: <span class="hljs-regexp">/^endmacro$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - }, - { - <span class="hljs-comment">/* - * import logic tokens. - * - * Format: {% import "template.twig" as form %} - */</span> - type: Twig.logic.type.import_, - regex: <span class="hljs-regexp">/^import\s+(.+)\s+as\s+([a-zA-Z0-9_]+)$/</span>, - next: [ ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = token.match[<span class="hljs-number">1</span>].trim(), - contextName = token.match[<span class="hljs-number">2</span>].trim(); - <span class="hljs-keyword">delete</span> token.match; - - token.expression = expression; - token.contextName = contextName; - - token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">if</span> (token.expression !== <span class="hljs-string">"_self"</span>) { - <span class="hljs-keyword">var</span> file = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, context]); - <span class="hljs-keyword">var</span> template = <span class="hljs-keyword">this</span>.importFile(file || token.expression); - context[token.contextName] = template.render({}, {output: <span class="hljs-string">'macros'</span>}); - } - <span class="hljs-keyword">else</span> { - context[token.contextName] = <span class="hljs-keyword">this</span>.macros; - } - - <span class="hljs-keyword">return</span> { - chain: chain, - output: <span class="hljs-string">''</span> - } - - } - }, - { - <span class="hljs-comment">/* - * from logic tokens. - * - * Format: {% from "template.twig" import func as form %} - */</span> - type: Twig.logic.type.from, - regex: <span class="hljs-regexp">/^from\s+(.+)\s+import\s+([a-zA-Z0-9_, ]+)$/</span>, - next: [ ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = token.match[<span class="hljs-number">1</span>].trim(), - macroExpressions = token.match[<span class="hljs-number">2</span>].trim().split(<span class="hljs-regexp">/[ ,]+/</span>), - macroNames = {}; - - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>; i<macroExpressions.length; i++) { - <span class="hljs-keyword">var</span> res = macroExpressions[i];</pre></div></div> - - </li> - - - <li id="section-216"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-216">¶</a> - </div> - <p>match function as variable</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> macroMatch = res.match(<span class="hljs-regexp">/^([a-zA-Z0-9_]+)\s+(.+)\s+as\s+([a-zA-Z0-9_]+)$/</span>); - <span class="hljs-keyword">if</span> (macroMatch) { - macroNames[macroMatch[<span class="hljs-number">1</span>].trim()] = macroMatch[<span class="hljs-number">2</span>].trim(); - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (res.match(<span class="hljs-regexp">/^([a-zA-Z0-9_]+)$/</span>)) { - macroNames[res] = res; - } - <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-217"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-217">¶</a> - </div> - <p>ignore import</p> - - </div> - - <div class="content"><div class='highlight'><pre> } - - } - - <span class="hljs-keyword">delete</span> token.match; - - token.expression = expression; - token.macroNames = macroNames; - - token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> macros; - - <span class="hljs-keyword">if</span> (token.expression !== <span class="hljs-string">"_self"</span>) { - <span class="hljs-keyword">var</span> file = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, context]); - <span class="hljs-keyword">var</span> template = <span class="hljs-keyword">this</span>.importFile(file || token.expression); - macros = template.render({}, {output: <span class="hljs-string">'macros'</span>}); - } - <span class="hljs-keyword">else</span> { - macros = <span class="hljs-keyword">this</span>.macros; - } - - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> macroName <span class="hljs-keyword">in</span> token.macroNames) { - <span class="hljs-keyword">if</span> (macros.hasOwnProperty(macroName)) { - context[token.macroNames[macroName]] = macros[macroName]; - } - } - - <span class="hljs-keyword">return</span> { - chain: chain, - output: <span class="hljs-string">''</span> - } - - } - }, - { - <span class="hljs-comment">/** - * The embed tag combines the behaviour of include and extends. - * It allows you to include another template's contents, just like include does. - * - * Format: {% embed "template.twig" [with {some: 'values'} only] %} - */</span> - type: Twig.logic.type.embed, - regex: <span class="hljs-regexp">/^embed\s+(ignore missing\s+)?(.+?)\s*(?:with\s+(.+?))?\s*(only)?$/</span>, - next: [ - Twig.logic.type.endembed - ], - open: <span class="hljs-literal">true</span>, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - <span class="hljs-keyword">var</span> match = token.match, - includeMissing = match[<span class="hljs-number">1</span>] !== <span class="hljs-literal">undefined</span>, - expression = match[<span class="hljs-number">2</span>].trim(), - withContext = match[<span class="hljs-number">3</span>], - only = ((match[<span class="hljs-number">4</span>] !== <span class="hljs-literal">undefined</span>) && match[<span class="hljs-number">4</span>].length); - - <span class="hljs-keyword">delete</span> token.match; - - token.only = only; - token.includeMissing = includeMissing; - - token.stack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: expression - }]).stack; - - <span class="hljs-keyword">if</span> (withContext !== <span class="hljs-literal">undefined</span>) { - token.withStack = Twig.expression.compile.apply(<span class="hljs-keyword">this</span>, [{ - type: Twig.expression.type.expression, - value: withContext.trim() - }]).stack; - } - - <span class="hljs-keyword">return</span> token; - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-218"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-218">¶</a> - </div> - <p>Resolve filename</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> innerContext = {}, - withContext, - i, - template; - - <span class="hljs-keyword">if</span> (!token.only) { - <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> context) { - <span class="hljs-keyword">if</span> (context.hasOwnProperty(i)) - innerContext[i] = context[i]; - } - } - - <span class="hljs-keyword">if</span> (token.withStack !== <span class="hljs-literal">undefined</span>) { - withContext = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.withStack, context]); - - <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> withContext) { - <span class="hljs-keyword">if</span> (withContext.hasOwnProperty(i)) - innerContext[i] = withContext[i]; - } - } - - <span class="hljs-keyword">var</span> file = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, innerContext]); - - <span class="hljs-keyword">if</span> (file <span class="hljs-keyword">instanceof</span> Twig.Template) { - template = file; - } <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-219"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-219">¶</a> - </div> - <p>Import file</p> - - </div> - - <div class="content"><div class='highlight'><pre> template = <span class="hljs-keyword">this</span>.importFile(file); - }</pre></div></div> - - </li> - - - <li id="section-220"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-220">¶</a> - </div> - <p>reset previous blocks</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">this</span>.blocks = {};</pre></div></div> - - </li> - - - <li id="section-221"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-221">¶</a> - </div> - <p>parse tokens. output will be not used</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> output = Twig.parse.apply(<span class="hljs-keyword">this</span>, [token.output, innerContext]);</pre></div></div> - - </li> - - - <li id="section-222"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-222">¶</a> - </div> - <p>render tempalte with blocks defined in embed block</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> { - chain: chain, - output: template.render(innerContext, {<span class="hljs-string">'blocks'</span>:<span class="hljs-keyword">this</span>.blocks}) - }; - } - }, - <span class="hljs-comment">/* Add the {% endembed %} token - * - */</span> - { - type: Twig.logic.type.endembed, - regex: <span class="hljs-regexp">/^endembed$/</span>, - next: [ ], - open: <span class="hljs-literal">false</span> - } - - ]; - - - <span class="hljs-comment">/** - * Registry for logic handlers. - */</span> - Twig.logic.handler = {}; - - <span class="hljs-comment">/** - * Define a new token type, available at Twig.logic.type.{type} - */</span> - Twig.logic.extendType = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">type, value</span>) </span>{ - value = value || (<span class="hljs-string">"Twig.logic.type"</span> + type); - Twig.logic.type[type] = value; - }; - - <span class="hljs-comment">/** - * Extend the logic parsing functionality with a new token definition. - * - * // Define a new tag - * Twig.logic.extend({ - * type: Twig.logic.type.{type}, - * // The pattern to match for this token - * regex: ..., - * // What token types can follow this token, leave blank if any. - * next: [ ... ] - * // Create and return compiled version of the token - * compile: function(token) { ... } - * // Parse the compiled token with the context provided by the render call - * // and whether this token chain is complete. - * parse: function(token, context, chain) { ... } - * }); - * - * @param {Object} definition The new logic expression. - */</span> - Twig.logic.extend = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">definition</span>) </span>{ - - <span class="hljs-keyword">if</span> (!definition.type) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to extend logic definition. No type provided for "</span> + definition); - } <span class="hljs-keyword">else</span> { - Twig.logic.extendType(definition.type); - } - Twig.logic.handler[definition.type] = definition; - };</pre></div></div> - - </li> - - - <li id="section-223"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-223">¶</a> - </div> - <p>Extend with built-in expressions</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> (Twig.logic.definitions.length > <span class="hljs-number">0</span>) { - Twig.logic.extend(Twig.logic.definitions.shift()); - } - - <span class="hljs-comment">/** - * Compile a logic token into an object ready for parsing. - * - * @param {Object} raw_token An uncompiled logic token. - * - * @return {Object} A compiled logic token, ready for parsing. - */</span> - Twig.logic.compile = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">raw_token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = raw_token.value.trim(), - token = Twig.logic.tokenize.apply(<span class="hljs-keyword">this</span>, [expression]), - token_template = Twig.logic.handler[token.type];</pre></div></div> - - </li> - - - <li id="section-224"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-224">¶</a> - </div> - <p>Check if the token needs compiling</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (token_template.compile) { - token = token_template.compile.apply(<span class="hljs-keyword">this</span>, [token]); - Twig.log.trace(<span class="hljs-string">"Twig.logic.compile: "</span>, <span class="hljs-string">"Compiled logic token to "</span>, token); - } - - <span class="hljs-keyword">return</span> token; - }; - - <span class="hljs-comment">/** - * Tokenize logic expressions. This function matches token expressions against regular - * expressions provided in token definitions provided with Twig.logic.extend. - * - * @param {string} expression the logic token expression to tokenize - * (i.e. what's between {% and %}) - * - * @return {Object} The matched token with type set to the token type and match to the regex match. - */</span> - Twig.logic.tokenize = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">expression</span>) </span>{ - <span class="hljs-keyword">var</span> token = {}, - token_template_type = <span class="hljs-literal">null</span>, - token_type = <span class="hljs-literal">null</span>, - token_regex = <span class="hljs-literal">null</span>, - regex_array = <span class="hljs-literal">null</span>, - regex = <span class="hljs-literal">null</span>, - match = <span class="hljs-literal">null</span>;</pre></div></div> - - </li> - - - <li id="section-225"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-225">¶</a> - </div> - <p>Ignore whitespace around expressions.</p> - - </div> - - <div class="content"><div class='highlight'><pre> expression = expression.trim(); - - <span class="hljs-keyword">for</span> (token_template_type <span class="hljs-keyword">in</span> Twig.logic.handler) { - <span class="hljs-keyword">if</span> (Twig.logic.handler.hasOwnProperty(token_template_type)) {</pre></div></div> - - </li> - - - <li id="section-226"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-226">¶</a> - </div> - <p>Get the type and regex for this template type</p> - - </div> - - <div class="content"><div class='highlight'><pre> token_type = Twig.logic.handler[token_template_type].type; - token_regex = Twig.logic.handler[token_template_type].regex;</pre></div></div> - - </li> - - - <li id="section-227"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-227">¶</a> - </div> - <p>Handle multiple regular expressions per type.</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex_array = []; - <span class="hljs-keyword">if</span> (token_regex <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) { - regex_array = token_regex; - } <span class="hljs-keyword">else</span> { - regex_array.push(token_regex); - }</pre></div></div> - - </li> - - - <li id="section-228"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-228">¶</a> - </div> - <p>Check regular expressions in the order they were specified in the definition.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> (regex_array.length > <span class="hljs-number">0</span>) { - regex = regex_array.shift(); - match = regex.exec(expression.trim()); - <span class="hljs-keyword">if</span> (match !== <span class="hljs-literal">null</span>) { - token.type = token_type; - token.match = match; - Twig.log.trace(<span class="hljs-string">"Twig.logic.tokenize: "</span>, <span class="hljs-string">"Matched a "</span>, token_type, <span class="hljs-string">" regular expression of "</span>, match); - <span class="hljs-keyword">return</span> token; - } - } - } - }</pre></div></div> - - </li> - - - <li id="section-229"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-229">¶</a> - </div> - <p>No regex matches</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to parse '"</span> + expression.trim() + <span class="hljs-string">"'"</span>); - }; - - <span class="hljs-comment">/** - * Parse a logic token within a given context. - * - * What are logic chains? - * Logic chains represent a series of tokens that are connected, - * for example: - * {% if ... %} {% else %} {% endif %} - * - * The chain parameter is used to signify if a chain is open of closed. - * open: - * More tokens in this chain should be parsed. - * closed: - * This token chain has completed parsing and any additional - * tokens (else, elseif, etc...) should be ignored. - * - * @param {Object} token The compiled token. - * @param {Object} context The render context. - * @param {boolean} chain Is this an open logic chain. If false, that means a - * chain is closed and no further cases should be parsed. - */</span> - Twig.logic.parse = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token, context, chain</span>) </span>{ - <span class="hljs-keyword">var</span> output = <span class="hljs-string">''</span>, - token_template; - - context = context || { }; - - Twig.log.debug(<span class="hljs-string">"Twig.logic.parse: "</span>, <span class="hljs-string">"Parsing logic token "</span>, token); - - token_template = Twig.logic.handler[token.type]; - - <span class="hljs-keyword">if</span> (token_template.parse) { - output = token_template.parse.apply(<span class="hljs-keyword">this</span>, [token, context, chain]); - } - <span class="hljs-keyword">return</span> output; - }; - - <span class="hljs-keyword">return</span> Twig; - -})(Twig || { });</pre></div></div> - - </li> - - - <li id="section-230"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-230">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-231"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-231">¶</a> - </div> - <h2 id="twig-expression-js">twig.expression.js</h2> -<p>This file handles tokenizing, compiling and parsing expressions.</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> "use strict"</span>; - - <span class="hljs-comment">/** - * Namespace for expression handling. - */</span> - Twig.expression = { }; - - <span class="hljs-comment">/** - * Reserved word that can't be used as variable names. - */</span> - Twig.expression.reservedWords = [ - <span class="hljs-string">"true"</span>, <span class="hljs-string">"false"</span>, <span class="hljs-string">"null"</span>, <span class="hljs-string">"TRUE"</span>, <span class="hljs-string">"FALSE"</span>, <span class="hljs-string">"NULL"</span>, <span class="hljs-string">"_context"</span> - ]; - - <span class="hljs-comment">/** - * The type of tokens used in expressions. - */</span> - Twig.expression.type = { - comma: <span class="hljs-string">'Twig.expression.type.comma'</span>, - operator: { - unary: <span class="hljs-string">'Twig.expression.type.operator.unary'</span>, - binary: <span class="hljs-string">'Twig.expression.type.operator.binary'</span> - }, - string: <span class="hljs-string">'Twig.expression.type.string'</span>, - bool: <span class="hljs-string">'Twig.expression.type.bool'</span>, - array: { - start: <span class="hljs-string">'Twig.expression.type.array.start'</span>, - end: <span class="hljs-string">'Twig.expression.type.array.end'</span> - }, - object: { - start: <span class="hljs-string">'Twig.expression.type.object.start'</span>, - end: <span class="hljs-string">'Twig.expression.type.object.end'</span> - }, - parameter: { - start: <span class="hljs-string">'Twig.expression.type.parameter.start'</span>, - end: <span class="hljs-string">'Twig.expression.type.parameter.end'</span> - }, - key: { - period: <span class="hljs-string">'Twig.expression.type.key.period'</span>, - brackets: <span class="hljs-string">'Twig.expression.type.key.brackets'</span> - }, - filter: <span class="hljs-string">'Twig.expression.type.filter'</span>, - _function: <span class="hljs-string">'Twig.expression.type._function'</span>, - variable: <span class="hljs-string">'Twig.expression.type.variable'</span>, - number: <span class="hljs-string">'Twig.expression.type.number'</span>, - _null: <span class="hljs-string">'Twig.expression.type.null'</span>, - context: <span class="hljs-string">'Twig.expression.type.context'</span>, - test: <span class="hljs-string">'Twig.expression.type.test'</span> - }; - - Twig.expression.set = {</pre></div></div> - - </li> - - - <li id="section-232"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-232">¶</a> - </div> - <p>What can follow an expression (in general)</p> - - </div> - - <div class="content"><div class='highlight'><pre> operations: [ - Twig.expression.type.filter, - Twig.expression.type.operator.unary, - Twig.expression.type.operator.binary, - Twig.expression.type.array.end, - Twig.expression.type.object.end, - Twig.expression.type.parameter.end, - Twig.expression.type.comma, - Twig.expression.type.test - ], - expressions: [ - Twig.expression.type._function, - Twig.expression.type.bool, - Twig.expression.type.string, - Twig.expression.type.variable, - Twig.expression.type.number, - Twig.expression.type._null, - Twig.expression.type.context, - Twig.expression.type.parameter.start, - Twig.expression.type.array.start, - Twig.expression.type.object.start - ] - };</pre></div></div> - - </li> - - - <li id="section-233"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-233">¶</a> - </div> - <p>Most expressions allow a ‘.’ or ‘[‘ after them, so we provide a convenience set</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.expression.set.operations_extended = Twig.expression.set.operations.concat([ - Twig.expression.type.key.period, - Twig.expression.type.key.brackets]);</pre></div></div> - - </li> - - - <li id="section-234"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-234">¶</a> - </div> - <p>Some commonly used compile and parse functions.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.expression.fn = { - compile: { - push: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - output.push(token); - }, - push_both: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - output.push(token); - stack.push(token); - } - }, - parse: { - push: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - stack.push(token); - }, - push_value: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - stack.push(token.value); - } - } - };</pre></div></div> - - </li> - - - <li id="section-235"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-235">¶</a> - </div> - <p>The regular expressions and compile/parse logic used to match tokens in expressions.</p> -<p>Properties:</p> -<pre><code> type: The type <span class="hljs-keyword">of</span> expression <span class="hljs-keyword">this</span> matches - - regex: One or more regular expressions that matche the format <span class="hljs-keyword">of</span> the token. - - next: Valid tokens that can occur next <span class="hljs-keyword">in</span> the expression. -</code></pre><p>Functions:</p> -<pre><code> compile: A <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">that</span> <span class="hljs-title">compiles</span> <span class="hljs-title">the</span> <span class="hljs-title">raw</span> <span class="hljs-title">regular</span> <span class="hljs-title">expression</span> <span class="hljs-title">match</span> <span class="hljs-title">into</span> <span class="hljs-title">a</span> <span class="hljs-title">token</span>. - - <span class="hljs-title">parse</span>: <span class="hljs-title">A</span> <span class="hljs-title">function</span> <span class="hljs-title">that</span> <span class="hljs-title">parses</span> <span class="hljs-title">the</span> <span class="hljs-title">compiled</span> <span class="hljs-title">token</span> <span class="hljs-title">into</span> <span class="hljs-title">output</span>.</span> -</code></pre> - </div> - - <div class="content"><div class='highlight'><pre> Twig.expression.definitions = [ - { - type: Twig.expression.type.test, - regex: <span class="hljs-regexp">/^is\s+(not)?\s*([a-zA-Z_][a-zA-Z0-9_]*)/</span>, - next: Twig.expression.set.operations.concat([Twig.expression.type.parameter.start]), - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - token.filter = token.match[<span class="hljs-number">2</span>]; - token.modifier = token.match[<span class="hljs-number">1</span>]; - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">delete</span> token.value; - output.push(token); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - <span class="hljs-keyword">var</span> value = stack.pop(), - params = token.params && Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.params, context]), - result = Twig.test(token.filter, value, params); - - <span class="hljs-keyword">if</span> (token.modifier == <span class="hljs-string">'not'</span>) { - stack.push(!result); - } <span class="hljs-keyword">else</span> { - stack.push(result); - } - } - }, - { - type: Twig.expression.type.comma,</pre></div></div> - - </li> - - - <li id="section-236"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-236">¶</a> - </div> - <p>Match a comma</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/^,/</span>, - next: Twig.expression.set.expressions.concat([Twig.expression.type.array.end, Twig.expression.type.object.end]), - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">var</span> i = stack.length - <span class="hljs-number">1</span>, - stack_token; - - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">delete</span> token.value;</pre></div></div> - - </li> - - - <li id="section-237"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-237">¶</a> - </div> - <p>pop tokens off the stack until the start of the object</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span>(;i >= <span class="hljs-number">0</span>; i--) { - stack_token = stack.pop(); - <span class="hljs-keyword">if</span> (stack_token.type === Twig.expression.type.object.start - || stack_token.type === Twig.expression.type.parameter.start - || stack_token.type === Twig.expression.type.array.start) { - stack.push(stack_token); - <span class="hljs-keyword">break</span>; - } - output.push(stack_token); - } - output.push(token); - } - }, - { - type: Twig.expression.type.operator.binary,</pre></div></div> - - </li> - - - <li id="section-238"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-238">¶</a> - </div> - <p>Match any of +, <em>, /, -, %, ~, <, <=, >, >=, !=, ==, *</em>, ?, :, and, or, not</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/(^[\+\-~%\?\:]|^[!=]==?|^[!<>]=?|^\*\*?|^\/\/?|^and\s+|^or\s+|^in\s+|^not in\s+|^\.\.)/</span>, - next: Twig.expression.set.expressions.concat([Twig.expression.type.operator.unary]), - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">delete</span> token.match; - - token.value = token.value.trim(); - <span class="hljs-keyword">var</span> value = token.value, - operator = Twig.expression.operator.lookup(value, token); - - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"Operator: "</span>, operator, <span class="hljs-string">" from "</span>, value); - - <span class="hljs-keyword">while</span> (stack.length > <span class="hljs-number">0</span> && - (stack[stack.length<span class="hljs-number">-1</span>].type == Twig.expression.type.operator.unary || stack[stack.length<span class="hljs-number">-1</span>].type == Twig.expression.type.operator.binary) && - ( - (operator.associativity === Twig.expression.operator.leftToRight && - operator.precidence >= stack[stack.length<span class="hljs-number">-1</span>].precidence) || - - (operator.associativity === Twig.expression.operator.rightToLeft && - operator.precidence > stack[stack.length<span class="hljs-number">-1</span>].precidence) - ) - ) { - <span class="hljs-keyword">var</span> temp = stack.pop(); - output.push(temp); - } - - <span class="hljs-keyword">if</span> (value === <span class="hljs-string">":"</span>) {</pre></div></div> - - </li> - - - <li id="section-239"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-239">¶</a> - </div> - <p>Check if this is a ternary or object key being set</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (stack[stack.length - <span class="hljs-number">1</span>] && stack[stack.length<span class="hljs-number">-1</span>].value === <span class="hljs-string">"?"</span>) {</pre></div></div> - - </li> - - - <li id="section-240"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-240">¶</a> - </div> - <p>Continue as normal for a ternary</p> - - </div> - - <div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-241"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-241">¶</a> - </div> - <p>This is not a ternary so we push the token to the output where it can be handled - when the assocated object is closed.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> key_token = output.pop(); - - <span class="hljs-keyword">if</span> (key_token.type === Twig.expression.type.string || - key_token.type === Twig.expression.type.variable) { - token.key = key_token.value; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (key_token.type === Twig.expression.type.number) {</pre></div></div> - - </li> - - - <li id="section-242"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-242">¶</a> - </div> - <p>Convert integer keys into string keys</p> - - </div> - - <div class="content"><div class='highlight'><pre> token.key = key_token.value.toString(); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (key_token.type === Twig.expression.type.parameter.end && - key_token.expression) { - token.params = key_token.params; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unexpected value before ':' of "</span> + key_token.type + <span class="hljs-string">" = "</span> + key_token.value); - } - - output.push(token); - <span class="hljs-keyword">return</span>; - } - } <span class="hljs-keyword">else</span> { - stack.push(operator); - } - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - <span class="hljs-keyword">if</span> (token.key) {</pre></div></div> - - </li> - - - <li id="section-243"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-243">¶</a> - </div> - <p>handle ternary ‘:’ operator</p> - - </div> - - <div class="content"><div class='highlight'><pre> stack.push(token); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (token.params) {</pre></div></div> - - </li> - - - <li id="section-244"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-244">¶</a> - </div> - <p>handle “{(expression):value}”</p> - - </div> - - <div class="content"><div class='highlight'><pre> token.key = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.params, context]); - stack.push(token); - <span class="hljs-keyword">delete</span>(token.params); - } <span class="hljs-keyword">else</span> { - Twig.expression.operator.parse(token.value, stack); - } - } - }, - { - type: Twig.expression.type.operator.unary,</pre></div></div> - - </li> - - - <li id="section-245"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-245">¶</a> - </div> - <p>Match any of not</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/(^not\s+)/</span>, - next: Twig.expression.set.expressions, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">delete</span> token.match; - - token.value = token.value.trim(); - <span class="hljs-keyword">var</span> value = token.value, - operator = Twig.expression.operator.lookup(value, token); - - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"Operator: "</span>, operator, <span class="hljs-string">" from "</span>, value); - - <span class="hljs-keyword">while</span> (stack.length > <span class="hljs-number">0</span> && - (stack[stack.length<span class="hljs-number">-1</span>].type == Twig.expression.type.operator.unary || stack[stack.length<span class="hljs-number">-1</span>].type == Twig.expression.type.operator.binary) && - ( - (operator.associativity === Twig.expression.operator.leftToRight && - operator.precidence >= stack[stack.length<span class="hljs-number">-1</span>].precidence) || - - (operator.associativity === Twig.expression.operator.rightToLeft && - operator.precidence > stack[stack.length<span class="hljs-number">-1</span>].precidence) - ) - ) { - <span class="hljs-keyword">var</span> temp = stack.pop(); - output.push(temp); - } - - stack.push(operator); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - Twig.expression.operator.parse(token.value, stack); - } - }, - { - <span class="hljs-comment">/** - * Match a string. This is anything between a pair of single or double quotes. - */</span> - type: Twig.expression.type.string,</pre></div></div> - - </li> - - - <li id="section-246"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-246">¶</a> - </div> - <p>See: <a href="http://blog.stevenlevithan.com/archives/match-quoted-string">http://blog.stevenlevithan.com/archives/match-quoted-string</a></p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/^(["'])(?:(?=(\\?))\2[\s\S])*?\1/</span>, - next: Twig.expression.set.operations, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">var</span> value = token.value; - <span class="hljs-keyword">delete</span> token.match</pre></div></div> - - </li> - - - <li id="section-247"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-247">¶</a> - </div> - <p>Remove the quotes from the string</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (value.substring(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>) === <span class="hljs-string">'"'</span>) { - value = value.replace(<span class="hljs-string">'\\"'</span>, <span class="hljs-string">'"'</span>); - } <span class="hljs-keyword">else</span> { - value = value.replace(<span class="hljs-string">"\\'"</span>, <span class="hljs-string">"'"</span>); - } - token.value = value.substring(<span class="hljs-number">1</span>, value.length<span class="hljs-number">-1</span>).replace( <span class="hljs-regexp">/\\n/g</span>, <span class="hljs-string">"\n"</span> ).replace( <span class="hljs-regexp">/\\r/g</span>, <span class="hljs-string">"\r"</span> ); - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"String value: "</span>, token.value); - output.push(token); - }, - parse: Twig.expression.fn.parse.push_value - }, - { - <span class="hljs-comment">/** - * Match a parameter set start. - */</span> - type: Twig.expression.type.parameter.start, - regex: <span class="hljs-regexp">/^\(/</span>, - next: Twig.expression.set.expressions.concat([Twig.expression.type.parameter.end]), - compile: Twig.expression.fn.compile.push_both, - parse: Twig.expression.fn.parse.push - }, - { - <span class="hljs-comment">/** - * Match a parameter set end. - */</span> - type: Twig.expression.type.parameter.end, - regex: <span class="hljs-regexp">/^\)/</span>, - next: Twig.expression.set.operations_extended, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">var</span> stack_token, - end_token = token; - - stack_token = stack.pop(); - <span class="hljs-keyword">while</span>(stack.length > <span class="hljs-number">0</span> && stack_token.type != Twig.expression.type.parameter.start) { - output.push(stack_token); - stack_token = stack.pop(); - }</pre></div></div> - - </li> - - - <li id="section-248"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-248">¶</a> - </div> - <p>Move contents of parens into preceding filter</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> param_stack = []; - <span class="hljs-keyword">while</span>(token.type !== Twig.expression.type.parameter.start) {</pre></div></div> - - </li> - - - <li id="section-249"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-249">¶</a> - </div> - <p>Add token to arguments stack</p> - - </div> - - <div class="content"><div class='highlight'><pre> param_stack.unshift(token); - token = output.pop(); - } - param_stack.unshift(token); - - <span class="hljs-keyword">var</span> is_expression = <span class="hljs-literal">false</span>;</pre></div></div> - - </li> - - - <li id="section-250"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-250">¶</a> - </div> - <p>Get the token preceding the parameters</p> - - </div> - - <div class="content"><div class='highlight'><pre> token = output[output.length<span class="hljs-number">-1</span>]; - - <span class="hljs-keyword">if</span> (token === <span class="hljs-literal">undefined</span> || - (token.type !== Twig.expression.type._function && - token.type !== Twig.expression.type.filter && - token.type !== Twig.expression.type.test && - token.type !== Twig.expression.type.key.brackets && - token.type !== Twig.expression.type.key.period)) { - - end_token.expression = <span class="hljs-literal">true</span>;</pre></div></div> - - </li> - - - <li id="section-251"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-251">¶</a> - </div> - <p>remove start and end token from stack</p> - - </div> - - <div class="content"><div class='highlight'><pre> param_stack.pop(); - param_stack.shift(); - - end_token.params = param_stack; - - output.push(end_token); - - } <span class="hljs-keyword">else</span> { - end_token.expression = <span class="hljs-literal">false</span>; - token.params = param_stack; - } - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - <span class="hljs-keyword">var</span> new_array = [], - array_ended = <span class="hljs-literal">false</span>, - value = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">if</span> (token.expression) { - value = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.params, context]) - stack.push(value); - - } <span class="hljs-keyword">else</span> { - - <span class="hljs-keyword">while</span> (stack.length > <span class="hljs-number">0</span>) { - value = stack.pop();</pre></div></div> - - </li> - - - <li id="section-252"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-252">¶</a> - </div> - <p>Push values into the array until the start of the array</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (value && value.type && value.type == Twig.expression.type.parameter.start) { - array_ended = <span class="hljs-literal">true</span>; - <span class="hljs-keyword">break</span>; - } - new_array.unshift(value); - } - - <span class="hljs-keyword">if</span> (!array_ended) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Expected end of parameter set."</span>); - } - - stack.push(new_array); - } - } - }, - { - <span class="hljs-comment">/** - * Match an array start. - */</span> - type: Twig.expression.type.array.start, - regex: <span class="hljs-regexp">/^\[/</span>, - next: Twig.expression.set.expressions.concat([Twig.expression.type.array.end]), - compile: Twig.expression.fn.compile.push_both, - parse: Twig.expression.fn.parse.push - }, - { - <span class="hljs-comment">/** - * Match an array end. - */</span> - type: Twig.expression.type.array.end, - regex: <span class="hljs-regexp">/^\]/</span>, - next: Twig.expression.set.operations_extended, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">var</span> i = stack.length - <span class="hljs-number">1</span>, - stack_token;</pre></div></div> - - </li> - - - <li id="section-253"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-253">¶</a> - </div> - <p>pop tokens off the stack until the start of the object</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span>(;i >= <span class="hljs-number">0</span>; i--) { - stack_token = stack.pop(); - <span class="hljs-keyword">if</span> (stack_token.type === Twig.expression.type.array.start) { - <span class="hljs-keyword">break</span>; - } - output.push(stack_token); - } - output.push(token); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - <span class="hljs-keyword">var</span> new_array = [], - array_ended = <span class="hljs-literal">false</span>, - value = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">while</span> (stack.length > <span class="hljs-number">0</span>) { - value = stack.pop();</pre></div></div> - - </li> - - - <li id="section-254"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-254">¶</a> - </div> - <p>Push values into the array until the start of the array</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (value.type && value.type == Twig.expression.type.array.start) { - array_ended = <span class="hljs-literal">true</span>; - <span class="hljs-keyword">break</span>; - } - new_array.unshift(value); - } - <span class="hljs-keyword">if</span> (!array_ended) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Expected end of array."</span>); - } - - stack.push(new_array); - } - },</pre></div></div> - - </li> - - - <li id="section-255"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-255">¶</a> - </div> - <p>Token that represents the start of a hash map ‘}’</p> -<p>Hash maps take the form: - { “key”: ‘value’, “another_key”: item }</p> -<p>Keys must be quoted (either single or double) and values can be any expression.</p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.expression.type.object.start, - regex: <span class="hljs-regexp">/^\{/</span>, - next: Twig.expression.set.expressions.concat([Twig.expression.type.object.end]), - compile: Twig.expression.fn.compile.push_both, - parse: Twig.expression.fn.parse.push - },</pre></div></div> - - </li> - - - <li id="section-256"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-256">¶</a> - </div> - <p>Token that represents the end of a Hash Map ‘}’</p> -<p>This is where the logic for building the internal -representation of a hash map is defined.</p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.expression.type.object.end, - regex: <span class="hljs-regexp">/^\}/</span>, - next: Twig.expression.set.operations_extended, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">var</span> i = stack.length<span class="hljs-number">-1</span>, - stack_token;</pre></div></div> - - </li> - - - <li id="section-257"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-257">¶</a> - </div> - <p>pop tokens off the stack until the start of the object</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span>(;i >= <span class="hljs-number">0</span>; i--) { - stack_token = stack.pop(); - <span class="hljs-keyword">if</span> (stack_token && stack_token.type === Twig.expression.type.object.start) { - <span class="hljs-keyword">break</span>; - } - output.push(stack_token); - } - output.push(token); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">end_token, stack, context</span>) </span>{ - <span class="hljs-keyword">var</span> new_object = {}, - object_ended = <span class="hljs-literal">false</span>, - token = <span class="hljs-literal">null</span>, - token_key = <span class="hljs-literal">null</span>, - has_value = <span class="hljs-literal">false</span>, - value = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">while</span> (stack.length > <span class="hljs-number">0</span>) { - token = stack.pop();</pre></div></div> - - </li> - - - <li id="section-258"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-258">¶</a> - </div> - <p>Push values into the array until the start of the object</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (token && token.type && token.type === Twig.expression.type.object.start) { - object_ended = <span class="hljs-literal">true</span>; - <span class="hljs-keyword">break</span>; - } - <span class="hljs-keyword">if</span> (token && token.type && (token.type === Twig.expression.type.operator.binary || token.type === Twig.expression.type.operator.unary) && token.key) { - <span class="hljs-keyword">if</span> (!has_value) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Missing value for key '"</span> + token.key + <span class="hljs-string">"' in object definition."</span>); - } - new_object[token.key] = value;</pre></div></div> - - </li> - - - <li id="section-259"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-259">¶</a> - </div> - <p>Preserve the order that elements are added to the map -This is necessary since JavaScript objects don’t -guarantee the order of keys</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (new_object._keys === <span class="hljs-literal">undefined</span>) new_object._keys = []; - new_object._keys.unshift(token.key);</pre></div></div> - - </li> - - - <li id="section-260"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-260">¶</a> - </div> - <p>reset value check</p> - - </div> - - <div class="content"><div class='highlight'><pre> value = <span class="hljs-literal">null</span>; - has_value = <span class="hljs-literal">false</span>; - - } <span class="hljs-keyword">else</span> { - has_value = <span class="hljs-literal">true</span>; - value = token; - } - } - <span class="hljs-keyword">if</span> (!object_ended) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unexpected end of object."</span>); - } - - stack.push(new_object); - } - },</pre></div></div> - - </li> - - - <li id="section-261"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-261">¶</a> - </div> - <p>Token representing a filter</p> -<p>Filters can follow any expression and take the form: - expression|filter(optional, args)</p> -<p>Filter parsing is done in the Twig.filters namespace.</p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.expression.type.filter,</pre></div></div> - - </li> - - - <li id="section-262"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-262">¶</a> - </div> - <p>match a | then a letter or <em>, then any number of letters, numbers, </em> or -</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/^\|\s?([a-zA-Z_][a-zA-Z0-9_\-]*)/</span>, - next: Twig.expression.set.operations_extended.concat([ - Twig.expression.type.parameter.start]), - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - token.value = token.match[<span class="hljs-number">1</span>]; - output.push(token); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - <span class="hljs-keyword">var</span> input = stack.pop(), - params = token.params && Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.params, context]); - - stack.push(Twig.filter.apply(<span class="hljs-keyword">this</span>, [token.value, input, params])); - } - }, - { - type: Twig.expression.type._function,</pre></div></div> - - </li> - - - <li id="section-263"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-263">¶</a> - </div> - <p>match any letter or <em>, then any number of letters, numbers, </em> or - followed by (</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/^([a-zA-Z_][a-zA-Z0-9_]*)\s*\(/</span>, - next: Twig.expression.type.parameter.start, - transform: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">match, tokens</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-string">'('</span>; - }, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">var</span> fn = token.match[<span class="hljs-number">1</span>]; - token.fn = fn;</pre></div></div> - - </li> - - - <li id="section-264"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-264">¶</a> - </div> - <p>cleanup token</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">delete</span> token.value; - - output.push(token); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - <span class="hljs-keyword">var</span> params = token.params && Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.params, context]), - fn = token.fn, - value; - - <span class="hljs-keyword">if</span> (Twig.functions[fn]) {</pre></div></div> - - </li> - - - <li id="section-265"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-265">¶</a> - </div> - <p>Get the function from the built-in functions</p> - - </div> - - <div class="content"><div class='highlight'><pre> value = Twig.functions[fn].apply(<span class="hljs-keyword">this</span>, params); - - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> context[fn] == <span class="hljs-string">'function'</span>) {</pre></div></div> - - </li> - - - <li id="section-266"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-266">¶</a> - </div> - <p>Get the function from the user/context defined functions</p> - - </div> - - <div class="content"><div class='highlight'><pre> value = context[fn].apply(context, params); - - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(fn + <span class="hljs-string">' function does not exist and is not defined in the context'</span>); - } - - stack.push(value); - } - },</pre></div></div> - - </li> - - - <li id="section-267"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-267">¶</a> - </div> - <p>Token representing a variable.</p> -<p>Variables can contain letters, numbers, underscores and -dashes, but must start with a letter or underscore.</p> -<p>Variables are retrieved from the render context and take -the value of ‘undefined’ if the given variable doesn’t -exist in the context.</p> - - </div> - - <div class="content"><div class='highlight'><pre> { - type: Twig.expression.type.variable,</pre></div></div> - - </li> - - - <li id="section-268"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-268">¶</a> - </div> - <p>match any letter or <em>, then any number of letters, numbers, </em> or -</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/^[a-zA-Z_][a-zA-Z0-9_]*/</span>, - next: Twig.expression.set.operations_extended.concat([ - Twig.expression.type.parameter.start]), - compile: Twig.expression.fn.compile.push, - validate: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">match, tokens</span>) </span>{ - <span class="hljs-keyword">return</span> (Twig.indexOf(Twig.expression.reservedWords, match[<span class="hljs-number">0</span>]) < <span class="hljs-number">0</span>); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-269"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-269">¶</a> - </div> - <p>Get the variable from the context</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> value = Twig.expression.resolve(context[token.value], context); - stack.push(value); - } - }, - { - type: Twig.expression.type.key.period, - regex: <span class="hljs-regexp">/^\.([a-zA-Z0-9_]+)/</span>, - next: Twig.expression.set.operations_extended.concat([ - Twig.expression.type.parameter.start]), - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - token.key = token.match[<span class="hljs-number">1</span>]; - <span class="hljs-keyword">delete</span> token.match; - <span class="hljs-keyword">delete</span> token.value; - - output.push(token); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - <span class="hljs-keyword">var</span> params = token.params && Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.params, context]), - key = token.key, - object = stack.pop(), - value; - - <span class="hljs-keyword">if</span> (object === <span class="hljs-literal">null</span> || object === <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.options.strict_variables) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Can't access a key "</span> + key + <span class="hljs-string">" on an null or undefined object."</span>); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; - } - } - - <span class="hljs-keyword">var</span> capitalize = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{<span class="hljs-keyword">return</span> value.substr(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>).toUpperCase() + value.substr(<span class="hljs-number">1</span>);};</pre></div></div> - - </li> - - - <li id="section-270"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-270">¶</a> - </div> - <p>Get the variable from the context</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object === <span class="hljs-string">'object'</span> && key <span class="hljs-keyword">in</span> object) { - value = object[key]; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (object[<span class="hljs-string">"get"</span>+capitalize(key)] !== <span class="hljs-literal">undefined</span>) { - value = object[<span class="hljs-string">"get"</span>+capitalize(key)]; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (object[<span class="hljs-string">"is"</span>+capitalize(key)] !== <span class="hljs-literal">undefined</span>) { - value = object[<span class="hljs-string">"is"</span>+capitalize(key)]; - } <span class="hljs-keyword">else</span> { - value = <span class="hljs-literal">undefined</span>; - } - stack.push(Twig.expression.resolve(value, object, params)); - } - }, - { - type: Twig.expression.type.key.brackets, - regex: <span class="hljs-regexp">/^\[([^\]]*)\]/</span>, - next: Twig.expression.set.operations_extended.concat([ - Twig.expression.type.parameter.start]), - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">var</span> match = token.match[<span class="hljs-number">1</span>]; - <span class="hljs-keyword">delete</span> token.value; - <span class="hljs-keyword">delete</span> token.match;</pre></div></div> - - </li> - - - <li id="section-271"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-271">¶</a> - </div> - <p>The expression stack for the key</p> - - </div> - - <div class="content"><div class='highlight'><pre> token.stack = Twig.expression.compile({ - value: match - }).stack; - - output.push(token); - }, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-272"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-272">¶</a> - </div> - <p>Evaluate key</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> params = token.params && Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.params, context]), - key = Twig.expression.parse.apply(<span class="hljs-keyword">this</span>, [token.stack, context]), - object = stack.pop(), - value; - - <span class="hljs-keyword">if</span> (object === <span class="hljs-literal">null</span> || object === <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.options.strict_variables) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Can't access a key "</span> + key + <span class="hljs-string">" on an null or undefined object."</span>); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; - } - }</pre></div></div> - - </li> - - - <li id="section-273"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-273">¶</a> - </div> - <p>Get the variable from the context</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object === <span class="hljs-string">'object'</span> && key <span class="hljs-keyword">in</span> object) { - value = object[key]; - } <span class="hljs-keyword">else</span> { - value = <span class="hljs-literal">null</span>; - } - stack.push(Twig.expression.resolve(value, object, params)); - } - }, - { - <span class="hljs-comment">/** - * Match a null value. - */</span> - type: Twig.expression.type._null,</pre></div></div> - - </li> - - - <li id="section-274"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-274">¶</a> - </div> - <p>match a number</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/^(null|NULL|none|NONE)/</span>, - next: Twig.expression.set.operations, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - <span class="hljs-keyword">delete</span> token.match; - token.value = <span class="hljs-literal">null</span>; - output.push(token); - }, - parse: Twig.expression.fn.parse.push_value - }, - { - <span class="hljs-comment">/** - * Match the context - */</span> - type: Twig.expression.type.context, - regex: <span class="hljs-regexp">/^_context/</span>, - next: Twig.expression.set.operations_extended.concat([ - Twig.expression.type.parameter.start]), - compile: Twig.expression.fn.compile.push, - parse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, context</span>) </span>{ - stack.push(context); - } - }, - { - <span class="hljs-comment">/** - * Match a number (integer or decimal) - */</span> - type: Twig.expression.type.number,</pre></div></div> - - </li> - - - <li id="section-275"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-275">¶</a> - </div> - <p>match a number</p> - - </div> - - <div class="content"><div class='highlight'><pre> regex: <span class="hljs-regexp">/^\-?\d+(\.\d+)?/</span>, - next: Twig.expression.set.operations, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - token.value = <span class="hljs-built_in">Number</span>(token.value); - output.push(token); - }, - parse: Twig.expression.fn.parse.push_value - }, - { - <span class="hljs-comment">/** - * Match a boolean - */</span> - type: Twig.expression.type.bool, - regex: <span class="hljs-regexp">/^(true|TRUE|false|FALSE)/</span>, - next: Twig.expression.set.operations, - compile: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">token, stack, output</span>) </span>{ - token.value = (token.match[<span class="hljs-number">0</span>].toLowerCase( ) === <span class="hljs-string">"true"</span>); - <span class="hljs-keyword">delete</span> token.match; - output.push(token); - }, - parse: Twig.expression.fn.parse.push_value - } - ]; - - <span class="hljs-comment">/** - * Resolve a context value. - * - * If the value is a function, it is executed with a context parameter. - * - * @param {string} key The context object key. - * @param {Object} context The render context. - */</span> - Twig.expression.resolve = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, context, params</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> value == <span class="hljs-string">'function'</span>) { - <span class="hljs-keyword">return</span> value.apply(context, params || []); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> value; - } - }; - - <span class="hljs-comment">/** - * Registry for logic handlers. - */</span> - Twig.expression.handler = {}; - - <span class="hljs-comment">/** - * Define a new expression type, available at Twig.logic.type.{type} - * - * @param {string} type The name of the new type. - */</span> - Twig.expression.extendType = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">type</span>) </span>{ - Twig.expression.type[type] = <span class="hljs-string">"Twig.expression.type."</span> + type; - }; - - <span class="hljs-comment">/** - * Extend the expression parsing functionality with a new definition. - * - * Token definitions follow this format: - * { - * type: One of Twig.expression.type.[type], either pre-defined or added using - * Twig.expression.extendType - * - * next: Array of types from Twig.expression.type that can follow this token, - * - * regex: A regex or array of regex's that should match the token. - * - * compile: function(token, stack, output) called when this token is being compiled. - * Should return an object with stack and output set. - * - * parse: function(token, stack, context) called when this token is being parsed. - * Should return an object with stack and context set. - * } - * - * @param {Object} definition A token definition. - */</span> - Twig.expression.extend = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">definition</span>) </span>{ - <span class="hljs-keyword">if</span> (!definition.type) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to extend logic definition. No type provided for "</span> + definition); - } - Twig.expression.handler[definition.type] = definition; - };</pre></div></div> - - </li> - - - <li id="section-276"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-276">¶</a> - </div> - <p>Extend with built-in expressions</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> (Twig.expression.definitions.length > <span class="hljs-number">0</span>) { - Twig.expression.extend(Twig.expression.definitions.shift()); - } - - <span class="hljs-comment">/** - * Break an expression into tokens defined in Twig.expression.definitions. - * - * @param {string} expression The string to tokenize. - * - * @return {Array} An array of tokens. - */</span> - Twig.expression.tokenize = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">expression</span>) </span>{ - <span class="hljs-keyword">var</span> tokens = [],</pre></div></div> - - </li> - - - <li id="section-277"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-277">¶</a> - </div> - <p>Keep an offset of the location in the expression for error messages.</p> - - </div> - - <div class="content"><div class='highlight'><pre> exp_offset = <span class="hljs-number">0</span>,</pre></div></div> - - </li> - - - <li id="section-278"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-278">¶</a> - </div> - <p>The valid next tokens of the previous token</p> - - </div> - - <div class="content"><div class='highlight'><pre> next = <span class="hljs-literal">null</span>,</pre></div></div> - - </li> - - - <li id="section-279"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-279">¶</a> - </div> - <p>Match information</p> - - </div> - - <div class="content"><div class='highlight'><pre> type, regex, regex_array,</pre></div></div> - - </li> - - - <li id="section-280"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-280">¶</a> - </div> - <p>The possible next token for the match</p> - - </div> - - <div class="content"><div class='highlight'><pre> token_next,</pre></div></div> - - </li> - - - <li id="section-281"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-281">¶</a> - </div> - <p>Has a match been found from the definitions</p> - - </div> - - <div class="content"><div class='highlight'><pre> match_found, invalid_matches = [], match_function; - - match_function = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">var</span> match = <span class="hljs-built_in">Array</span>.prototype.slice.apply(<span class="hljs-built_in">arguments</span>), - string = match.pop(), - offset = match.pop(); - - Twig.log.trace(<span class="hljs-string">"Twig.expression.tokenize"</span>, - <span class="hljs-string">"Matched a "</span>, type, <span class="hljs-string">" regular expression of "</span>, match); - - <span class="hljs-keyword">if</span> (next && Twig.indexOf(next, type) < <span class="hljs-number">0</span>) { - invalid_matches.push( - type + <span class="hljs-string">" cannot follow a "</span> + tokens[tokens.length - <span class="hljs-number">1</span>].type + - <span class="hljs-string">" at template:"</span> + exp_offset + <span class="hljs-string">" near '"</span> + match[<span class="hljs-number">0</span>].substring(<span class="hljs-number">0</span>, <span class="hljs-number">20</span>) + - <span class="hljs-string">"...'"</span> - );</pre></div></div> - - </li> - - - <li id="section-282"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-282">¶</a> - </div> - <p>Not a match, don’t change the expression</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> match[<span class="hljs-number">0</span>]; - }</pre></div></div> - - </li> - - - <li id="section-283"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-283">¶</a> - </div> - <p>Validate the token if a validation function is provided</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (Twig.expression.handler[type].validate && - !Twig.expression.handler[type].validate(match, tokens)) { - <span class="hljs-keyword">return</span> match[<span class="hljs-number">0</span>]; - } - - invalid_matches = []; - - tokens.push({ - type: type, - value: match[<span class="hljs-number">0</span>], - match: match - }); - - match_found = <span class="hljs-literal">true</span>; - next = token_next; - exp_offset += match[<span class="hljs-number">0</span>].length;</pre></div></div> - - </li> - - - <li id="section-284"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-284">¶</a> - </div> - <p>Does the token need to return output back to the expression string -e.g. a function match of cycle( might return the ‘(‘ back to the expression -This allows look-ahead to differentiate between token types (e.g. functions and variable names)</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (Twig.expression.handler[type].transform) { - <span class="hljs-keyword">return</span> Twig.expression.handler[type].transform(match, tokens); - } - <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>; - }; - - Twig.log.debug(<span class="hljs-string">"Twig.expression.tokenize"</span>, <span class="hljs-string">"Tokenizing expression "</span>, expression); - - <span class="hljs-keyword">while</span> (expression.length > <span class="hljs-number">0</span>) { - expression = expression.trim(); - <span class="hljs-keyword">for</span> (type <span class="hljs-keyword">in</span> Twig.expression.handler) { - <span class="hljs-keyword">if</span> (Twig.expression.handler.hasOwnProperty(type)) { - token_next = Twig.expression.handler[type].next; - regex = Twig.expression.handler[type].regex;</pre></div></div> - - </li> - - - <li id="section-285"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-285">¶</a> - </div> - <p>Twig.log.trace(“Checking type “, type, “ on “, expression);</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (regex <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>) { - regex_array = regex; - } <span class="hljs-keyword">else</span> { - regex_array = [regex]; - } - - match_found = <span class="hljs-literal">false</span>; - <span class="hljs-keyword">while</span> (regex_array.length > <span class="hljs-number">0</span>) { - regex = regex_array.pop(); - expression = expression.replace(regex, match_function); - }</pre></div></div> - - </li> - - - <li id="section-286"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-286">¶</a> - </div> - <p>An expression token has been matched. Break the for loop and start trying to - match the next template (if expression isn’t empty.)</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (match_found) { - <span class="hljs-keyword">break</span>; - } - } - } - <span class="hljs-keyword">if</span> (!match_found) { - <span class="hljs-keyword">if</span> (invalid_matches.length > <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(invalid_matches.join(<span class="hljs-string">" OR "</span>)); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to parse '"</span> + expression + <span class="hljs-string">"' at template position"</span> + exp_offset); - } - } - } - - Twig.log.trace(<span class="hljs-string">"Twig.expression.tokenize"</span>, <span class="hljs-string">"Tokenized to "</span>, tokens); - <span class="hljs-keyword">return</span> tokens; - }; - - <span class="hljs-comment">/** - * Compile an expression token. - * - * @param {Object} raw_token The uncompiled token. - * - * @return {Object} The compiled token. - */</span> - Twig.expression.compile = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">raw_token</span>) </span>{ - <span class="hljs-keyword">var</span> expression = raw_token.value,</pre></div></div> - - </li> - - - <li id="section-287"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-287">¶</a> - </div> - <p>Tokenize expression</p> - - </div> - - <div class="content"><div class='highlight'><pre> tokens = Twig.expression.tokenize(expression), - token = <span class="hljs-literal">null</span>, - output = [], - stack = [], - token_template = <span class="hljs-literal">null</span>; - - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"Compiling "</span>, expression);</pre></div></div> - - </li> - - - <li id="section-288"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-288">¶</a> - </div> - <p>Push tokens into RPN stack using the Sunting-yard algorithm -See <a href="http://en.wikipedia.org/wiki/Shunting_yard_algorithm">http://en.wikipedia.org/wiki/Shunting_yard_algorithm</a></p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">while</span> (tokens.length > <span class="hljs-number">0</span>) { - token = tokens.shift(); - token_template = Twig.expression.handler[token.type]; - - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"Compiling "</span>, token);</pre></div></div> - - </li> - - - <li id="section-289"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-289">¶</a> - </div> - <p>Compile the template</p> - - </div> - - <div class="content"><div class='highlight'><pre> token_template.compile && token_template.compile(token, stack, output); - - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"Stack is"</span>, stack); - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"Output is"</span>, output); - } - - <span class="hljs-keyword">while</span>(stack.length > <span class="hljs-number">0</span>) { - output.push(stack.pop()); - } - - Twig.log.trace(<span class="hljs-string">"Twig.expression.compile: "</span>, <span class="hljs-string">"Final output is"</span>, output); - - raw_token.stack = output; - <span class="hljs-keyword">delete</span> raw_token.value; - - <span class="hljs-keyword">return</span> raw_token; - }; - - - <span class="hljs-comment">/** - * Parse an RPN expression stack within a context. - * - * @param {Array} tokens An array of compiled expression tokens. - * @param {Object} context The render context to parse the tokens with. - * - * @return {Object} The result of parsing all the tokens. The result - * can be anything, String, Array, Object, etc... based on - * the given expression. - */</span> - Twig.expression.parse = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">tokens, context</span>) </span>{ - <span class="hljs-keyword">var</span> that = <span class="hljs-keyword">this</span>;</pre></div></div> - - </li> - - - <li id="section-290"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-290">¶</a> - </div> - <p>If the token isn’t an array, make it one.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!(tokens <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Array</span>)) { - tokens = [tokens]; - }</pre></div></div> - - </li> - - - <li id="section-291"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-291">¶</a> - </div> - <p>The output stack</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> stack = [], - token_template = <span class="hljs-literal">null</span>; - - Twig.forEach(tokens, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">token</span>) </span>{ - token_template = Twig.expression.handler[token.type]; - - token_template.parse && token_template.parse.apply(that, [token, stack, context]); - });</pre></div></div> - - </li> - - - <li id="section-292"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-292">¶</a> - </div> - <p>Pop the final value off the stack</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> stack.pop(); - }; - - <span class="hljs-keyword">return</span> Twig; - -})( Twig || { } );</pre></div></div> - - </li> - - - <li id="section-293"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-293">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-294"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-294">¶</a> - </div> - <h2 id="twig-expression-operator-js">twig.expression.operator.js</h2> -<p>This file handles operator lookups and parsing.</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> "use strict"</span>; - - <span class="hljs-comment">/** - * Operator associativity constants. - */</span> - Twig.expression.operator = { - leftToRight: <span class="hljs-string">'leftToRight'</span>, - rightToLeft: <span class="hljs-string">'rightToLeft'</span> - }; - - <span class="hljs-keyword">var</span> containment = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a, b</span>) </span>{ - <span class="hljs-keyword">if</span> (b === <span class="hljs-literal">undefined</span> || b === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (b.indexOf !== <span class="hljs-literal">undefined</span>) {</pre></div></div> - - </li> - - - <li id="section-295"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-295">¶</a> - </div> - <p>String</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> a === b || a !== <span class="hljs-string">''</span> && b.indexOf(a) > <span class="hljs-number">-1</span>; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">var</span> el; - <span class="hljs-keyword">for</span> (el <span class="hljs-keyword">in</span> b) { - <span class="hljs-keyword">if</span> (b.hasOwnProperty(el) && b[el] === a) { - <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; - } - } - <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; - } - }; - - <span class="hljs-comment">/** - * Get the precidence and associativity of an operator. These follow the order that C/C++ use. - * See http://en.wikipedia.org/wiki/Operators_in_C_and_C++ for the table of values. - */</span> - Twig.expression.operator.lookup = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">operator, token</span>) </span>{ - <span class="hljs-keyword">switch</span> (operator) { - <span class="hljs-keyword">case</span> <span class="hljs-string">".."</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'not in'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'in'</span>: - token.precidence = <span class="hljs-number">20</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">','</span>: - token.precidence = <span class="hljs-number">18</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>;</pre></div></div> - - </li> - - - <li id="section-296"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-296">¶</a> - </div> - <p>Ternary</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">'?'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">':'</span>: - token.precidence = <span class="hljs-number">16</span>; - token.associativity = Twig.expression.operator.rightToLeft; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'or'</span>: - token.precidence = <span class="hljs-number">14</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'and'</span>: - token.precidence = <span class="hljs-number">13</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'=='</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'!='</span>: - token.precidence = <span class="hljs-number">9</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'<'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'<='</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'>'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'>='</span>: - token.precidence = <span class="hljs-number">8</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>; - - - <span class="hljs-keyword">case</span> <span class="hljs-string">'~'</span>: <span class="hljs-comment">// String concatination</span> - <span class="hljs-keyword">case</span> <span class="hljs-string">'+'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>: - token.precidence = <span class="hljs-number">6</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'//'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'**'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'*'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'%'</span>: - token.precidence = <span class="hljs-number">5</span>; - token.associativity = Twig.expression.operator.leftToRight; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'not'</span>: - token.precidence = <span class="hljs-number">3</span>; - token.associativity = Twig.expression.operator.rightToLeft; - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">default</span>: - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(operator + <span class="hljs-string">" is an unknown operator."</span>); - } - token.operator = operator; - <span class="hljs-keyword">return</span> token; - }; - - <span class="hljs-comment">/** - * Handle operations on the RPN stack. - * - * Returns the updated stack. - */</span> - Twig.expression.operator.parse = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">operator, stack</span>) </span>{ - Twig.log.trace(<span class="hljs-string">"Twig.expression.operator.parse: "</span>, <span class="hljs-string">"Handling "</span>, operator); - <span class="hljs-keyword">var</span> a, b, c; - <span class="hljs-keyword">switch</span> (operator) { - <span class="hljs-keyword">case</span> <span class="hljs-string">':'</span>:</pre></div></div> - - </li> - - - <li id="section-297"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-297">¶</a> - </div> - <p>Ignore</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'?'</span>: - c = stack.pop(); <span class="hljs-comment">// false expr</span> - b = stack.pop(); <span class="hljs-comment">// true expr</span> - a = stack.pop(); <span class="hljs-comment">// conditional</span> - <span class="hljs-keyword">if</span> (a) { - stack.push(b); - } <span class="hljs-keyword">else</span> { - stack.push(c); - } - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'+'</span>: - b = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - a = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - stack.push(a + b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>: - b = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - a = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - stack.push(a - b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'*'</span>: - b = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - a = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - stack.push(a * b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>: - b = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - a = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - stack.push(a / b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'//'</span>: - b = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - a = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - stack.push(<span class="hljs-built_in">parseInt</span>(a / b)); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'%'</span>: - b = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - a = <span class="hljs-built_in">parseFloat</span>(stack.pop()); - stack.push(a % b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'~'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push( (a != <span class="hljs-literal">null</span> ? a.toString() : <span class="hljs-string">""</span>) - + (b != <span class="hljs-literal">null</span> ? b.toString() : <span class="hljs-string">""</span>) ); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'not'</span>: - <span class="hljs-keyword">case</span> <span class="hljs-string">'!'</span>: - stack.push(!stack.pop()); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'<'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a < b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'<='</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a <= b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'>'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a > b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'>='</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a >= b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'==='</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a === b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'=='</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a == b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'!=='</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a !== b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'!='</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a != b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'or'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a || b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'and'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(a && b); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'**'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push(<span class="hljs-built_in">Math</span>.pow(a, b)); - <span class="hljs-keyword">break</span>; - - - <span class="hljs-keyword">case</span> <span class="hljs-string">'not in'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push( !containment(a, b) ); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'in'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push( containment(a, b) ); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">case</span> <span class="hljs-string">'..'</span>: - b = stack.pop(); - a = stack.pop(); - stack.push( Twig.functions.range(a, b) ); - <span class="hljs-keyword">break</span>; - - <span class="hljs-keyword">default</span>: - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(operator + <span class="hljs-string">" is an unknown operator."</span>); - } - }; - - <span class="hljs-keyword">return</span> Twig; - -})( Twig || { } );</pre></div></div> - - </li> - - - <li id="section-298"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-298">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-299"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-299">¶</a> - </div> - <h2 id="twig-filters-js">twig.filters.js</h2> -<p>This file handles parsing filters.</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-300"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-300">¶</a> - </div> - <p>Determine object type</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">is</span>(<span class="hljs-params">type, obj</span>) </span>{ - <span class="hljs-keyword">var</span> clas = <span class="hljs-built_in">Object</span>.prototype.toString.call(obj).slice(<span class="hljs-number">8</span>, <span class="hljs-number">-1</span>); - <span class="hljs-keyword">return</span> obj !== <span class="hljs-literal">undefined</span> && obj !== <span class="hljs-literal">null</span> && clas === type; - } - - Twig.filters = {</pre></div></div> - - </li> - - - <li id="section-301"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-301">¶</a> - </div> - <p>String Filters</p> - - </div> - - <div class="content"><div class='highlight'><pre> upper: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> value !== <span class="hljs-string">"string"</span> ) { - <span class="hljs-keyword">return</span> value; - } - - <span class="hljs-keyword">return</span> value.toUpperCase(); - }, - lower: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> value !== <span class="hljs-string">"string"</span> ) { - <span class="hljs-keyword">return</span> value; - } - - <span class="hljs-keyword">return</span> value.toLowerCase(); - }, - capitalize: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> value !== <span class="hljs-string">"string"</span> ) { - <span class="hljs-keyword">return</span> value; - } - - <span class="hljs-keyword">return</span> value.substr(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>).toUpperCase() + value.toLowerCase().substr(<span class="hljs-number">1</span>); - }, - title: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> value !== <span class="hljs-string">"string"</span> ) { - <span class="hljs-keyword">return</span> value; - } - - <span class="hljs-keyword">return</span> value.toLowerCase().replace( <span class="hljs-regexp">/(^|\s)([a-z])/g</span> , <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">m, p1, p2</span>)</span>{ - <span class="hljs-keyword">return</span> p1 + p2.toUpperCase(); - }); - }, - length: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"Array"</span>, value) || <span class="hljs-keyword">typeof</span> value === <span class="hljs-string">"string"</span>) { - <span class="hljs-keyword">return</span> value.length; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"Object"</span>, value)) { - <span class="hljs-keyword">if</span> (value._keys === <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(value).length; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> value._keys.length; - } - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>; - } - },</pre></div></div> - - </li> - - - <li id="section-302"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-302">¶</a> - </div> - <p>Array/Object Filters</p> - - </div> - - <div class="content"><div class='highlight'><pre> reverse: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Array"</span>, value)) { - <span class="hljs-keyword">return</span> value.reverse(); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"String"</span>, value)) { - <span class="hljs-keyword">return</span> value.split(<span class="hljs-string">""</span>).reverse().join(<span class="hljs-string">""</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Object"</span>, value)) { - <span class="hljs-keyword">var</span> keys = value._keys || <span class="hljs-built_in">Object</span>.keys(value).reverse(); - value._keys = keys; - <span class="hljs-keyword">return</span> value; - } - }, - sort: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Array"</span>, value)) { - <span class="hljs-keyword">return</span> value.sort(); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (is(<span class="hljs-string">'Object'</span>, value)) {</pre></div></div> - - </li> - - - <li id="section-303"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-303">¶</a> - </div> - <p>Sorting objects isn’t obvious since the order of -returned keys isn’t guaranteed in JavaScript. -Because of this we use a “hidden” key called _keys to -store the keys in the order we want to return them.</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">delete</span> value._keys; - <span class="hljs-keyword">var</span> keys = <span class="hljs-built_in">Object</span>.keys(value), - sorted_keys = keys.sort(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">a, b</span>) </span>{ - <span class="hljs-keyword">var</span> a1, a2;</pre></div></div> - - </li> - - - <li id="section-304"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-304">¶</a> - </div> - <p>if a and b are comparable, we’re fine :-)</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span>((value[a] > value[b]) == !(value[a] <= value[b])) { - <span class="hljs-keyword">return</span> value[a] > value[b] ? <span class="hljs-number">1</span> : - value[a] < value[b] ? <span class="hljs-number">-1</span> : - <span class="hljs-number">0</span>; - }</pre></div></div> - - </li> - - - <li id="section-305"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-305">¶</a> - </div> - <p>if a and b can be parsed as numbers, we can compare -their numeric value</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(!<span class="hljs-built_in">isNaN</span>(a1 = <span class="hljs-built_in">parseFloat</span>(value[a])) && - !<span class="hljs-built_in">isNaN</span>(b1 = <span class="hljs-built_in">parseFloat</span>(value[b]))) { - <span class="hljs-keyword">return</span> a1 > b1 ? <span class="hljs-number">1</span> : - a1 < b1 ? <span class="hljs-number">-1</span> : - <span class="hljs-number">0</span>; - }</pre></div></div> - - </li> - - - <li id="section-306"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-306">¶</a> - </div> - <p>if one of the values is a string, we convert the -other value to string as well</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> value[a] == <span class="hljs-string">'string'</span>) { - <span class="hljs-keyword">return</span> value[a] > value[b].toString() ? <span class="hljs-number">1</span> : - value[a] < value[b].toString() ? <span class="hljs-number">-1</span> : - <span class="hljs-number">0</span>; - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(<span class="hljs-keyword">typeof</span> value[b] == <span class="hljs-string">'string'</span>) { - <span class="hljs-keyword">return</span> value[a].toString() > value[b] ? <span class="hljs-number">1</span> : - value[a].toString() < value[b] ? <span class="hljs-number">-1</span> : - <span class="hljs-number">0</span>; - }</pre></div></div> - - </li> - - - <li id="section-307"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-307">¶</a> - </div> - <p>everything failed - return ‘null’ as sign, that -the values are not comparable</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; - } - }); - value._keys = sorted_keys; - <span class="hljs-keyword">return</span> value; - } - }, - keys: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">var</span> keyset = value._keys || <span class="hljs-built_in">Object</span>.keys(value), - output = []; - - Twig.forEach(keyset, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key</span>) </span>{ - <span class="hljs-keyword">if</span> (key === <span class="hljs-string">"_keys"</span>) <span class="hljs-keyword">return</span>; <span class="hljs-comment">// Ignore the _keys property</span> - <span class="hljs-keyword">if</span> (value.hasOwnProperty(key)) { - output.push(key); - } - }); - <span class="hljs-keyword">return</span> output; - }, - url_encode: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">var</span> result = <span class="hljs-built_in">encodeURIComponent</span>(value); - result = result.replace(<span class="hljs-string">"'"</span>, <span class="hljs-string">"%27"</span>); - <span class="hljs-keyword">return</span> result; - }, - join: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">var</span> join_str = <span class="hljs-string">""</span>, - output = [], - keyset = <span class="hljs-literal">null</span>; - - <span class="hljs-keyword">if</span> (params && params[<span class="hljs-number">0</span>]) { - join_str = params[<span class="hljs-number">0</span>]; - } - <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Array"</span>, value)) { - output = value; - } <span class="hljs-keyword">else</span> { - keyset = value._keys || <span class="hljs-built_in">Object</span>.keys(value); - Twig.forEach(keyset, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key</span>) </span>{ - <span class="hljs-keyword">if</span> (key === <span class="hljs-string">"_keys"</span>) <span class="hljs-keyword">return</span>; <span class="hljs-comment">// Ignore the _keys property</span> - <span class="hljs-keyword">if</span> (value.hasOwnProperty(key)) { - output.push(value[key]); - } - }); - } - <span class="hljs-keyword">return</span> output.join(join_str); - }, - <span class="hljs-string">"default"</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (params !== <span class="hljs-literal">undefined</span> && params.length > <span class="hljs-number">1</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"default filter expects one argument"</span>); - } - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span> || value === <span class="hljs-string">''</span> ) { - <span class="hljs-keyword">if</span> (params === <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>; - } - - <span class="hljs-keyword">return</span> params[<span class="hljs-number">0</span>]; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> value; - } - }, - json_encode: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span>(value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">return</span> <span class="hljs-string">"null"</span>; - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ((<span class="hljs-keyword">typeof</span> value == <span class="hljs-string">'object'</span>) && (is(<span class="hljs-string">"Array"</span>, value))) { - output = []; - - Twig.forEach(value, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">v</span>) </span>{ - output.push(Twig.filters.json_encode(v)); - }); - - <span class="hljs-keyword">return</span> <span class="hljs-string">"["</span> + output.join(<span class="hljs-string">","</span>) + <span class="hljs-string">"]"</span>; - } - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> value == <span class="hljs-string">'object'</span>) { - <span class="hljs-keyword">var</span> keyset = value._keys || <span class="hljs-built_in">Object</span>.keys(value), - output = []; - - Twig.forEach(keyset, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key</span>) </span>{ - output.push(<span class="hljs-built_in">JSON</span>.stringify(key) + <span class="hljs-string">":"</span> + Twig.filters.json_encode(value[key])); - }); - - <span class="hljs-keyword">return</span> <span class="hljs-string">"{"</span> + output.join(<span class="hljs-string">","</span>) + <span class="hljs-string">"}"</span>; - } - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> <span class="hljs-built_in">JSON</span>.stringify(value); - } - }, - merge: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">var</span> obj = [], - arr_index = <span class="hljs-number">0</span>, - keyset = [];</pre></div></div> - - </li> - - - <li id="section-308"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-308">¶</a> - </div> - <p>Check to see if all the objects being merged are arrays</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!is(<span class="hljs-string">"Array"</span>, value)) {</pre></div></div> - - </li> - - - <li id="section-309"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-309">¶</a> - </div> - <p>Create obj as an Object</p> - - </div> - - <div class="content"><div class='highlight'><pre> obj = { }; - } <span class="hljs-keyword">else</span> { - Twig.forEach(params, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">param</span>) </span>{ - <span class="hljs-keyword">if</span> (!is(<span class="hljs-string">"Array"</span>, param)) { - obj = { }; - } - }); - } - <span class="hljs-keyword">if</span> (!is(<span class="hljs-string">"Array"</span>, obj)) { - obj._keys = []; - } - - <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Array"</span>, value)) { - Twig.forEach(value, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">val</span>) </span>{ - <span class="hljs-keyword">if</span> (obj._keys) obj._keys.push(arr_index); - obj[arr_index] = val; - arr_index++; - }); - } <span class="hljs-keyword">else</span> { - keyset = value._keys || <span class="hljs-built_in">Object</span>.keys(value); - Twig.forEach(keyset, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key</span>) </span>{ - obj[key] = value[key]; - obj._keys.push(key);</pre></div></div> - - </li> - - - <li id="section-310"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-310">¶</a> - </div> - <p>Handle edge case where a number index in an object is greater than - the array counter. In such a case, the array counter is increased - one past the index.</p> -<p>Example {{ [“a”, “b”]|merge({“4”:”value”}, [“c”, “d”]) -Without this, d would have an index of “4” and overwrite the value - of “value”</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> int_key = <span class="hljs-built_in">parseInt</span>(key, <span class="hljs-number">10</span>); - <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">isNaN</span>(int_key) && int_key >= arr_index) { - arr_index = int_key + <span class="hljs-number">1</span>; - } - }); - }</pre></div></div> - - </li> - - - <li id="section-311"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-311">¶</a> - </div> - <p>mixin the merge arrays</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.forEach(params, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">param</span>) </span>{ - <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Array"</span>, param)) { - Twig.forEach(param, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">val</span>) </span>{ - <span class="hljs-keyword">if</span> (obj._keys) obj._keys.push(arr_index); - obj[arr_index] = val; - arr_index++; - }); - } <span class="hljs-keyword">else</span> { - keyset = param._keys || <span class="hljs-built_in">Object</span>.keys(param); - Twig.forEach(keyset, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">key</span>) </span>{ - <span class="hljs-keyword">if</span> (!obj[key]) obj._keys.push(key); - obj[key] = param[key]; - - <span class="hljs-keyword">var</span> int_key = <span class="hljs-built_in">parseInt</span>(key, <span class="hljs-number">10</span>); - <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">isNaN</span>(int_key) && int_key >= arr_index) { - arr_index = int_key + <span class="hljs-number">1</span>; - } - }); - } - }); - <span class="hljs-keyword">if</span> (params.length === <span class="hljs-number">0</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Filter merge expects at least one parameter"</span>); - } - - <span class="hljs-keyword">return</span> obj; - }, - date: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">var</span> date = Twig.functions.date(value); - <span class="hljs-keyword">var</span> format = params && params.length ? params[<span class="hljs-number">0</span>] : <span class="hljs-string">'F j, Y H:i'</span>; - <span class="hljs-keyword">return</span> Twig.lib.formatDate(date, format); - }, - - date_modify: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">return</span>; - } - <span class="hljs-keyword">if</span> (params === <span class="hljs-literal">undefined</span> || params.length !== <span class="hljs-number">1</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"date_modify filter expects 1 argument"</span>); - } - - <span class="hljs-keyword">var</span> modifyText = params[<span class="hljs-number">0</span>], time; - - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"Date"</span>, value)) { - time = Twig.lib.strtotime(modifyText, value.getTime() / <span class="hljs-number">1000</span>); - } - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"String"</span>, value)) { - time = Twig.lib.strtotime(modifyText, Twig.lib.strtotime(value)); - } - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"Number"</span>, value)) { - time = Twig.lib.strtotime(modifyText, value); - } - - <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(time * <span class="hljs-number">1000</span>); - }, - - replace: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span>||value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">var</span> pairs = params[<span class="hljs-number">0</span>], - tag; - <span class="hljs-keyword">for</span> (tag <span class="hljs-keyword">in</span> pairs) { - <span class="hljs-keyword">if</span> (pairs.hasOwnProperty(tag) && tag !== <span class="hljs-string">"_keys"</span>) { - value = Twig.lib.replaceAll(value, tag, pairs[tag]); - } - } - <span class="hljs-keyword">return</span> value; - }, - - format: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">return</span> Twig.lib.vsprintf(value, params); - }, - - striptags: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">return</span> Twig.lib.strip_tags(value); - }, - - <span class="hljs-built_in">escape</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span>|| value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">var</span> strategy = <span class="hljs-string">"html"</span>; - <span class="hljs-keyword">if</span>(params && params.length && params[<span class="hljs-number">0</span>] !== <span class="hljs-literal">true</span>) - strategy = params[<span class="hljs-number">0</span>]; - - <span class="hljs-keyword">if</span>(strategy == <span class="hljs-string">"html"</span>) { - <span class="hljs-keyword">var</span> raw_value = value.toString().replace(<span class="hljs-regexp">/&/g</span>, <span class="hljs-string">"&amp;"</span>) - .replace(<span class="hljs-regexp">/</g</span>, <span class="hljs-string">"&lt;"</span>) - .replace(<span class="hljs-regexp">/>/g</span>, <span class="hljs-string">"&gt;"</span>) - .replace(<span class="hljs-regexp">/"/g</span>, <span class="hljs-string">"&quot;"</span>) - .replace(<span class="hljs-regexp">/'/g</span>, <span class="hljs-string">"&#039;"</span>); - <span class="hljs-keyword">return</span> Twig.Markup(raw_value, <span class="hljs-string">'html'</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(strategy == <span class="hljs-string">"js"</span>) { - <span class="hljs-keyword">var</span> raw_value = value.toString(); - <span class="hljs-keyword">var</span> result = <span class="hljs-string">""</span>; - - <span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < raw_value.length; i++) { - <span class="hljs-keyword">if</span>(raw_value[i].match(<span class="hljs-regexp">/^[a-zA-Z0-9,\._]$/</span>)) - result += raw_value[i]; - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">var</span> char_code = raw_value.charCodeAt(i); - - <span class="hljs-keyword">if</span>(char_code < <span class="hljs-number">0x80</span>) - result += <span class="hljs-string">"\\x"</span> + char_code.toString(<span class="hljs-number">16</span>).toUpperCase(); - <span class="hljs-keyword">else</span> - result += Twig.lib.sprintf(<span class="hljs-string">"\\u%04s"</span>, char_code.toString(<span class="hljs-number">16</span>).toUpperCase()); - } - } - - <span class="hljs-keyword">return</span> Twig.Markup(result, <span class="hljs-string">'js'</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(strategy == <span class="hljs-string">"css"</span>) { - <span class="hljs-keyword">var</span> raw_value = value.toString(); - <span class="hljs-keyword">var</span> result = <span class="hljs-string">""</span>; - - <span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < raw_value.length; i++) { - <span class="hljs-keyword">if</span>(raw_value[i].match(<span class="hljs-regexp">/^[a-zA-Z0-9]$/</span>)) - result += raw_value[i]; - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">var</span> char_code = raw_value.charCodeAt(i); - result += <span class="hljs-string">"\\"</span> + char_code.toString(<span class="hljs-number">16</span>).toUpperCase() + <span class="hljs-string">" "</span>; - } - } - - <span class="hljs-keyword">return</span> Twig.Markup(result, <span class="hljs-string">'css'</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(strategy == <span class="hljs-string">"url"</span>) { - <span class="hljs-keyword">var</span> result = Twig.filters.url_encode(value); - <span class="hljs-keyword">return</span> Twig.Markup(result, <span class="hljs-string">'url'</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(strategy == <span class="hljs-string">"html_attr"</span>) { - <span class="hljs-keyword">var</span> raw_value = value.toString(); - <span class="hljs-keyword">var</span> result = <span class="hljs-string">""</span>; - - <span class="hljs-keyword">for</span>(<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < raw_value.length; i++) { - <span class="hljs-keyword">if</span>(raw_value[i].match(<span class="hljs-regexp">/^[a-zA-Z0-9,\.\-_]$/</span>)) - result += raw_value[i]; - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(raw_value[i].match(<span class="hljs-regexp">/^[&<>"]$/</span>)) - result += raw_value[i].replace(<span class="hljs-regexp">/&/g</span>, <span class="hljs-string">"&amp;"</span>) - .replace(<span class="hljs-regexp">/</g</span>, <span class="hljs-string">"&lt;"</span>) - .replace(<span class="hljs-regexp">/>/g</span>, <span class="hljs-string">"&gt;"</span>) - .replace(<span class="hljs-regexp">/"/g</span>, <span class="hljs-string">"&quot;"</span>); - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">var</span> char_code = raw_value.charCodeAt(i);</pre></div></div> - - </li> - - - <li id="section-312"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-312">¶</a> - </div> - <p>The following replaces characters undefined in HTML with -the hex entity for the Unicode replacement character.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span>(char_code <= <span class="hljs-number">0x1f</span> && char_code != <span class="hljs-number">0x09</span> && char_code != <span class="hljs-number">0x0a</span> && char_code != <span class="hljs-number">0x0d</span>) - result += <span class="hljs-string">"&#xFFFD;"</span>; - <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(char_code < <span class="hljs-number">0x80</span>) - result += Twig.lib.sprintf(<span class="hljs-string">"&#x%02s;"</span>, char_code.toString(<span class="hljs-number">16</span>).toUpperCase()); - <span class="hljs-keyword">else</span> - result += Twig.lib.sprintf(<span class="hljs-string">"&#x%04s;"</span>, char_code.toString(<span class="hljs-number">16</span>).toUpperCase()); - } - } - - <span class="hljs-keyword">return</span> Twig.Markup(result, <span class="hljs-string">'html_attr'</span>); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"escape strategy unsupported"</span>); - } - }, - - <span class="hljs-comment">/* Alias of escape */</span> - <span class="hljs-string">"e"</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">return</span> Twig.filters.escape(value, params); - }, - - nl2br: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - <span class="hljs-keyword">var</span> linebreak_tag = <span class="hljs-string">"BACKSLASH_n_replace"</span>, - br = <span class="hljs-string">"<br />"</span> + linebreak_tag; - - value = Twig.filters.escape(value) - .replace(<span class="hljs-regexp">/\r\n/g</span>, br) - .replace(<span class="hljs-regexp">/\r/g</span>, br) - .replace(<span class="hljs-regexp">/\n/g</span>, br); - - value = Twig.lib.replaceAll(value, linebreak_tag, <span class="hljs-string">"\n"</span>); - - <span class="hljs-keyword">return</span> Twig.Markup(value); - }, - - <span class="hljs-comment">/** - * Adapted from: http://phpjs.org/functions/number_format:481 - */</span> - number_format: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">var</span> number = value, - decimals = (params && params[<span class="hljs-number">0</span>]) ? params[<span class="hljs-number">0</span>] : <span class="hljs-literal">undefined</span>, - dec = (params && params[<span class="hljs-number">1</span>] !== <span class="hljs-literal">undefined</span>) ? params[<span class="hljs-number">1</span>] : <span class="hljs-string">"."</span>, - sep = (params && params[<span class="hljs-number">2</span>] !== <span class="hljs-literal">undefined</span>) ? params[<span class="hljs-number">2</span>] : <span class="hljs-string">","</span>; - - number = (number + <span class="hljs-string">''</span>).replace(<span class="hljs-regexp">/[^0-9+\-Ee.]/g</span>, <span class="hljs-string">''</span>); - <span class="hljs-keyword">var</span> n = !<span class="hljs-built_in">isFinite</span>(+number) ? <span class="hljs-number">0</span> : +number, - prec = !<span class="hljs-built_in">isFinite</span>(+decimals) ? <span class="hljs-number">0</span> : <span class="hljs-built_in">Math</span>.abs(decimals), - s = <span class="hljs-string">''</span>, - toFixedFix = <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">n, prec</span>) </span>{ - <span class="hljs-keyword">var</span> k = <span class="hljs-built_in">Math</span>.pow(<span class="hljs-number">10</span>, prec); - <span class="hljs-keyword">return</span> <span class="hljs-string">''</span> + <span class="hljs-built_in">Math</span>.round(n * k) / k; - };</pre></div></div> - - </li> - - - <li id="section-313"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-313">¶</a> - </div> - <p>Fix for IE parseFloat(0.55).toFixed(0) = 0;</p> - - </div> - - <div class="content"><div class='highlight'><pre> s = (prec ? toFixedFix(n, prec) : <span class="hljs-string">''</span> + <span class="hljs-built_in">Math</span>.round(n)).split(<span class="hljs-string">'.'</span>); - <span class="hljs-keyword">if</span> (s[<span class="hljs-number">0</span>].length > <span class="hljs-number">3</span>) { - s[<span class="hljs-number">0</span>] = s[<span class="hljs-number">0</span>].replace(<span class="hljs-regexp">/\B(?=(?:\d{3})+(?!\d))/g</span>, sep); - } - <span class="hljs-keyword">if</span> ((s[<span class="hljs-number">1</span>] || <span class="hljs-string">''</span>).length < prec) { - s[<span class="hljs-number">1</span>] = s[<span class="hljs-number">1</span>] || <span class="hljs-string">''</span>; - s[<span class="hljs-number">1</span>] += <span class="hljs-keyword">new</span> <span class="hljs-built_in">Array</span>(prec - s[<span class="hljs-number">1</span>].length + <span class="hljs-number">1</span>).join(<span class="hljs-string">'0'</span>); - } - <span class="hljs-keyword">return</span> s.join(dec); - }, - - trim: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span>|| value === <span class="hljs-literal">null</span>){ - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">var</span> str = Twig.filters.escape( <span class="hljs-string">''</span> + value ), - whitespace; - <span class="hljs-keyword">if</span> ( params && params[<span class="hljs-number">0</span>] ) { - whitespace = <span class="hljs-string">''</span> + params[<span class="hljs-number">0</span>]; - } <span class="hljs-keyword">else</span> { - whitespace = <span class="hljs-string">' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000'</span>; - } - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i < str.length; i++) { - <span class="hljs-keyword">if</span> (whitespace.indexOf(str.charAt(i)) === <span class="hljs-number">-1</span>) { - str = str.substring(i); - <span class="hljs-keyword">break</span>; - } - } - <span class="hljs-keyword">for</span> (i = str.length - <span class="hljs-number">1</span>; i >= <span class="hljs-number">0</span>; i--) { - <span class="hljs-keyword">if</span> (whitespace.indexOf(str.charAt(i)) === <span class="hljs-number">-1</span>) { - str = str.substring(<span class="hljs-number">0</span>, i + <span class="hljs-number">1</span>); - <span class="hljs-keyword">break</span>; - } - } - <span class="hljs-keyword">return</span> whitespace.indexOf(str.charAt(<span class="hljs-number">0</span>)) === <span class="hljs-number">-1</span> ? str : <span class="hljs-string">''</span>; - }, - - truncate: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">var</span> length = <span class="hljs-number">30</span>, - preserve = <span class="hljs-literal">false</span>, - separator = <span class="hljs-string">'...'</span>; - - value = value + <span class="hljs-string">''</span>; - <span class="hljs-keyword">if</span> (params) { - <span class="hljs-keyword">if</span> (params[<span class="hljs-number">0</span>]) { - length = params[<span class="hljs-number">0</span>]; - } - <span class="hljs-keyword">if</span> (params[<span class="hljs-number">1</span>]) { - preserve = params[<span class="hljs-number">1</span>]; - } - <span class="hljs-keyword">if</span> (params[<span class="hljs-number">2</span>]) { - separator = params[<span class="hljs-number">2</span>]; - } - } - - <span class="hljs-keyword">if</span> (value.length > length) { - - <span class="hljs-keyword">if</span> (preserve) { - length = value.indexOf(<span class="hljs-string">' '</span>, length); - <span class="hljs-keyword">if</span> (length === <span class="hljs-number">-1</span>) { - <span class="hljs-keyword">return</span> value; - } - } - - value = value.substr(<span class="hljs-number">0</span>, length) + separator; - } - - <span class="hljs-keyword">return</span> value; - }, - - slice: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">return</span>; - } - <span class="hljs-keyword">if</span> (params === <span class="hljs-literal">undefined</span> || params.length < <span class="hljs-number">1</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"slice filter expects at least 1 argument"</span>); - }</pre></div></div> - - </li> - - - <li id="section-314"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-314">¶</a> - </div> - <p>default to start of string</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> start = params[<span class="hljs-number">0</span>] || <span class="hljs-number">0</span>;</pre></div></div> - - </li> - - - <li id="section-315"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-315">¶</a> - </div> - <p>default to length of string</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> length = params.length > <span class="hljs-number">1</span> ? params[<span class="hljs-number">1</span>] : value.length;</pre></div></div> - - </li> - - - <li id="section-316"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-316">¶</a> - </div> - <p>handle negative start values</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> startIndex = start >= <span class="hljs-number">0</span> ? start : <span class="hljs-built_in">Math</span>.max( value.length + start, <span class="hljs-number">0</span> ); - - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"Array"</span>, value)) { - <span class="hljs-keyword">var</span> output = []; - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i = startIndex; i < startIndex + length && i < value.length; i++) { - output.push(value[i]); - } - <span class="hljs-keyword">return</span> output; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"String"</span>, value)) { - <span class="hljs-keyword">return</span> value.substr(startIndex, length); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"slice filter expects value to be an array or string"</span>); - } - }, - - abs: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">return</span>; - } - - <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.abs(value); - }, - - first: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Array"</span>, value)) { - <span class="hljs-keyword">return</span> value[<span class="hljs-number">0</span>]; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (is(<span class="hljs-string">"Object"</span>, value)) { - <span class="hljs-keyword">if</span> (<span class="hljs-string">'_keys'</span> <span class="hljs-keyword">in</span> value) { - <span class="hljs-keyword">return</span> value[value._keys[<span class="hljs-number">0</span>]]; - } - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> value === <span class="hljs-string">"string"</span> ) { - <span class="hljs-keyword">return</span> value.substr(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>); - } - - <span class="hljs-keyword">return</span>; - }, - - split: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">undefined</span> || value === <span class="hljs-literal">null</span>) { - <span class="hljs-keyword">return</span>; - } - <span class="hljs-keyword">if</span> (params === <span class="hljs-literal">undefined</span> || params.length < <span class="hljs-number">1</span> || params.length > <span class="hljs-number">2</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"split filter expects 1 or 2 argument"</span>); - } - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"String"</span>, value)) { - <span class="hljs-keyword">var</span> delimiter = params[<span class="hljs-number">0</span>], - limit = params[<span class="hljs-number">1</span>], - split = value.split(delimiter); - - <span class="hljs-keyword">if</span> (limit === <span class="hljs-literal">undefined</span>) { - - <span class="hljs-keyword">return</span> split; - - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (limit < <span class="hljs-number">0</span>) { - - <span class="hljs-keyword">return</span> value.split(delimiter, split.length + limit); - - } <span class="hljs-keyword">else</span> { - - <span class="hljs-keyword">var</span> limitedSplit = []; - - <span class="hljs-keyword">if</span> (delimiter == <span class="hljs-string">''</span>) {</pre></div></div> - - </li> - - - <li id="section-317"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-317">¶</a> - </div> - <p>empty delimiter -“aabbcc”|split(‘’, 2) - -> [‘aa’, ‘bb’, ‘cc’]</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">while</span>(split.length > <span class="hljs-number">0</span>) { - <span class="hljs-keyword">var</span> temp = <span class="hljs-string">""</span>; - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>; i<limit && split.length > <span class="hljs-number">0</span>; i++) { - temp += split.shift(); - } - limitedSplit.push(temp); - } - - } <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-318"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-318">¶</a> - </div> - <p>non-empty delimiter -“one,two,three,four,five”|split(‘,’, 3) - -> [‘one’, ‘two’, ‘three,four,five’]</p> - - </div> - - <div class="content"><div class='highlight'><pre> - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> i=<span class="hljs-number">0</span>; i<limit<span class="hljs-number">-1</span> && split.length > <span class="hljs-number">0</span>; i++) { - limitedSplit.push(split.shift()); - } - - <span class="hljs-keyword">if</span> (split.length > <span class="hljs-number">0</span>) { - limitedSplit.push(split.join(delimiter)); - } - } - - <span class="hljs-keyword">return</span> limitedSplit; - } - - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"split filter expects value to be a string"</span>); - } - }, - last: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">'Object'</span>, value)) { - <span class="hljs-keyword">var</span> keys; - - <span class="hljs-keyword">if</span> (value._keys === <span class="hljs-literal">undefined</span>) { - keys = <span class="hljs-built_in">Object</span>.keys(value); - } <span class="hljs-keyword">else</span> { - keys = value._keys; - } - - <span class="hljs-keyword">return</span> value[keys[keys.length - <span class="hljs-number">1</span>]]; - }</pre></div></div> - - </li> - - - <li id="section-319"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-319">¶</a> - </div> - <p>string|array</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> value[value.length - <span class="hljs-number">1</span>]; - }, - raw: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">return</span> Twig.Markup(value); - }, - batch: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">items, params</span>) </span>{ - <span class="hljs-keyword">var</span> size = params.shift(), - fill = params.shift(), - result, - last, - missing; - - <span class="hljs-keyword">if</span> (!Twig.lib.is(<span class="hljs-string">"Array"</span>, items)) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"batch filter expects items to be an array"</span>); - } - - <span class="hljs-keyword">if</span> (!Twig.lib.is(<span class="hljs-string">"Number"</span>, size)) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"batch filter expects size to be a number"</span>); - } - - size = <span class="hljs-built_in">Math</span>.ceil(size); - - result = Twig.lib.chunkArray(items, size); - - <span class="hljs-keyword">if</span> (fill && items.length % size != <span class="hljs-number">0</span>) { - last = result.pop(); - missing = size - last.length; - - <span class="hljs-keyword">while</span> (missing--) { - last.push(fill); - } - - result.push(last); - } - - <span class="hljs-keyword">return</span> result; - }, - round: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - params = params || []; - - <span class="hljs-keyword">var</span> precision = params.length > <span class="hljs-number">0</span> ? params[<span class="hljs-number">0</span>] : <span class="hljs-number">0</span>, - method = params.length > <span class="hljs-number">1</span> ? params[<span class="hljs-number">1</span>] : <span class="hljs-string">"common"</span>; - - value = <span class="hljs-built_in">parseFloat</span>(value); - - <span class="hljs-keyword">if</span>(precision && !Twig.lib.is(<span class="hljs-string">"Number"</span>, precision)) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"round filter expects precision to be a number"</span>); - } - - <span class="hljs-keyword">if</span> (method === <span class="hljs-string">"common"</span>) { - <span class="hljs-keyword">return</span> Twig.lib.round(value, precision); - } - - <span class="hljs-keyword">if</span>(!Twig.lib.is(<span class="hljs-string">"Function"</span>, <span class="hljs-built_in">Math</span>[method])) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"round filter expects method to be 'floor', 'ceil', or 'common'"</span>); - } - - <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>[method](value * <span class="hljs-built_in">Math</span>.pow(<span class="hljs-number">10</span>, precision)) / <span class="hljs-built_in">Math</span>.pow(<span class="hljs-number">10</span>, precision); - } - }; - - Twig.filter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">filter, value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (!Twig.filters[filter]) { - <span class="hljs-keyword">throw</span> <span class="hljs-string">"Unable to find filter "</span> + filter; - } - <span class="hljs-keyword">return</span> Twig.filters[filter].apply(<span class="hljs-keyword">this</span>, [value, params]); - }; - - Twig.filter.extend = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">filter, definition</span>) </span>{ - Twig.filters[filter] = definition; - }; - - <span class="hljs-keyword">return</span> Twig; - -})(Twig || { });</pre></div></div> - - </li> - - - <li id="section-320"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-320">¶</a> - </div> - <pre><code>Twig.js - <span class="hljs-number">2012</span> Hadrien Lanneau -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-321"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-321">¶</a> - </div> - <h2 id="twig-functions-js">twig.functions.js</h2> -<p>This file handles parsing filters.</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ - <span class="hljs-comment">/** - * @constant - * @type {string} - */</span> - <span class="hljs-keyword">var</span> TEMPLATE_NOT_FOUND_MESSAGE = <span class="hljs-string">'Template "{name}" is not defined.'</span>;</pre></div></div> - - </li> - - - <li id="section-322"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-322">¶</a> - </div> - <p>Determine object type</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">is</span>(<span class="hljs-params">type, obj</span>) </span>{ - <span class="hljs-keyword">var</span> clas = <span class="hljs-built_in">Object</span>.prototype.toString.call(obj).slice(<span class="hljs-number">8</span>, <span class="hljs-number">-1</span>); - <span class="hljs-keyword">return</span> obj !== <span class="hljs-literal">undefined</span> && obj !== <span class="hljs-literal">null</span> && clas === type; - } - - Twig.functions = {</pre></div></div> - - </li> - - - <li id="section-323"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-323">¶</a> - </div> - <p> attribute, block, constant, date, dump, parent, random,.</p> - - </div> - - </li> - - - <li id="section-324"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-324">¶</a> - </div> - <p>Range function from <a href="http://phpjs.org/functions/range:499">http://phpjs.org/functions/range:499</a> -Used under an MIT License</p> - - </div> - - <div class="content"><div class='highlight'><pre> range: <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">low, high, step</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-325"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-325">¶</a> - </div> - <p><a href="http://kevin.vanzonneveld.net">http://kevin.vanzonneveld.net</a></p> -<ul> -<li>original by: Waldo Malqui Silva</li> -<li>example 1: range ( 0, 12 );</li> -<li>returns 1: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]</li> -<li>example 2: range( 0, 100, 10 );</li> -<li>returns 2: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]</li> -<li>example 3: range( ‘a’, ‘i’ );</li> -<li>returns 3: [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’, ‘g’, ‘h’, ‘i’]</li> -<li>example 4: range( ‘c’, ‘a’ );</li> -<li>returns 4: [‘c’, ‘b’, ‘a’]</li> -</ul> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> matrix = []; - <span class="hljs-keyword">var</span> inival, endval, plus; - <span class="hljs-keyword">var</span> walker = step || <span class="hljs-number">1</span>; - <span class="hljs-keyword">var</span> chars = <span class="hljs-literal">false</span>; - - <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">isNaN</span>(low) && !<span class="hljs-built_in">isNaN</span>(high)) { - inival = <span class="hljs-built_in">parseInt</span>(low, <span class="hljs-number">10</span>); - endval = <span class="hljs-built_in">parseInt</span>(high, <span class="hljs-number">10</span>); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-built_in">isNaN</span>(low) && <span class="hljs-built_in">isNaN</span>(high)) { - chars = <span class="hljs-literal">true</span>; - inival = low.charCodeAt(<span class="hljs-number">0</span>); - endval = high.charCodeAt(<span class="hljs-number">0</span>); - } <span class="hljs-keyword">else</span> { - inival = (<span class="hljs-built_in">isNaN</span>(low) ? <span class="hljs-number">0</span> : low); - endval = (<span class="hljs-built_in">isNaN</span>(high) ? <span class="hljs-number">0</span> : high); - } - - plus = ((inival > endval) ? <span class="hljs-literal">false</span> : <span class="hljs-literal">true</span>); - <span class="hljs-keyword">if</span> (plus) { - <span class="hljs-keyword">while</span> (inival <= endval) { - matrix.push(((chars) ? <span class="hljs-built_in">String</span>.fromCharCode(inival) : inival)); - inival += walker; - } - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">while</span> (inival >= endval) { - matrix.push(((chars) ? <span class="hljs-built_in">String</span>.fromCharCode(inival) : inival)); - inival -= walker; - } - } - - <span class="hljs-keyword">return</span> matrix; - }, - cycle: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">arr, i</span>) </span>{ - <span class="hljs-keyword">var</span> pos = i % arr.length; - <span class="hljs-keyword">return</span> arr[pos]; - }, - dump: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">var</span> EOL = <span class="hljs-string">'\n'</span>, - indentChar = <span class="hljs-string">' '</span>, - indentTimes = <span class="hljs-number">0</span>, - out = <span class="hljs-string">''</span>, - args = <span class="hljs-built_in">Array</span>.prototype.slice.call(<span class="hljs-built_in">arguments</span>), - indent = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">times</span>) </span>{ - <span class="hljs-keyword">var</span> ind = <span class="hljs-string">''</span>; - <span class="hljs-keyword">while</span> (times > <span class="hljs-number">0</span>) { - times--; - ind += indentChar; - } - <span class="hljs-keyword">return</span> ind; - }, - displayVar = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">variable</span>) </span>{ - out += indent(indentTimes); - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(variable) === <span class="hljs-string">'object'</span>) { - dumpVar(variable); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(variable) === <span class="hljs-string">'function'</span>) { - out += <span class="hljs-string">'function()'</span> + EOL; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(variable) === <span class="hljs-string">'string'</span>) { - out += <span class="hljs-string">'string('</span> + variable.length + <span class="hljs-string">') "'</span> + variable + <span class="hljs-string">'"'</span> + EOL; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(variable) === <span class="hljs-string">'number'</span>) { - out += <span class="hljs-string">'number('</span> + variable + <span class="hljs-string">')'</span> + EOL; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span>(variable) === <span class="hljs-string">'boolean'</span>) { - out += <span class="hljs-string">'bool('</span> + variable + <span class="hljs-string">')'</span> + EOL; - } - }, - dumpVar = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">variable</span>) </span>{ - <span class="hljs-keyword">var</span> i; - <span class="hljs-keyword">if</span> (variable === <span class="hljs-literal">null</span>) { - out += <span class="hljs-string">'NULL'</span> + EOL; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (variable === <span class="hljs-literal">undefined</span>) { - out += <span class="hljs-string">'undefined'</span> + EOL; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> variable === <span class="hljs-string">'object'</span>) { - out += indent(indentTimes) + <span class="hljs-keyword">typeof</span>(variable); - indentTimes++; - out += <span class="hljs-string">'('</span> + (<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">obj</span>) </span>{ - <span class="hljs-keyword">var</span> size = <span class="hljs-number">0</span>, key; - <span class="hljs-keyword">for</span> (key <span class="hljs-keyword">in</span> obj) { - <span class="hljs-keyword">if</span> (obj.hasOwnProperty(key)) { - size++; - } - } - <span class="hljs-keyword">return</span> size; - })(variable) + <span class="hljs-string">') {'</span> + EOL; - <span class="hljs-keyword">for</span> (i <span class="hljs-keyword">in</span> variable) { - out += indent(indentTimes) + <span class="hljs-string">'['</span> + i + <span class="hljs-string">']=> '</span> + EOL; - displayVar(variable[i]); - } - indentTimes--; - out += indent(indentTimes) + <span class="hljs-string">'}'</span> + EOL; - } <span class="hljs-keyword">else</span> { - displayVar(variable); - } - };</pre></div></div> - - </li> - - - <li id="section-326"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-326">¶</a> - </div> - <p>handle no argument case by dumping the entire render context</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (args.length == <span class="hljs-number">0</span>) args.push(<span class="hljs-keyword">this</span>.context); - - Twig.forEach(args, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">variable</span>) </span>{ - dumpVar(variable); - }); - - <span class="hljs-keyword">return</span> out; - }, - date: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">date, time</span>) </span>{ - <span class="hljs-keyword">var</span> dateObj; - <span class="hljs-keyword">if</span> (date === <span class="hljs-literal">undefined</span>) { - dateObj = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(); - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"Date"</span>, date)) { - dateObj = date; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"String"</span>, date)) { - <span class="hljs-keyword">if</span> (date.match(<span class="hljs-regexp">/^[0-9]+$/</span>)) { - dateObj = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(date * <span class="hljs-number">1000</span>); - } - <span class="hljs-keyword">else</span> { - dateObj = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(Twig.lib.strtotime(date) * <span class="hljs-number">1000</span>); - } - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">"Number"</span>, date)) {</pre></div></div> - - </li> - - - <li id="section-327"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-327">¶</a> - </div> - <p>timestamp</p> - - </div> - - <div class="content"><div class='highlight'><pre> dateObj = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(date * <span class="hljs-number">1000</span>); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to parse date "</span> + date); - } - <span class="hljs-keyword">return</span> dateObj; - }, - block: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">block</span>) </span>{ - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">this</span>.originalBlockTokens[block]) { - <span class="hljs-keyword">return</span> Twig.logic.parse.apply(<span class="hljs-keyword">this</span>, [<span class="hljs-keyword">this</span>.originalBlockTokens[block], <span class="hljs-keyword">this</span>.context]).output; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.blocks[block]; - } - }, - parent: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{</pre></div></div> - - </li> - - - <li id="section-328"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-328">¶</a> - </div> - <p>Add a placeholder</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> Twig.placeholders.parent; - }, - attribute: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">object, method, params</span>) </span>{ - <span class="hljs-keyword">if</span> (Twig.lib.is(<span class="hljs-string">'Object'</span>, object)) { - <span class="hljs-keyword">if</span> (object.hasOwnProperty(method)) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> object[method] === <span class="hljs-string">"function"</span>) { - <span class="hljs-keyword">return</span> object[method].apply(<span class="hljs-literal">undefined</span>, params); - } - <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> object[method]; - } - } - }</pre></div></div> - - </li> - - - <li id="section-329"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-329">¶</a> - </div> - <p>Array will return element 0-index</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> object[method] || <span class="hljs-literal">undefined</span>; - }, - max: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">values</span>) </span>{ - <span class="hljs-keyword">if</span>(Twig.lib.is(<span class="hljs-string">"Object"</span>, values)) { - <span class="hljs-keyword">delete</span> values[<span class="hljs-string">"_keys"</span>]; - <span class="hljs-keyword">return</span> Twig.lib.max(values); - } - - <span class="hljs-keyword">return</span> Twig.lib.max.apply(<span class="hljs-literal">null</span>, <span class="hljs-built_in">arguments</span>); - }, - min: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">values</span>) </span>{ - <span class="hljs-keyword">if</span>(Twig.lib.is(<span class="hljs-string">"Object"</span>, values)) { - <span class="hljs-keyword">delete</span> values[<span class="hljs-string">"_keys"</span>]; - <span class="hljs-keyword">return</span> Twig.lib.min(values); - } - - <span class="hljs-keyword">return</span> Twig.lib.min.apply(<span class="hljs-literal">null</span>, <span class="hljs-built_in">arguments</span>); - }, - template_from_string: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">template</span>) </span>{ - <span class="hljs-keyword">if</span> (template === <span class="hljs-literal">undefined</span>) { - template = <span class="hljs-string">''</span>; - } - <span class="hljs-keyword">return</span> Twig.Templates.parsers.twig({ - options: <span class="hljs-keyword">this</span>.options, - data: template - }); - }, - random: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">var</span> LIMIT_INT31 = <span class="hljs-number">0x80000000</span>; - - <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getRandomNumber</span>(<span class="hljs-params">n</span>) </span>{ - <span class="hljs-keyword">var</span> random = <span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * LIMIT_INT31); - <span class="hljs-keyword">var</span> limits = [<span class="hljs-number">0</span>, n]; - <span class="hljs-keyword">var</span> min = <span class="hljs-built_in">Math</span>.min.apply(<span class="hljs-literal">null</span>, limits), - max = <span class="hljs-built_in">Math</span>.max.apply(<span class="hljs-literal">null</span>, limits); - <span class="hljs-keyword">return</span> min + <span class="hljs-built_in">Math</span>.floor((max - min + <span class="hljs-number">1</span>) * random / LIMIT_INT31); - } - - <span class="hljs-keyword">if</span>(Twig.lib.is(<span class="hljs-string">"Number"</span>, value)) { - <span class="hljs-keyword">return</span> getRandomNumber(value); - } - - <span class="hljs-keyword">if</span>(Twig.lib.is(<span class="hljs-string">"String"</span>, value)) { - <span class="hljs-keyword">return</span> value.charAt(getRandomNumber(value.length<span class="hljs-number">-1</span>)); - } - - <span class="hljs-keyword">if</span>(Twig.lib.is(<span class="hljs-string">"Array"</span>, value)) { - <span class="hljs-keyword">return</span> value[getRandomNumber(value.length<span class="hljs-number">-1</span>)]; - } - - <span class="hljs-keyword">if</span>(Twig.lib.is(<span class="hljs-string">"Object"</span>, value)) { - <span class="hljs-keyword">var</span> keys = <span class="hljs-built_in">Object</span>.keys(value); - <span class="hljs-keyword">return</span> value[keys[getRandomNumber(keys.length<span class="hljs-number">-1</span>)]]; - } - - <span class="hljs-keyword">return</span> getRandomNumber(LIMIT_INT31<span class="hljs-number">-1</span>); - }, - - <span class="hljs-comment">/** - * Returns the content of a template without rendering it - * @param {string} name - * @param {boolean} [ignore_missing=false] - * @returns {string} - */</span> - source: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">name, ignore_missing</span>) </span>{ - <span class="hljs-keyword">var</span> templateSource; - <span class="hljs-keyword">var</span> templateFound = <span class="hljs-literal">false</span>; - <span class="hljs-keyword">var</span> isNodeEnvironment = <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">module</span> !== <span class="hljs-string">'undefined'</span> && <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">module</span>.exports !== <span class="hljs-string">'undefined'</span> && <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">window</span> === <span class="hljs-string">'undefined'</span>; - <span class="hljs-keyword">var</span> loader; - <span class="hljs-keyword">var</span> path;</pre></div></div> - - </li> - - - <li id="section-330"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-330">¶</a> - </div> - <p>if we are running in a node.js environment, set the loader to ‘fs’ and ensure the -path is relative to the CWD of the running script -else, set the loader to ‘ajax’ and set the path to the value of name</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (isNodeEnvironment) { - loader = <span class="hljs-string">'fs'</span>; - path = __dirname + <span class="hljs-string">'/'</span> + name; - } <span class="hljs-keyword">else</span> { - loader = <span class="hljs-string">'ajax'</span>; - path = name; - }</pre></div></div> - - </li> - - - <li id="section-331"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-331">¶</a> - </div> - <p>build the params object</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> params = { - id: name, - path: path, - method: loader, - parser: <span class="hljs-string">'source'</span>, - <span class="hljs-keyword">async</span>: <span class="hljs-literal">false</span>, - fetchTemplateSource: <span class="hljs-literal">true</span> - };</pre></div></div> - - </li> - - - <li id="section-332"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-332">¶</a> - </div> - <p>default ignore_missing to false</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> ignore_missing === <span class="hljs-string">'undefined'</span>) { - ignore_missing = <span class="hljs-literal">false</span>; - }</pre></div></div> - - </li> - - - <li id="section-333"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-333">¶</a> - </div> - <p>try to load the remote template</p> -<p>on exception, log it</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">try</span> { - templateSource = Twig.Templates.loadRemote(name, params);</pre></div></div> - - </li> - - - <li id="section-334"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-334">¶</a> - </div> - <p>if the template is undefined or null, set the template to an empty string and do NOT flip the -boolean indicating we found the template</p> -<p>else, all is good! flip the boolean indicating we found the template</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> templateSource === <span class="hljs-string">'undefined'</span> || templateSource === <span class="hljs-literal">null</span>) { - templateSource = <span class="hljs-string">''</span>; - } <span class="hljs-keyword">else</span> { - templateFound = <span class="hljs-literal">true</span>; - } - } <span class="hljs-keyword">catch</span> (e) { - Twig.log.debug(<span class="hljs-string">'Twig.functions.source: '</span>, <span class="hljs-string">'Problem loading template '</span>, e); - }</pre></div></div> - - </li> - - - <li id="section-335"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-335">¶</a> - </div> - <p>if the template was NOT found AND we are not ignoring missing templates, return the same message -that is returned by the PHP implementation of the twig source() function</p> -<p>else, return the template source</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (!templateFound && !ignore_missing) { - <span class="hljs-keyword">return</span> TEMPLATE_NOT_FOUND_MESSAGE.replace(<span class="hljs-string">'{name}'</span>, name); - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">return</span> templateSource; - } - } - }; - - Twig._function = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">_function, value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (!Twig.functions[_function]) { - <span class="hljs-keyword">throw</span> <span class="hljs-string">"Unable to find function "</span> + _function; - } - <span class="hljs-keyword">return</span> Twig.functions[_function](value, params); - }; - - Twig._function.extend = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">_function, definition</span>) </span>{ - Twig.functions[_function] = definition; - }; - - <span class="hljs-keyword">return</span> Twig; - -})(Twig || { });</pre></div></div> - - </li> - - - <li id="section-336"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-336">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-337"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-337">¶</a> - </div> - <h2 id="twig-path-js">twig.path.js</h2> -<p>This file handles path parsing</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> "use strict"</span>; - - <span class="hljs-comment">/** - * Namespace for path handling. - */</span> - Twig.path = {}; - - <span class="hljs-comment">/** - * Generate the canonical version of a url based on the given base path and file path and in - * the previously registered namespaces. - * - * @param {string} template The Twig Template - * @param {string} file The file path, may be relative and may contain namespaces. - * - * @return {string} The canonical version of the path - */</span> - Twig.path.parsePath = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">template, file</span>) </span>{ - <span class="hljs-keyword">var</span> namespaces = <span class="hljs-literal">null</span>, - file = file || <span class="hljs-string">""</span>; - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> template === <span class="hljs-string">'object'</span> && <span class="hljs-keyword">typeof</span> template.options === <span class="hljs-string">'object'</span>) { - namespaces = template.options.namespaces; - } - - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> namespaces === <span class="hljs-string">'object'</span> && (file.indexOf(<span class="hljs-string">'::'</span>) > <span class="hljs-number">0</span>) || file.indexOf(<span class="hljs-string">'@'</span>) >= <span class="hljs-number">0</span>){ - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> k <span class="hljs-keyword">in</span> namespaces){ - <span class="hljs-keyword">if</span> (namespaces.hasOwnProperty(k)) { - file = file.replace(k + <span class="hljs-string">'::'</span>, namespaces[k]); - file = file.replace(<span class="hljs-string">'@'</span> + k, namespaces[k]); - } - } - - <span class="hljs-keyword">return</span> file; - } - - <span class="hljs-keyword">return</span> Twig.path.relativePath(template, file); - }; - - <span class="hljs-comment">/** - * Generate the relative canonical version of a url based on the given base path and file path. - * - * @param {Twig.Template} template The Twig.Template. - * @param {string} file The file path, relative to the base path. - * - * @return {string} The canonical version of the path. - */</span> - Twig.path.relativePath = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">template, file</span>) </span>{ - <span class="hljs-keyword">var</span> base, - base_path, - sep_chr = <span class="hljs-string">"/"</span>, - new_path = [], - file = file || <span class="hljs-string">""</span>, - val; - - <span class="hljs-keyword">if</span> (template.url) { - <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> template.base !== <span class="hljs-string">'undefined'</span>) { - base = template.base + ((template.base.charAt(template.base.length<span class="hljs-number">-1</span>) === <span class="hljs-string">'/'</span>) ? <span class="hljs-string">''</span> : <span class="hljs-string">'/'</span>); - } <span class="hljs-keyword">else</span> { - base = template.url; - } - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (template.path) {</pre></div></div> - - </li> - - - <li id="section-338"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-338">¶</a> - </div> - <p>Get the system-specific path separator</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">"path"</span>), - sep = path.sep || sep_chr, - relative = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">"^\\.{1,2}"</span> + sep.replace(<span class="hljs-string">"\\"</span>, <span class="hljs-string">"\\\\"</span>)); - file = file.replace(<span class="hljs-regexp">/\//g</span>, sep); - - <span class="hljs-keyword">if</span> (template.base !== <span class="hljs-literal">undefined</span> && file.match(relative) == <span class="hljs-literal">null</span>) { - file = file.replace(template.base, <span class="hljs-string">''</span>); - base = template.base + sep; - } <span class="hljs-keyword">else</span> { - base = path.normalize(template.path); - } - - base = base.replace(sep+sep, sep); - sep_chr = sep; - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ((template.name || template.id) && template.method && template.method !== <span class="hljs-string">'fs'</span> && template.method !== <span class="hljs-string">'ajax'</span>) {</pre></div></div> - - </li> - - - <li id="section-339"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-339">¶</a> - </div> - <p>Custom registered loader</p> - - </div> - - <div class="content"><div class='highlight'><pre> base = template.base || template.name || template.id; - } <span class="hljs-keyword">else</span> { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Cannot extend an inline template."</span>); - } - - base_path = base.split(sep_chr);</pre></div></div> - - </li> - - - <li id="section-340"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-340">¶</a> - </div> - <p>Remove file from url</p> - - </div> - - <div class="content"><div class='highlight'><pre> base_path.pop(); - base_path = base_path.concat(file.split(sep_chr)); - - <span class="hljs-keyword">while</span> (base_path.length > <span class="hljs-number">0</span>) { - val = base_path.shift(); - <span class="hljs-keyword">if</span> (val == <span class="hljs-string">"."</span>) {</pre></div></div> - - </li> - - - <li id="section-341"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-341">¶</a> - </div> - <p>Ignore</p> - - </div> - - <div class="content"><div class='highlight'><pre> } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (val == <span class="hljs-string">".."</span> && new_path.length > <span class="hljs-number">0</span> && new_path[new_path.length<span class="hljs-number">-1</span>] != <span class="hljs-string">".."</span>) { - new_path.pop(); - } <span class="hljs-keyword">else</span> { - new_path.push(val); - } - } - - <span class="hljs-keyword">return</span> new_path.join(sep_chr); - }; - - <span class="hljs-keyword">return</span> Twig; -}) (Twig || { });</pre></div></div> - - </li> - - - <li id="section-342"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-342">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-343"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-343">¶</a> - </div> - <h2 id="twig-tests-js">twig.tests.js</h2> -<p>This file handles expression tests. (is empty, is not defined, etc…)</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> "use strict"</span>; - Twig.tests = { - empty: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">if</span> (value === <span class="hljs-literal">null</span> || value === <span class="hljs-literal">undefined</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;</pre></div></div> - - </li> - - - <li id="section-344"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-344">¶</a> - </div> - <p>Handler numbers</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> value === <span class="hljs-string">"number"</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; <span class="hljs-comment">// numbers are never "empty"</span></pre></div></div> - - </li> - - - <li id="section-345"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-345">¶</a> - </div> - <p>Handle strings and arrays</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (value.length && value.length > <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</pre></div></div> - - </li> - - - <li id="section-346"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-346">¶</a> - </div> - <p>Handle objects</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> key <span class="hljs-keyword">in</span> value) { - <span class="hljs-keyword">if</span> (value.hasOwnProperty(key)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>; - } - <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>; - }, - odd: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">return</span> value % <span class="hljs-number">2</span> === <span class="hljs-number">1</span>; - }, - even: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">return</span> value % <span class="hljs-number">2</span> === <span class="hljs-number">0</span>; - }, - divisibleby: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">return</span> value % params[<span class="hljs-number">0</span>] === <span class="hljs-number">0</span>; - }, - defined: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">return</span> value !== <span class="hljs-literal">undefined</span>; - }, - none: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">return</span> value === <span class="hljs-literal">null</span>; - }, - <span class="hljs-string">'null'</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.none(value); <span class="hljs-comment">// Alias of none</span> - }, - sameas: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value, params</span>) </span>{ - <span class="hljs-keyword">return</span> value === params[<span class="hljs-number">0</span>]; - }, - iterable: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">value</span>) </span>{ - <span class="hljs-keyword">return</span> value && (Twig.lib.is(<span class="hljs-string">"Array"</span>, value) || Twig.lib.is(<span class="hljs-string">"Object"</span>, value)); - } - <span class="hljs-comment">/* - constant ? - */</span> - }; - - Twig.test = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">test, value, params</span>) </span>{ - <span class="hljs-keyword">if</span> (!Twig.tests[test]) { - <span class="hljs-keyword">throw</span> <span class="hljs-string">"Test "</span> + test + <span class="hljs-string">" is not defined."</span>; - } - <span class="hljs-keyword">return</span> Twig.tests[test](value, params); - }; - - Twig.test.extend = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">test, definition</span>) </span>{ - Twig.tests[test] = definition; - }; - - <span class="hljs-keyword">return</span> Twig; -})( Twig || { } );</pre></div></div> - - </li> - - - <li id="section-347"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-347">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-348"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-348">¶</a> - </div> - <h2 id="twig-exports-js">twig.exports.js</h2> -<p>This file provides extension points and other hooks into the twig functionality.</p> - - </div> - - <div class="content"><div class='highlight'><pre> -<span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ -<span class="hljs-meta"> "use strict"</span>; - Twig.exports = { - VERSION: Twig.VERSION - }; - - <span class="hljs-comment">/** - * Create and compile a twig.js template. - * - * @param {Object} param Paramteres for creating a Twig template. - * - * @return {Twig.Template} A Twig template ready for rendering. - */</span> - Twig.exports.twig = <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">twig</span>(<span class="hljs-params">params</span>) </span>{ -<span class="hljs-meta"> 'use strict'</span>; - <span class="hljs-keyword">var</span> id = params.id, - options = { - strict_variables: params.strict_variables || <span class="hljs-literal">false</span>,</pre></div></div> - - </li> - - - <li id="section-349"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-349">¶</a> - </div> - <p>TODO: turn autoscape on in the next major version</p> - - </div> - - <div class="content"><div class='highlight'><pre> autoescape: params.autoescape != <span class="hljs-literal">null</span> && params.autoescape || <span class="hljs-literal">false</span>, - allowInlineIncludes: params.allowInlineIncludes || <span class="hljs-literal">false</span>, - rethrow: params.rethrow || <span class="hljs-literal">false</span>, - namespaces: params.namespaces - }; - - <span class="hljs-keyword">if</span> (Twig.cache && id) { - Twig.validateId(id); - } - - <span class="hljs-keyword">if</span> (params.debug !== <span class="hljs-literal">undefined</span>) { - Twig.debug = params.debug; - } - <span class="hljs-keyword">if</span> (params.trace !== <span class="hljs-literal">undefined</span>) { - Twig.trace = params.trace; - } - - <span class="hljs-keyword">if</span> (params.data !== <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">return</span> Twig.Templates.parsers.twig({ - data: params.data, - path: params.hasOwnProperty(<span class="hljs-string">'path'</span>) ? params.path : <span class="hljs-literal">undefined</span>, - <span class="hljs-built_in">module</span>: params.module, - id: id, - options: options - }); - - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (params.ref !== <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">if</span> (params.id !== <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Both ref and id cannot be set on a twig.js template."</span>); - } - <span class="hljs-keyword">return</span> Twig.Templates.load(params.ref); - - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (params.method !== <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">if</span> (!Twig.Templates.isRegisteredLoader(params.method)) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">'Loader for "'</span> + params.method + <span class="hljs-string">'" is not defined.'</span>); - } - <span class="hljs-keyword">return</span> Twig.Templates.loadRemote(params.name || params.href || params.path || id || <span class="hljs-literal">undefined</span>, { - id: id, - method: params.method, - parser: params.parser || <span class="hljs-string">'twig'</span>, - base: params.base, - <span class="hljs-built_in">module</span>: params.module, - precompiled: params.precompiled, - <span class="hljs-keyword">async</span>: params.async, - options: options - - }, params.load, params.error); - - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (params.href !== <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">return</span> Twig.Templates.loadRemote(params.href, { - id: id, - method: <span class="hljs-string">'ajax'</span>, - parser: params.parser || <span class="hljs-string">'twig'</span>, - base: params.base, - <span class="hljs-built_in">module</span>: params.module, - precompiled: params.precompiled, - <span class="hljs-keyword">async</span>: params.async, - options: options - - }, params.load, params.error); - - } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (params.path !== <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">return</span> Twig.Templates.loadRemote(params.path, { - id: id, - method: <span class="hljs-string">'fs'</span>, - parser: params.parser || <span class="hljs-string">'twig'</span>, - base: params.base, - <span class="hljs-built_in">module</span>: params.module, - precompiled: params.precompiled, - <span class="hljs-keyword">async</span>: params.async, - options: options - - }, params.load, params.error); - } - };</pre></div></div> - - </li> - - - <li id="section-350"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-350">¶</a> - </div> - <p>Extend Twig with a new filter.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.exports.extendFilter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">filter, definition</span>) </span>{ - Twig.filter.extend(filter, definition); - };</pre></div></div> - - </li> - - - <li id="section-351"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-351">¶</a> - </div> - <p>Extend Twig with a new function.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.exports.extendFunction = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn, definition</span>) </span>{ - Twig._function.extend(fn, definition); - };</pre></div></div> - - </li> - - - <li id="section-352"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-352">¶</a> - </div> - <p>Extend Twig with a new test.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.exports.extendTest = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">test, definition</span>) </span>{ - Twig.test.extend(test, definition); - };</pre></div></div> - - </li> - - - <li id="section-353"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-353">¶</a> - </div> - <p>Extend Twig with a new definition.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.exports.extendTag = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">definition</span>) </span>{ - Twig.logic.extend(definition); - };</pre></div></div> - - </li> - - - <li id="section-354"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-354">¶</a> - </div> - <p>Provide an environment for extending Twig core. -Calls fn with the internal Twig object.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.exports.extend = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">fn</span>) </span>{ - fn(Twig); - }; - - - <span class="hljs-comment">/** - * Provide an extension for use with express 2. - * - * @param {string} markup The template markup. - * @param {array} options The express options. - * - * @return {string} The rendered template. - */</span> - Twig.exports.compile = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">markup, options</span>) </span>{ - <span class="hljs-keyword">var</span> id = options.filename, - path = options.filename, - template;</pre></div></div> - - </li> - - - <li id="section-355"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-355">¶</a> - </div> - <p>Try to load the template from the cache</p> - - </div> - - <div class="content"><div class='highlight'><pre> template = <span class="hljs-keyword">new</span> Twig.Template({ - data: markup, - path: path, - id: id, - options: options.settings[<span class="hljs-string">'twig options'</span>] - }); <span class="hljs-comment">// Twig.Templates.load(id) ||</span> - - <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">context</span>) </span>{ - <span class="hljs-keyword">return</span> template.render(context); - }; - }; - - <span class="hljs-comment">/** - * Provide an extension for use with express 3. - * - * @param {string} path The location of the template file on disk. - * @param {Object|Function} The options or callback. - * @param {Function} fn callback. - * - * @throws Twig.Error - */</span> - Twig.exports.renderFile = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">path, options, fn</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-356"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-356">¶</a> - </div> - <p>handle callback in options</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> options === <span class="hljs-string">'function'</span>) { - fn = options; - options = {}; - } - - options = options || {}; - - <span class="hljs-keyword">var</span> settings = options.settings || {}; - - <span class="hljs-keyword">var</span> params = { - path: path, - base: settings.views, - load: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">template</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-357"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-357">¶</a> - </div> - <p>render and return template</p> - - </div> - - <div class="content"><div class='highlight'><pre> fn(<span class="hljs-literal">null</span>, template.render(options)); - } - };</pre></div></div> - - </li> - - - <li id="section-358"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-358">¶</a> - </div> - <p>mixin any options provided to the express app.</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> view_options = settings[<span class="hljs-string">'twig options'</span>]; - - <span class="hljs-keyword">if</span> (view_options) { - <span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> option <span class="hljs-keyword">in</span> view_options) { - <span class="hljs-keyword">if</span> (view_options.hasOwnProperty(option)) { - params[option] = view_options[option]; - } - } - } - - Twig.exports.twig(params); - };</pre></div></div> - - </li> - - - <li id="section-359"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-359">¶</a> - </div> - <p>Express 3 handler</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.exports.__express = Twig.exports.renderFile; - - <span class="hljs-comment">/** - * Shoud Twig.js cache templates. - * Disable during development to see changes to templates without - * reloading, and disable in production to improve performance. - * - * @param {boolean} cache - */</span> - Twig.exports.cache = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cache</span>) </span>{ - Twig.cache = cache; - };</pre></div></div> - - </li> - - - <li id="section-360"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-360">¶</a> - </div> - <p>We need to export the path module so we can effectively test it</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.exports.path = Twig.path; - - <span class="hljs-keyword">return</span> Twig; -}) (Twig || { });</pre></div></div> - - </li> - - - <li id="section-361"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-361">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-362"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-362">¶</a> - </div> - <h2 id="twig-compiler-js">twig.compiler.js</h2> -<p>This file handles compiling templates into JS</p> - - </div> - - <div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> Twig = (<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">Twig</span>) </span>{ - <span class="hljs-comment">/** - * Namespace for compilation. - */</span> - Twig.compiler = { - <span class="hljs-built_in">module</span>: {} - };</pre></div></div> - - </li> - - - <li id="section-363"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-363">¶</a> - </div> - <p>Compile a Twig Template to output.</p> - - </div> - - <div class="content"><div class='highlight'><pre> Twig.compiler.compile = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">template, options</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-364"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-364">¶</a> - </div> - <p>Get tokens</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> tokens = <span class="hljs-built_in">JSON</span>.stringify(template.tokens) - , id = template.id - , output; - - <span class="hljs-keyword">if</span> (options.module) { - <span class="hljs-keyword">if</span> (Twig.compiler.module[options.module] === <span class="hljs-literal">undefined</span>) { - <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Twig.Error(<span class="hljs-string">"Unable to find module type "</span> + options.module); - } - output = Twig.compiler.module[options.module](id, tokens, options.twig); - } <span class="hljs-keyword">else</span> { - output = Twig.compiler.wrap(id, tokens); - } - <span class="hljs-keyword">return</span> output; - }; - - Twig.compiler.module = { - amd: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">id, tokens, pathToTwig</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-string">'define(["'</span> + pathToTwig + <span class="hljs-string">'"], function (Twig) {\n\tvar twig, templates;\ntwig = Twig.twig;\ntemplates = '</span> + Twig.compiler.wrap(id, tokens) + <span class="hljs-string">'\n\treturn templates;\n});'</span>; - } - , node: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">id, tokens</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-string">'var twig = require("twig").twig;\n'</span> - + <span class="hljs-string">'exports.template = '</span> + Twig.compiler.wrap(id, tokens) - } - , cjs2: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">id, tokens, pathToTwig</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-string">'module.declare([{ twig: "'</span> + pathToTwig + <span class="hljs-string">'" }], function (require, exports, module) {\n'</span> - + <span class="hljs-string">'\tvar twig = require("twig").twig;\n'</span> - + <span class="hljs-string">'\texports.template = '</span> + Twig.compiler.wrap(id, tokens) - + <span class="hljs-string">'\n});'</span> - } - }; - - Twig.compiler.wrap = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">id, tokens</span>) </span>{ - <span class="hljs-keyword">return</span> <span class="hljs-string">'twig({id:"'</span>+id.replace(<span class="hljs-string">'"'</span>, <span class="hljs-string">'\\"'</span>)+<span class="hljs-string">'", data:'</span>+tokens+<span class="hljs-string">', precompiled: true});\n'</span>; - }; - - <span class="hljs-keyword">return</span> Twig; -})(Twig || {});</pre></div></div> - - </li> - - - <li id="section-365"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-365">¶</a> - </div> - <pre><code>Twig.js -Available under the BSD <span class="hljs-number">2</span>-Clause License -https:<span class="hljs-comment">//github.com/justjohn/twig.js</span> -</code></pre> - </div> - - </li> - - - <li id="section-366"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-366">¶</a> - </div> - <h2 id="twig-module-js">twig.module.js</h2> -<p>Provide a CommonJS/AMD/Node module export.</p> - - </div> - - <div class="content"><div class='highlight'><pre> -<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">module</span> !== <span class="hljs-string">'undefined'</span> && <span class="hljs-built_in">module</span>.declare) {</pre></div></div> - - </li> - - - <li id="section-367"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-367">¶</a> - </div> - <p>Provide a CommonJS Modules/2.0 draft 8 module</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-built_in">module</span>.declare([], <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">require, exports, module</span>) </span>{</pre></div></div> - - </li> - - - <li id="section-368"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-368">¶</a> - </div> - <p>Add exports from the Twig exports</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-keyword">for</span> (key <span class="hljs-keyword">in</span> Twig.exports) { - <span class="hljs-keyword">if</span> (Twig.exports.hasOwnProperty(key)) { - exports[key] = Twig.exports[key]; - } - } - }); -} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> define == <span class="hljs-string">'function'</span> && define.amd) { - define(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{ - <span class="hljs-keyword">return</span> Twig.exports; - }); -} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> <span class="hljs-built_in">module</span> !== <span class="hljs-string">'undefined'</span> && <span class="hljs-built_in">module</span>.exports) {</pre></div></div> - - </li> - - - <li id="section-369"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-369">¶</a> - </div> - <p>Provide a CommonJS Modules/1.1 module</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-built_in">module</span>.exports = Twig.exports; -} <span class="hljs-keyword">else</span> {</pre></div></div> - - </li> - - - <li id="section-370"> - <div class="annotation"> - - <div class="pilwrap "> - <a class="pilcrow" href="#section-370">¶</a> - </div> - <p>Export for browser use</p> - - </div> - - <div class="content"><div class='highlight'><pre> <span class="hljs-built_in">window</span>.twig = Twig.exports.twig; - <span class="hljs-built_in">window</span>.Twig = Twig.exports; -}</pre></div></div> - - </li> - - </ul> - </div> -</body> -</html> |