MDL-65758 library: Update mustache.js to 3.0.1
authorMathew May <mathewm@hotmail.co.nz>
Wed, 12 Jun 2019 02:58:58 +0000 (10:58 +0800)
committerMathew May <mathewm@hotmail.co.nz>
Wed, 12 Jun 2019 02:58:58 +0000 (10:58 +0800)
lib/amd/build/mustache.min.js
lib/amd/src/mustache.js
lib/thirdpartylibs.xml

index e28c528..ab7d884 100644 (file)
Binary files a/lib/amd/build/mustache.min.js and b/lib/amd/build/mustache.min.js differ
index 29135a1..8ec1b44 100644 (file)
@@ -1,44 +1,9 @@
-// The MIT License
-//
-// Copyright (c) 2009 Chris Wanstrath (Ruby)
-// Copyright (c) 2010-2014 Jan Lehnardt (JavaScript)
-// Copyright (c) 2010-2015 The mustache.js community
-//
-// 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.
-//
-
-// Description of import into Moodle:
-// Checkout from https://github.com/moodle/custom-mustache.js
-// Rebase onto latest release tag from https://github.com/janl/mustache.js
-// Copy mustache.js into lib/amd/src/ in Moodle folder.
-// Add the license as a comment to the file and these instructions.
-// Add jshint tags so this file is not linted.
-// Remove the "global define:" comment (hint for linter)
-// Make sure that you have not removed the custom code for '$' and '<'.
-
 /*!
  * mustache.js - Logic-less {{mustache}} templates with JavaScript
  * http://github.com/janl/mustache.js
  */
 
-/* jshint ignore:start */
+/*global define: false Mustache: true*/
 
 (function defineMustache (global, factory) {
   if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {
     return obj != null && typeof obj === 'object' && (propName in obj);
   }
 
+  /**
+   * Safe way of detecting whether or not the given thing is a primitive and
+   * whether it has the given property
+   */
+  function primitiveHasOwnProperty (primitive, propName) {  
+    return (
+      primitive != null
+      && typeof primitive !== 'object'
+      && primitive.hasOwnProperty
+      && primitive.hasOwnProperty(propName)
+    );
+  }
+
   // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
   // See https://github.com/janl/mustache.js/issues/189
   var regExpTest = RegExp.prototype.test;
   var spaceRe = /\s+/;
   var equalsRe = /\s*=/;
   var curlyRe = /\s*\}/;
-  var tagRe = /#|\^|\/|>|\{|&|=|!|\$|</;
+  var tagRe = /#|\^|\/|>|\{|&|=|!/;
 
   /**
    * Breaks up the given `template` string into a tree of tokens. If the `tags`
       token = [ type, value, start, scanner.pos ];
       tokens.push(token);
 
-      if (type === '#' || type === '^' || type === '$' || type === '<') {
+      if (type === '#' || type === '^') {
         sections.push(token);
       } else if (type === '/') {
         // Check section nesting.
       token = tokens[i];
 
       switch (token[0]) {
-        case '$':
-        case '<':
         case '#':
         case '^':
           collector.push(token);
    */
   function Context (view, parentContext) {
     this.view = view;
-    this.blocks = {};
     this.cache = { '.': this.view };
     this.parent = parentContext;
   }
     return new Context(view, this);
   };
 
