Roxen.git / server / etc / modules / Mustache.pike

version» Context lines:

Roxen.git/server/etc/modules/Mustache.pike:18:   //! {{^preamble}}   //! <div class="notify">Preamble is missing</div>   //! {{/preamble}}   //!   //! <ul>   //! {{#names}}   //! <li>{{>name_row}}</li>   //! {{/names}}   //! </ul>";   //! - //! Public.Templates.Mustasche stash = Public.Templates.Mustasche(); + //! Mustache stash = Mustache();   //!   //! // Not strictly necessary, but this pre-parses and caches the template   //! stash->parse(tmpl);   //!   //! mappping data = ([   //! "header" : "This is a header",   //! "preamble" : "This is the preamble text",   //! "names" : ({   //! ([ "name" : "Lisa", "age" : 29 ]),   //! ([ "name" : "Mark", "age" : 43 ]),   //! ([ "name" : "Anna", "age" : 61 ])   //! })   //! ]);   //! - //! string html = stash.render(tmpl, data, - //! ([ "name_row" : - //! "<li>{{name}} is {{age}} years old</li>"])); + //! string html = stash->render(tmpl, data, + //! ([ "name_row" : + //! "<li>{{name}} is {{age}} years old</li>"]));   //! @endcode   //!   //! The output of the above would be something like   //!   //! @code   //! <h1>This is a header</h1>   //! <p>This is the preamble text</p>   //! <ul>   //! <li>Lisa is 29 years old</li>   //! <li>Mark is 43 years old</li>
Roxen.git/server/etc/modules/Mustache.pike:58:   //! @endcode      import Regexp.PCRE;      #ifdef MUSTACHE_DEBUG   # define TRACE(X...)werror("%s:%d: %s",basename(__FILE__),__LINE__,sprintf(X))   #else   # define TRACE(X...)0   #endif    +  + //! Parses and caches the given template in the default writer and returns the + //! array of tokens it contains. Doing this ahead of time avoids the need to + //! parse templates on the fly as they are rendered. + //! + //! @param template + //! Mustache template + //! + //! @param tags + //! Optional tags to use instead of the default @tt{ {{ }} @} + public array(Token) parse(string template, void|array(string) tags) + { +  return parse_template(template, tags); + } +  + //! Renders the @[template] with the given @[view] and @[partials]. + public string render(string template, mixed view, void|mixed partials) + { +  return render_template(template, view, partials); + } +  + //! Clears all cached templates + public void clear_cache() + { +  __cache = ([]); + } +  +    //! @ignore   //! Internal helper class   protected class Re   {    inherit Widestring;       int search(string s)    {    array(int)|int r = ::exec(s);   
Roxen.git/server/etc/modules/Mustache.pike:130:    "<" : "&lt;",    ">" : "&gt;",    "\"" : "&quot;",    "'" : "&#39;",    "/" : "&#x2F;",    "`" : "&#x60;",    "=" : "&#x3D;"   ]);      //! HTML escape the string @[s] - public string escape_html(string s) + protected string escape_html(string s)   {    return _re_escape_html->replace(s, lambda (string a) {    return entity_map[a] || a;    });   }      //! A simple string scanner that is used by the template parser to find   //! tokens in template strings.   protected class Scanner   {
Roxen.git/server/etc/modules/Mustache.pike:299:    case "array":    return ({ type, value, start, end, extra, extra2 });       default:    error("Unknown cast (%O) in object! ", how);    }    }       string _sprintf(int t)    { -  return sprintf("({ %O, %O, %O, %O, %O, %O })", +  return sprintf("Token({ %O, %O, %O, %O, %O, %O })",    type, value, start, end, extra, extra2);    }      #ifdef MUSTACHE_DEBUG    protected void destroy()    { -  TRACE("Token destroyed!\n"); +  TRACE("Token(%O, ...) destroyed!\n", type);    }   #endif   }      //! Breaks up the given @[template] string into a tree of tokens. If the   //! @[_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.   //! @tt{[ "<%", "%>" ]@}). Of course, the default is to use mustaches   //! (i.e. mustache.tags). - array(Token) parse_template(string|function template, void|array(string) _tags) + protected array(Token) + low_parse_template(string|function template, void|array(string) _tags)   {    if (functionp(template)) {    template = (string)template(0);    }       if (!template || !sizeof(template)) {    return ({});    }       array(Token) sections = ({}); // Stack to hold section tokens    array(Token) tokens = ({}); // Buffer to hold the tokens    array(int) spaces = ({}); // Indices of whitespace tokens on the current line    bool has_tag = false; // Is there a {{tag}} on the current line?    bool none_space = false; // Is there a non-space char on the current line?       // Strips all whitespace tokens array for the current line    // if there was a {{#tag}} on it and otherwise only space. -  void strip_space() { -  if (has_tag && !none_space) { -  while (sizeof(spaces)) { -  int t = spaces[-1]; -  spaces = spaces[..<1]; -  tokens[t] = 0; -  tokens -= ({ 0 }); -  } -  } -  else { -  spaces = ({}); -  } + #define strip_space() do { \ +  if (has_tag && !none_space) { \ +  while (sizeof(spaces)) { \ +  int t = spaces[-1]; \ +  spaces = spaces[..<1]; \ +  tokens[t] = 0; \ +  tokens -= ({ 0 }); \ +  } \ +  } \ +  else { \ +  spaces = ({}); \ +  } \ +  \ +  has_tag = false; \ +  none_space = false; \ +  } while (0);    -  has_tag = false; -  none_space = false; -  }; -  +     Re opening_tag_re, closing_tag_re, closing_curly_re;    -  void compile_tags(string|array(string) t) { -  if (stringp(t)) { -  t = _re_space->split(t); -  } +  // string|array(string) t + #define compile_tags(T) do { \ +  string|array(string) __t = (T); \ +  if (stringp(__t)) { \ +  __t = _re_space->split(__t); \ +  } \ +  \ +  if (!arrayp(__t) || sizeof(__t) != 2) { \ +  error("Invalid tags: %O\n", __t); \ +  } \ +  \ +  opening_tag_re = Re(escape_regexp(__t[0]) + "\\s*"); \ +  closing_tag_re = Re("\\s*" + escape_regexp(__t[1])); \ +  closing_curly_re = Re("\\s*" + escape_regexp("}" + __t[1])); \ +  } while (0);    -  if (!arrayp(t) || sizeof(t) != 2) { -  error("Invalid tags: %O\n", t); -  } -  -  opening_tag_re = Re(escape_regexp(t[0]) + "\\s*"); -  closing_tag_re = Re("\\s*" + escape_regexp(t[1])); -  closing_curly_re = Re("\\s*" + escape_regexp("}" + t[1])); -  }; -  +     compile_tags(_tags || tags);       Scanner scanner = Scanner(template);       int start, chr;    Token token, open_section;    string value;       while (!scanner->eos()) {    start = scanner->pos;
Roxen.git/server/etc/modules/Mustache.pike:615:    : nested_tokens;    break;       default:    collector += token;    break;    }    }       array(Token) my_toks = (array(object(Token))) nested_tokens; -  -  // TRACE(">>> nest_tokens leave\n"); -  -  destruct(collector); -  destruct(sections); -  destruct(nested_tokens); -  -  // TRACE("my_toks: %O\n", my_toks); -  +     return my_toks;   }         //! Represents a rendering context by wrapping a view object and   //! maintaining a reference to the parent context.   protected class Context   {    mixed view;    mapping cache;
Roxen.git/server/etc/modules/Mustache.pike:724: Inside #if defined(MUSTACHE_DEBUG)
     #ifdef MUSTACHE_DEBUG    protected void destroy()    {    TRACE("Context destroyed!\n");    }   #endif   }       - //! A Writer knows how to take a stream of tokens and render them to a - //! string, given a context. It also maintains a cache of templates to - //! avoid the need to parse the same template twice. - protected class Writer - { -  private mapping __cache = ([]); + //! @ignore + //! Template cache + private mapping __cache = set_weak_flag(([]), Pike.WEAK); + //! @endignore    -  //! Clears all cached templates in this writer. -  public void clear_cache() -  { -  __cache = ([]); -  } -  +    //! Parses and caches the given @[template] and returns the array of tokens   //! that is generated from the parse. -  public array(Token) parse(string template, void|array(string) tags) + protected array(Token) + parse_template(string|function template, void|array(string) tags)   {    array(Token) tokens = __cache[template];       if (!tokens) { -  tokens = __cache[template] = parse_template(template, tags); +  tokens = __cache[template] = low_parse_template(template, tags);    }       return tokens;   }      //! High-level method that is used to render the given @[template] with   //! the given @[view].   //!   //! The optional @[partials] argument may be an object/mapping that contains   //! the 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. -  public string render(string template, mixed view, + protected string render_template(string template, mixed view,    void|mixed partials)   { -  array(Token) tokens = parse(template); +  array(Token) tokens = parse_template(template);    Context ctx = objectp(view) && object_program(view) == Context    ? view    : Context(view);       string res = render_tokens(tokens, ctx, partials, template); -  // map(tokens, lambda (Token t) { -  // TRACE("Destroy: %O\n", t); -  // destruct(t); -  // }); -  tokens = 0; +     return res;    }          //! Low-level method that renders the given array of @[tokens] using    //! the given @[context] and @[partials].    //!    //! Note: The @[template] is only ever used to extract the portion    //! of the original template that was contained in a higher-order section.    //! If the template doesn't use higher-order sections, this argument may