-  /**
-   * Set a value in the current block context.
-   */
-  Context.prototype.setBlockVar = function set (name, value) {
-    var blocks = this.blocks;
-
-    blocks[name] = value;
-
-    return value;
-  };
-
-  /**
-   * Clear all current block vars.
-   */
-  Context.prototype.clearBlockVars = function clearBlockVars () {
-    this.blocks = {};
-  };
-
-  /**
-   * Get a value only from the current block context.
-   */
-  Context.prototype.getBlockVar = function getBlockVar (name) {
-    var blocks = this.blocks;
-
-    var value;
-    if (blocks.hasOwnProperty(name)) {
-      value = blocks[name];
-    } else {
-      if (this.parent) {
-        value = this.parent.getBlockVar(name);
-      }
-    }
-    // Can return undefined.
-    return value;
-  };
-
   /**
    * Returns the value of the given name in this context, traversing
    * up the context hierarchy if the value is absent in this context's view.
     if (cache.hasOwnProperty(name)) {
       value = cache[name];
     } else {
-      var context = this, names, index, lookupHit = false;
+      var context = this, intermediateValue, names, index, lookupHit = false;
 
       while (context) {
         if (name.indexOf('.') > 0) {
-          value = context.view;
+          intermediateValue = context.view;
           names = name.split('.');
           index = 0;
 
            *
            * This is specially necessary for when the value has been set to
            * `undefined` and we want to avoid looking up parent contexts.
+           *
+           * In the case where dot notation is used, we consider the lookup
+           * to be successful even if the last "object" in the path is
+           * not actually an object but a primitive (e.g., a string, or an
+           * integer), because it is sometimes useful to access a property
+           * of an autoboxed primitive, such as the length of a string.
            **/
-          while (value != null && index < names.length) {
+          while (intermediateValue != null && index < names.length) {
             if (index === names.length - 1)
-              lookupHit = hasProperty(value, names[index]);
+              lookupHit = (
+                hasProperty(intermediateValue, names[index]) 
+                || primitiveHasOwnProperty(intermediateValue, names[index])
+              );
 
-            value = value[names[index++]];
+            intermediateValue = intermediateValue[names[index++]];
           }
         } else {
-          value = context.view[name];
+          intermediateValue = context.view[name];
+
+          /**
+           * Only checking against `hasProperty`, which always returns `false` if
+           * `context.view` is not an object. Deliberately omitting the check
+           * against `primitiveHasOwnProperty` if dot notation is not used.
+           *
+           * Consider this example:
+           * ```
+           * Mustache.render("The length of a football field is {{#length}}{{length}}{{/length}}.", {length: "100 yards"})
+           * ```
+           *
+           * If we were to check also against `primitiveHasOwnProperty`, as we do
+           * in the dot notation case, then render call would return:
+           *
+           * "The length of a football field is 9."
+           *
+           * rather than the expected:
+           *
+           * "The length of a football field is 100 yards."
+           **/
           lookupHit = hasProperty(context.view, name);
         }
 
-        if (lookupHit)
+        if (lookupHit) {
+          value = intermediateValue;
           break;
+        }
 
         context = context.parent;
       }
   };
 
   /**
-   * Parses and caches the given `template` and returns the array of tokens
+   * Parses and caches the given `template` according to the given `tags` or
+   * `mustache.tags` if `tags` is omitted,  and returns the array of tokens
    * that is generated from the parse.
    */
   Writer.prototype.parse = function parse (template, tags) {
     var cache = this.cache;
-    var tokens = cache[template];
+    var cacheKey = template + ':' + (tags || mustache.tags).join(':');
+    var tokens = cache[cacheKey];
 
     if (tokens == null)
-      tokens = cache[template + ':' + (tags || mustache.tags).join(':')] = parseTemplate(template, tags);
+      tokens = cache[cacheKey] = parseTemplate(template, tags);
 
     return tokens;
   };
    * names and templates of partials that are used in the template. It may
    * also be a function that is used to load partial templates on the fly
    * that takes a single argument: the name of the partial.
+   *
+   * If the optional `tags` argument is given here it must be an array with two
+   * string values: the opening and closing tags used in the template (e.g.
+   * [ "<%", "%>" ]). The default is to mustache.tags.
    */
-  Writer.prototype.render = function render (template, view, partials) {
-    var tokens = this.parse(template);
+  Writer.prototype.render = function render (template, view, partials, tags) {
+    var tokens = this.parse(template, tags);
     var context = (view instanceof Context) ? view : new Context(view);
-    return this.renderTokens(tokens, context, partials, template);
+    return this.renderTokens(tokens, context, partials, template, tags);
   };
 
   /**
    * If the template doesn't use higher-order sections, this argument may
    * be omitted.
    */
-  Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {
+  Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate, tags) {
     var buffer = '';
 
     var token, symbol, value;
 
       if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);
       else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);
-      else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);
-      else if (symbol === '<') value = this.renderBlock(token, context, partials, originalTemplate);
-      else if (symbol === '$') value = this.renderBlockVariable(token, context, partials, originalTemplate);
+      else if (symbol === '>') value = this.renderPartial(token, context, partials, tags);
       else if (symbol === '&') value = this.unescapedValue(token, context);
       else if (symbol === 'name') value = this.escapedValue(token, context);
       else if (symbol === 'text') value = this.rawValue(token);
       return this.renderTokens(token[4], context, partials, originalTemplate);
   };
 
-  Writer.prototype.renderPartial = function renderPartial (token, context, partials) {
+  Writer.prototype.renderPartial = function renderPartial (token, context, partials, tags) {
     if (!partials) return;
 
     var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
     if (value != null)
-      return this.renderTokens(this.parse(value), context, partials, value);
-  };
-
-  Writer.prototype.renderBlock = function renderBlock (token, context, partials, originalTemplate) {
-    if (!partials) return;
-
-    var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
-    if (value != null)
-      // Ignore any wrongly set block vars before we started.
-      context.clearBlockVars();
-      // We are only rendering to record the default block variables.
-      this.renderTokens(token[4], context, partials, originalTemplate);
-      // Now we render and return the result.
-      var result = this.renderTokens(this.parse(value), context, partials, value);
-      // Don't leak the block variables outside this include.
-      context.clearBlockVars();
-      return result;
-  };
-
-  Writer.prototype.renderBlockVariable = function renderBlockVariable (token, context, partials, originalTemplate) {
-    var value = token[1];
-
-    var exists = context.getBlockVar(value);
-    if (!exists) {
-      context.setBlockVar(value, originalTemplate.slice(token[3], token[5]));
-      return this.renderTokens(token[4], context, partials, originalTemplate);
-    } else {
-      return this.renderTokens(this.parse(exists), context, partials, exists);
-    }
+      return this.renderTokens(this.parse(value, tags), context, partials, value);
   };
 
   Writer.prototype.unescapedValue = function unescapedValue (token, context) {
   };
 
   mustache.name = 'mustache.js';
-  mustache.version = '2.3.0';
+  mustache.version = '3.0.1';
   mustache.tags = [ '{{', '}}' ];
 
   // All high-level mustache.* functions use this writer.
 
   /**
    * Renders the `template` with the given `view` and `partials` using the
-   * default writer.
+   * default writer. If the optional `tags` argument is given here it must be an
+   * array with two string values: the opening and closing tags used in the
+   * template (e.g. [ "<%", "%>" ]). The default is to mustache.tags.
    */
-  mustache.render = function render (template, view, partials) {
+  mustache.render = function render (template, view, partials, tags) {
     if (typeof template !== 'string') {
       throw new TypeError('Invalid template! Template should be a "string" ' +
                           'but "' + typeStr(template) + '" was given as the first ' +
                           'argument for mustache#render(template, view, partials)');
     }
 
-    return defaultWriter.render(template, view, partials);
+    return defaultWriter.render(template, view, partials, tags);
   };
 
   // This is here for backwards compatibility with 0.4.x.,
 
   return mustache;
 }));
-/* jshint ignore:end */
index 85d046b..7a677cf 100644 (file)
     <location>amd/src/mustache.js</location>
     <name>Mustache.js</name>
     <license>MIT</license>
-    <version>2.3.0</version>
+    <version>3.0.1</version>
   </library>
   <library>
     <location>graphlib.php</location>