Roxen.git/server/etc/modules/Mustache.pike:847:    function add = b->add;    mixed value = ctx->lookup(token[1]);       if (!value) {    return "";    }       // This function is used to render an arbitrary template    // in the current context by higher-order sections.    string subrender(string tmpl) { -  return render(tmpl, ctx, partials); +  return render_template(tmpl, ctx, partials);    };       if (multisetp(value)) {    value = (array)value;    }       if (arrayp(value)) {    int len = sizeof(value);       for (int j; j < len; ++j) {
Roxen.git/server/etc/modules/Mustache.pike:883:    }    }    else {    add(safe_string(render_tokens(token[4], ctx, partials, template)));    }       return b->get();    }       -  string render_inverted(Token token, Context ctx, mixed partials, + protected string render_inverted(Token token, Context ctx, mixed partials,    string template)   {    mixed value = ctx->lookup(token[1]);       if (falsy(value)) {    return render_tokens(token[4], ctx, partials, template);    }   }       -  string render_partial(Token token, Context ctx, mixed partials) + protected string render_partial(Token token, Context ctx, mixed partials)   {    if (!partials) {    return UNDEFINED;    }       mixed value = callablep(partials) ? partials(token[1]) : partials[token[1]];       if (value) { -  return render_tokens(parse(value), ctx, partials, value); +  return render_tokens(parse_template(value), ctx, partials, value);    }   }       -  string unescaped_value(Token token, Context ctx) + protected string unescaped_value(Token token, Context ctx)   {    mixed value = ctx->lookup(token[1]);       if (value) {    return (string) value;    }   }       -  string escaped_value(Token token, Context ctx) + protected string escaped_value(Token token, Context ctx)   {    mixed value = ctx->lookup(token[1]);       if (value != UNDEFINED) {    return escape_html((string)value);    }   }       -  string raw_value(Token token) + protected string raw_value(Token token)   {    return (string) token[1];   }    - #ifdef MUSTACHE_DEBUG -  protected void destroy() -  { -  TRACE("Writer destroyed!\n"); -  } - #endif - } -  +    protected mixed safe_string(mixed i)   {    if (!stringp(i)) {    return i;    }       catch {    i = utf8_to_string(i);    return i;    };       return i;   }    - protected Writer default_writer = Writer(); -  -  - //! Clears all cached templates in the default writer. - public void clear_cache() - { -  default_writer->clear_cache(); - } -  - //! Parses and caches the given template in the default writer and returns the - //! array of tokens it contains. Doing this ahead of time avoids the need to - //! parse templates on the fly as they are rendered. - public array(Token) parse(string template, void|array(string) tags) - { -  return default_writer->parse(template, tags); - } -  - //! Renders the @[template] with the given @[view] and @[partials] using the - //! default writer. - public string render(string template, mixed view, void|mixed partials) - { -  return default_writer->render(template, view, partials); - } -  +    //! Is the value @[v] a @tt{falsy@} value or not. It's faly if it's   //! @tt{0, UNDEFINED, "" or ({})@}   protected bool falsy(mixed v)   {    if (!v) return true;    if ((stringp(v) || arrayp(v)) && !sizeof(v)) {    return true;    }       return false;   }      #ifdef MUSTACHE_DEBUG   protected void destroy()   {    TRACE("Mustache destroyed!\n");   }   #endif