1
2
3  (function() {
4
5    Polymer('core-layout', {
6
7      isContainer: false,
8      /**
9       * Controls if the element lays out vertically or not.
10       *
11       * @attribute vertical
12       * @type boolean
13       * @default false
14       */
15      vertical: false,
16      /**
17       * Controls how the items are aligned in the main-axis direction. For
18       * example for a horizontal layout, this controls how each item is aligned
19       * horizontally.
20       *
21       * @attribute justify
22       * @type string start|center|end|between
23       * @default ''
24       */
25      justify: '',
26      /**
27       * Controls how the items are aligned in cross-axis direction. For
28       * example for a horizontal layout, this controls how each item is aligned
29       * vertically.
30       *
31       * @attribute align
32       * @type string start|center|end
33       * @default ''
34       */
35      align: '',
36      /**
37       * Controls whether or not the items layout in reverse order.
38       *
39       * @attribute reverse
40       * @type boolean
41       * @default false
42       */
43      reverse: false,
44      layoutPrefix: 'core-',
45
46      // NOTE: include template so that styles are loaded, but remove
47      // so that we can decide dynamically what part to include
48      registerCallback: function(polymerElement) {
49        var template = polymerElement.querySelector('template');
50        this.styles = template.content.querySelectorAll('style').array();
51        this.styles.forEach(function(s) {
52          s.removeAttribute('no-shim');
53        })
54      },
55
56      fetchTemplate: function() {
57        return null;
58      },
59
60      attached: function() {
61        this.installScopeStyle(this.styles[0]);
62        if (this.children.length) {
63          this.isContainer = true;
64        }
65        var container = this.isContainer ? this : this.parentNode;
66        // detect if laying out a shadowRoot host.
67        var forHost = container instanceof ShadowRoot;
68        if (forHost) {
69          this.installScopeStyle(this.styles[1], 'host');
70          container = container.host || document.body;
71        }
72        this.layoutContainer = container;
73      },
74
75      detached: function() {
76        this.layoutContainer = null;
77      },
78
79      layoutContainerChanged: function(old) {
80        this.style.display = this.layoutContainer === this ? null : 'none';
81        this.verticalChanged();
82        this.alignChanged();
83        this.justifyChanged();
84      },
85
86      setLayoutClass: function(prefix, old, newValue) {
87        if (this.layoutContainer) {
88          prefix = this.layoutPrefix + prefix;
89          if (old) {
90            this.layoutContainer.classList.remove(prefix + old);
91          }
92          if (newValue) {
93            this.layoutContainer.classList.add(prefix + newValue);
94          }
95        }
96      },
97
98      verticalChanged: function(old) {
99        old = old ? 'v' : 'h';
100        var vertical = this.vertical ? 'v' : 'h';
101        this.setLayoutClass('', old, vertical);
102      },
103
104      alignChanged: function(old) {
105        this.setLayoutClass('align-', old, this.align);
106      },
107
108      justifyChanged: function(old) {
109        this.setLayoutClass('justify-', old, this.justify);
110      },
111
112      reverseChanged: function(old) {
113        old = old ? 'reverse' : '';
114        var newValue = this.reverse ? 'reverse' : '';
115        this.setLayoutClass('', old, newValue);
116      }
117
118    });
119
120  })();
121  ;
122
123
124  (function() {
125
126    var SKIP_ID = 'meta';
127    var metaData = {}, metaArray = {};
128
129    Polymer('core-meta', {
130
131      /**
132       * The type of meta-data.  All meta-data with the same type with be
133       * stored together.
134       *
135       * @attribute type
136       * @type string
137       * @default 'default'
138       */
139      type: 'default',
140
141      alwaysPrepare: true,
142
143      ready: function() {
144        this.register(this.id);
145      },
146
147      get metaArray() {
148        var t = this.type;
149        if (!metaArray[t]) {
150          metaArray[t] = [];
151        }
152        return metaArray[t];
153      },
154
155      get metaData() {
156        var t = this.type;
157        if (!metaData[t]) {
158          metaData[t] = {};
159        }
160        return metaData[t];
161      },
162
163      register: function(id, old) {
164        if (id && id !== SKIP_ID) {
165          this.unregister(this, old);
166          this.metaData[id] = this;
167          this.metaArray.push(this);
168        }
169      },
170
171      unregister: function(meta, id) {
172        delete this.metaData[id || meta.id];
173        var i = this.metaArray.indexOf(meta);
174        if (i >= 0) {
175          this.metaArray.splice(i, 1);
176        }
177      },
178
179      /**
180       * Returns a list of all meta-data elements with the same type.
181       *
182       * @attribute list
183       * @type array
184       * @default []
185       */
186      get list() {
187        return this.metaArray;
188      },
189
190      /**
191       * Retrieves meta-data by ID.
192       *
193       * @method byId
194       * @param {String} id The ID of the meta-data to be returned.
195       * @returns Returns meta-data.
196       */
197      byId: function(id) {
198        return this.metaData[id];
199      }
200
201    });
202
203  })();
204
205;
206
207
208    Polymer('core-iconset', {
209
210      /**
211       * The URL of the iconset image.
212       *
213       * @attribute src
214       * @type string
215       * @default ''
216       */
217      src: '',
218
219      /**
220       * The width of the iconset image. This must only be specified if the
221       * icons are arranged into separate rows inside the image.
222       *
223       * @attribute width
224       * @type number
225       * @default 0
226       */
227      width: 0,
228
229      /**
230       * A space separated list of names corresponding to icons in the iconset
231       * image file. This list must be ordered the same as the icon images
232       * in the image file.
233       *
234       * @attribute icons
235       * @type string
236       * @default ''
237       */
238      icons: '',
239
240      /**
241       * The size of an individual icon. Note that icons must be square.
242       *
243       * @attribute iconSize
244       * @type number
245       * @default 24
246       */
247      iconSize: 24,
248
249      /**
250       * The horizontal offset of the icon images in the inconset src image.
251       * This is typically used if the image resource contains additional images
252       * beside those intended for the iconset.
253       *
254       * @attribute offsetX
255       * @type number
256       * @default 0
257       */
258      offsetX: 0,
259      /**
260       * The vertical offset of the icon images in the inconset src image.
261       * This is typically used if the image resource contains additional images
262       * beside those intended for the iconset.
263       *
264       * @attribute offsetY
265       * @type number
266       * @default 0
267       */
268      offsetY: 0,
269      type: 'iconset',
270
271      created: function() {
272        this.iconMap = {};
273        this.iconNames = [];
274        this.themes = {};
275      },
276
277      ready: function() {
278        // TODO(sorvell): ensure iconset's src is always relative to the main
279        // document
280        if (this.src && (this.ownerDocument !== document)) {
281          this.src = this.resolvePath(this.src, this.ownerDocument.baseURI);
282        }
283        this.super();
284        this.updateThemes();
285      },
286
287      iconsChanged: function() {
288        var ox = this.offsetX;
289        var oy = this.offsetY;
290        this.icons && this.icons.split(/\s+/g).forEach(function(name, i) {
291          this.iconNames.push(name);
292          this.iconMap[name] = {
293            offsetX: ox,
294            offsetY: oy
295          }
296          if (ox + this.iconSize < this.width) {
297            ox += this.iconSize;
298          } else {
299            ox = this.offsetX;
300            oy += this.iconSize;
301          }
302        }, this);
303      },
304
305      updateThemes: function() {
306        var ts = this.querySelectorAll('property[theme]');
307        ts && ts.array().forEach(function(t) {
308          this.themes[t.getAttribute('theme')] = {
309            offsetX: parseInt(t.getAttribute('offsetX')) || 0,
310            offsetY: parseInt(t.getAttribute('offsetY')) || 0
311          };
312        }, this);
313      },
314
315      // TODO(ffu): support retrived by index e.g. getOffset(10);
316      /**
317       * Returns an object containing `offsetX` and `offsetY` properties which
318       * specify the pixel locaion in the iconset's src file for the given
319       * `icon` and `theme`. It's uncommon to call this method. It is useful,
320       * for example, to manually position a css backgroundImage to the proper
321       * offset. It's more common to use the `applyIcon` method.
322       *
323       * @method getOffset
324       * @param {String|Number} icon The name of the icon or the index of the
325       * icon within in the icon image.
326       * @param {String} theme The name of the theme.
327       * @returns {Object} An object specifying the offset of the given icon
328       * within the icon resource file; `offsetX` is the horizontal offset and
329       * `offsetY` is the vertical offset. Both values are in pixel units.
330       */
331      getOffset: function(icon, theme) {
332        var i = this.iconMap[icon];
333        if (!i) {
334          var n = this.iconNames[Number(icon)];
335          i = this.iconMap[n];
336        }
337        var t = this.themes[theme];
338        if (i && t) {
339          return {
340            offsetX: i.offsetX + t.offsetX,
341            offsetY: i.offsetY + t.offsetY
342          }
343        }
344        return i;
345      },
346
347      /**
348       * Applies an icon to the given element as a css background image. This
349       * method does not size the element, and it's often necessary to set
350       * the element's height and width so that the background image is visible.
351       *
352       * @method applyIcon
353       * @param {Element} element The element to which the background is
354       * applied.
355       * @param {String|Number} icon The name or index of the icon to apply.
356       * @param {String} theme (optional) The name of the theme for the icon.
357       * @param {Number} scale (optional, defaults to 1) A scaling factor
358       * with which the icon can be magnified.
359       */
360      applyIcon: function(element, icon, scale) {
361         var offset = this.getOffset(icon);
362         scale = scale || 1;
363         if (element && offset) {
364           var style = element.style;
365           style.backgroundImage = 'url(' + this.src + ')';
366           style.backgroundPosition = (-offset.offsetX * scale + 'px') +
367              ' ' + (-offset.offsetY * scale + 'px');
368           style.backgroundSize = scale === 1 ? 'auto' :
369              this.width * scale + 'px';
370         }
371      }
372
373    });
374
375  ;
376
377
378    Polymer('core-iconset-svg', {
379
380
381      /**
382       * The size of an individual icon. Note that icons must be square.
383       *
384       * @attribute iconSize
385       * @type number
386       * @default 24
387       */
388      iconSize: 24,
389      type: 'iconset',
390
391      created: function() {
392        this._icons = {};
393      },
394
395      ready: function() {
396        this.super();
397        this.updateIcons();
398      },
399
400      iconById: function(id) {
401        return this._icons[id] || (this._icons[id] = this.querySelector('#' + id));
402      },
403
404      cloneIcon: function(id) {
405        var icon = this.iconById(id);
406        if (icon) {
407          var content = icon.cloneNode(true);
408          var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
409          svg.setAttribute('viewBox', '0 0 ' + this.iconSize + ' ' +
410              this.iconSize);
411          // NOTE(dfreedm): work around https://crbug.com/370136
412          svg.style.pointerEvents = 'none';
413          svg.appendChild(content);
414          return svg;
415        }
416      },
417
418      get iconNames() {
419        if (!this._iconNames) {
420          this._iconNames = this.findIconNames();
421        }
422        return this._iconNames;
423      },
424
425      findIconNames: function() {
426        var icons = this.querySelectorAll('[id]').array();
427        if (icons.length) {
428          return icons.map(function(n){ return n.id });
429        }
430      },
431
432      /**
433       * Applies an icon to the given element. The svg icon is added to the
434       * element's shadowRoot if one exists or directly to itself.
435       *
436       * @method applyIcon
437       * @param {Element} element The element to which the icon is
438       * applied.
439       * @param {String|Number} icon The name the icon to apply.
440       */
441      applyIcon: function(element, icon, scale) {
442        var root = element.shadowRoot || element;
443        // remove old
444        var old = root.querySelector('svg');
445        if (old) {
446          old.remove();
447        }
448        // install new
449        var svg = this.cloneIcon(icon);
450        if (!svg) {
451          return;
452        }
453        var size = scale * this.iconSize;
454        if (size) {
455          svg.style.height = svg.style.width = size + 'px';
456        } else {
457          svg.setAttribute('height', '100%');
458          svg.setAttribute('width', '100%');
459          svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
460        }
461        svg.style.display = 'block';
462        root.insertBefore(svg, root.firstElementChild);
463      },
464
465      /**
466       * Tell users of the iconset, that the set has loaded.
467       * This finds all elements matching the selector argument and calls
468       * the method argument on them.
469       * @method updateIcons
470       * @param selector {string} css selector to identify iconset users,
471       * defaults to '[icon]'
472       * @param method {string} method to call on found elements,
473       * defaults to 'updateIcon'
474       */
475      updateIcons: function(selector, method) {
476        selector = selector || '[icon]';
477        method = method || 'updateIcon';
478        var deep = window.ShadowDOMPolyfill ? '' : 'html /deep/ ';
479        var i$ = document.querySelectorAll(deep + selector);
480        for (var i=0, e; e=i$[i]; i++) {
481          if (e[method]) {
482            e[method].call(e);
483          }
484        }
485      }
486
487
488    });
489
490  ;
491
492(function() {
493
494  // mono-state
495  var meta;
496
497  Polymer('core-icon', {
498
499    /**
500     * The URL of an image for the icon. If the src property is specified,
501     * the icon property should not be.
502     *
503     * @attribute src
504     * @type string
505     * @default ''
506     */
507    src: '',
508
509    /**
510     * Specifies the size of the icon in pixel units.
511     *
512     * @attribute size
513     * @type string
514     * @default 24
515     */
516    size: 24,
517
518    /**
519     * Specifies the icon name or index in the set of icons available in
520     * the icon's icon set. If the icon property is specified,
521     * the src property should not be.
522     *
523     * @attribute icon
524     * @type string
525     * @default ''
526     */
527    icon: '',
528
529    observe: {
530      'size icon': 'updateIcon'
531    },
532
533    defaultIconset: 'icons',
534
535    ready: function() {
536      if (!meta) {
537        meta = document.createElement('core-iconset');
538      }
539      this.updateIcon();
540    },
541
542    srcChanged: function() {
543      this.style.backgroundImage = 'url(' + this.src + ')';
544      this.style.backgroundPosition = 'center';
545      this.style.backgroundSize = this.size + 'px ' + this.size + 'px';
546    },
547
548    getIconset: function(name) {
549      return meta.byId(name || this.defaultIconset);
550    },
551
552    updateIcon: function() {
553      if (this.size) {
554        this.style.width = this.style.height = this.size + 'px';
555      }
556      if (this.icon) {
557        var parts = String(this.icon).split(':');
558        var icon = parts.pop();
559        if (icon) {
560          var set = this.getIconset(parts.pop());
561          if (set) {
562            set.applyIcon(this, icon, this.size / set.iconSize);
563          }
564        }
565      }
566    }
567
568  });
569
570})();
571;
572
573
574    Polymer('core-icon-button', {
575
576      /**
577       * The URL of an image for the icon.  Should not use `icon` property
578       * if you are using this property.
579       *
580       * @attribute src
581       * @type string
582       * @default ''
583       */
584      src: '',
585
586      /**
587       * If true, border is placed around the button to indicate it's
588       * active state.
589       *
590       * @attribute active
591       * @type boolean
592       * @default false
593       */
594      active: false,
595
596      /**
597       * Specifies the icon name or index in the set of icons available in
598       * the icon set.  Should not use `src` property if you are using this
599       * property.
600       *
601       * @attribute icon
602       * @type string
603       * @default ''
604       */
605      icon: '',
606
607      activeChanged: function() {
608        this.classList.toggle('selected', this.active);
609      }
610
611    });
612
613  ;
614Polymer('core-toolbar');;
615
616
617  Polymer('core-header-panel', {
618
619    publish: {
620      /**
621       * Controls header and scrolling behavior. Options are
622       * `standard`, `seamed`, `waterfall`, `waterfall-tall`,
623       * `waterfall-medium-tall`, `scroll` and `cover`.
624       * Default is `standard`.
625       *
626       * `standard`: The header is a step above the panel. The header will consume the
627       * panel at the point of entry, preventing it from passing through to the
628       * opposite side.
629       *
630       * `seamed`: The header is presented as seamed with the panel.
631       *
632       * `waterfall`: Similar to standard mode, but header is initially presented as
633       * seamed with panel, but then separates to form the step.
634       *
635       * `waterfall-tall`: The header is initially taller (`tall` class is added to
636       * the header).  As the user scrolls, the header separates (forming an edge)
637       * while condensing (`tall` class is removed from the header).
638       *
639       * `scroll`: The header keeps its seam with the panel, and is pushed off screen.
640       *
641       * `cover`: The panel covers the whole `core-header-panel` including the
642       * header. This allows user to style the panel in such a way that the panel is
643       * partially covering the header.
644       *
645       *     <style>
646       *       core-header-panel[mode=cover]::shadow #mainContainer {
647       *         left: 80px;
648       *       }
649       *       .content {
650       *         margin: 60px 60px 60px 0;
651       *       }
652       *     </style>
653       *
654       *     <core-header-panel mode="cover">
655       *       <core-appbar class="tall">
656       *         <core-icon-button icon="menu"></core-icon-button>
657       *       </core-appbar>
658       *       <div class="content"></div>
659       *     </core-header-panel>
660       *
661       * @attribute mode
662       * @type string
663       * @default ''
664       */
665      mode: {value: '', reflect: true},
666
667      /**
668       * The class used in waterfall-tall mode.  Change this if the header
669       * accepts a different class for toggling height, e.g. "medium-tall"
670       *
671       * @attribute tallClass
672       * @type string
673       * @default 'tall'
674       */
675      tallClass: 'tall',
676
677      /**
678       * If true, the drop-shadow is always shown no matter what mode is set to.
679       *
680       * @attribute shadow
681       * @type boolean
682       * @default false
683       */
684      shadow: false,
685    },
686
687    domReady: function() {
688      this.async('scroll');
689    },
690
691    modeChanged: function() {
692      this.scroll();
693    },
694
695    get header() {
696      return this.$.headerContent.getDistributedNodes()[0];
697    },
698
699    scroll: function() {
700      var shadowMode = {'waterfall': 1, 'waterfall-tall': 1};
701      var noShadow = {'seamed': 1, 'cover': 1, 'scroll': 1};
702      var tallMode = {'waterfall-tall': 1};
703
704      var main = this.$.mainContainer;
705      var header = this.header;
706
707      var sTop = main.scrollTop;
708      var atTop = sTop === 0;
709
710      if (header) {
711        this.$.dropShadow.classList.toggle('hidden', !this.shadow &&
712            (atTop && shadowMode[this.mode] || noShadow[this.mode]));
713
714        if (tallMode[this.mode]) {
715          header.classList.toggle(this.tallClass, atTop);
716        }
717
718        header.classList.toggle('animate', tallMode[this.mode]);
719      }
720    }
721
722  });
723
724;
725/**
726 * marked - a markdown parser
727 * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
728 * https://github.com/chjj/marked
729 */
730
731;(function() {
732
733/**
734 * Block-Level Grammar
735 */
736
737var block = {
738  newline: /^\n+/,
739  code: /^( {4}[^\n]+\n*)+/,
740  fences: noop,
741  hr: /^( *[-*_]){3,} *(?:\n+|$)/,
742  heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
743  nptable: noop,
744  lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
745  blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
746  list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
747  html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
748  def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
749  table: noop,
750  paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
751  text: /^[^\n]+/
752};
753
754block.bullet = /(?:[*+-]|\d+\.)/;
755block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
756block.item = replace(block.item, 'gm')
757  (/bull/g, block.bullet)
758  ();
759
760block.list = replace(block.list)
761  (/bull/g, block.bullet)
762  ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
763  ('def', '\\n+(?=' + block.def.source + ')')
764  ();
765
766block.blockquote = replace(block.blockquote)
767  ('def', block.def)
768  ();
769
770block._tag = '(?!(?:'
771  + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
772  + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
773  + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
774
775block.html = replace(block.html)
776  ('comment', /<!--[\s\S]*?-->/)
777  ('closed', /<(tag)[\s\S]+?<\/\1>/)
778  ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
779  (/tag/g, block._tag)
780  ();
781
782block.paragraph = replace(block.paragraph)
783  ('hr', block.hr)
784  ('heading', block.heading)
785  ('lheading', block.lheading)
786  ('blockquote', block.blockquote)
787  ('tag', '<' + block._tag)
788  ('def', block.def)
789  ();
790
791/**
792 * Normal Block Grammar
793 */
794
795block.normal = merge({}, block);
796
797/**
798 * GFM Block Grammar
799 */
800
801block.gfm = merge({}, block.normal, {
802  fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
803  paragraph: /^/
804});
805
806block.gfm.paragraph = replace(block.paragraph)
807  ('(?!', '(?!'
808    + block.gfm.fences.source.replace('\\1', '\\2') + '|'
809    + block.list.source.replace('\\1', '\\3') + '|')
810  ();
811
812/**
813 * GFM + Tables Block Grammar
814 */
815
816block.tables = merge({}, block.gfm, {
817  nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
818  table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
819});
820
821/**
822 * Block Lexer
823 */
824
825function Lexer(options) {
826  this.tokens = [];
827  this.tokens.links = {};
828  this.options = options || marked.defaults;
829  this.rules = block.normal;
830
831  if (this.options.gfm) {
832    if (this.options.tables) {
833      this.rules = block.tables;
834    } else {
835      this.rules = block.gfm;
836    }
837  }
838}
839
840/**
841 * Expose Block Rules
842 */
843
844Lexer.rules = block;
845
846/**
847 * Static Lex Method
848 */
849
850Lexer.lex = function(src, options) {
851  var lexer = new Lexer(options);
852  return lexer.lex(src);
853};
854
855/**
856 * Preprocessing
857 */
858
859Lexer.prototype.lex = function(src) {
860  src = src
861    .replace(/\r\n|\r/g, '\n')
862    .replace(/\t/g, '    ')
863    .replace(/\u00a0/g, ' ')
864    .replace(/\u2424/g, '\n');
865
866  return this.token(src, true);
867};
868
869/**
870 * Lexing
871 */
872
873Lexer.prototype.token = function(src, top, bq) {
874  var src = src.replace(/^ +$/gm, '')
875    , next
876    , loose
877    , cap
878    , bull
879    , b
880    , item
881    , space
882    , i
883    , l;
884
885  while (src) {
886    // newline
887    if (cap = this.rules.newline.exec(src)) {
888      src = src.substring(cap[0].length);
889      if (cap[0].length > 1) {
890        this.tokens.push({
891          type: 'space'
892        });
893      }
894    }
895
896    // code
897    if (cap = this.rules.code.exec(src)) {
898      src = src.substring(cap[0].length);
899      cap = cap[0].replace(/^ {4}/gm, '');
900      this.tokens.push({
901        type: 'code',
902        text: !this.options.pedantic
903          ? cap.replace(/\n+$/, '')
904          : cap
905      });
906      continue;
907    }
908
909    // fences (gfm)
910    if (cap = this.rules.fences.exec(src)) {
911      src = src.substring(cap[0].length);
912      this.tokens.push({
913        type: 'code',
914        lang: cap[2],
915        text: cap[3]
916      });
917      continue;
918    }
919
920    // heading
921    if (cap = this.rules.heading.exec(src)) {
922      src = src.substring(cap[0].length);
923      this.tokens.push({
924        type: 'heading',
925        depth: cap[1].length,
926        text: cap[2]
927      });
928      continue;
929    }
930
931    // table no leading pipe (gfm)
932    if (top && (cap = this.rules.nptable.exec(src))) {
933      src = src.substring(cap[0].length);
934
935      item = {
936        type: 'table',
937        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
938        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
939        cells: cap[3].replace(/\n$/, '').split('\n')
940      };
941
942      for (i = 0; i < item.align.length; i++) {
943        if (/^ *-+: *$/.test(item.align[i])) {
944          item.align[i] = 'right';
945        } else if (/^ *:-+: *$/.test(item.align[i])) {
946          item.align[i] = 'center';
947        } else if (/^ *:-+ *$/.test(item.align[i])) {
948          item.align[i] = 'left';
949        } else {
950          item.align[i] = null;
951        }
952      }
953
954      for (i = 0; i < item.cells.length; i++) {
955        item.cells[i] = item.cells[i].split(/ *\| */);
956      }
957
958      this.tokens.push(item);
959
960      continue;
961    }
962
963    // lheading
964    if (cap = this.rules.lheading.exec(src)) {
965      src = src.substring(cap[0].length);
966      this.tokens.push({
967        type: 'heading',
968        depth: cap[2] === '=' ? 1 : 2,
969        text: cap[1]
970      });
971      continue;
972    }
973
974    // hr
975    if (cap = this.rules.hr.exec(src)) {
976      src = src.substring(cap[0].length);
977      this.tokens.push({
978        type: 'hr'
979      });
980      continue;
981    }
982
983    // blockquote
984    if (cap = this.rules.blockquote.exec(src)) {
985      src = src.substring(cap[0].length);
986
987      this.tokens.push({
988        type: 'blockquote_start'
989      });
990
991      cap = cap[0].replace(/^ *> ?/gm, '');
992
993      // Pass `top` to keep the current
994      // "toplevel" state. This is exactly
995      // how markdown.pl works.
996      this.token(cap, top, true);
997
998      this.tokens.push({
999        type: 'blockquote_end'
1000      });
1001
1002      continue;
1003    }
1004
1005    // list
1006    if (cap = this.rules.list.exec(src)) {
1007      src = src.substring(cap[0].length);
1008      bull = cap[2];
1009
1010      this.tokens.push({
1011        type: 'list_start',
1012        ordered: bull.length > 1
1013      });
1014
1015      // Get each top-level item.
1016      cap = cap[0].match(this.rules.item);
1017
1018      next = false;
1019      l = cap.length;
1020      i = 0;
1021
1022      for (; i < l; i++) {
1023        item = cap[i];
1024
1025        // Remove the list item's bullet
1026        // so it is seen as the next token.
1027        space = item.length;
1028        item = item.replace(/^ *([*+-]|\d+\.) +/, '');
1029
1030        // Outdent whatever the
1031        // list item contains. Hacky.
1032        if (~item.indexOf('\n ')) {
1033          space -= item.length;
1034          item = !this.options.pedantic
1035            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
1036            : item.replace(/^ {1,4}/gm, '');
1037        }
1038
1039        // Determine whether the next list item belongs here.
1040        // Backpedal if it does not belong in this list.
1041        if (this.options.smartLists && i !== l - 1) {
1042          b = block.bullet.exec(cap[i + 1])[0];
1043          if (bull !== b && !(bull.length > 1 && b.length > 1)) {
1044            src = cap.slice(i + 1).join('\n') + src;
1045            i = l - 1;
1046          }
1047        }
1048
1049        // Determine whether item is loose or not.
1050        // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
1051        // for discount behavior.
1052        loose = next || /\n\n(?!\s*$)/.test(item);
1053        if (i !== l - 1) {
1054          next = item.charAt(item.length - 1) === '\n';
1055          if (!loose) loose = next;
1056        }
1057
1058        this.tokens.push({
1059          type: loose
1060            ? 'loose_item_start'
1061            : 'list_item_start'
1062        });
1063
1064        // Recurse.
1065        this.token(item, false, bq);
1066
1067        this.tokens.push({
1068          type: 'list_item_end'
1069        });
1070      }
1071
1072      this.tokens.push({
1073        type: 'list_end'
1074      });
1075
1076      continue;
1077    }
1078
1079    // html
1080    if (cap = this.rules.html.exec(src)) {
1081      src = src.substring(cap[0].length);
1082      this.tokens.push({
1083        type: this.options.sanitize
1084          ? 'paragraph'
1085          : 'html',
1086        pre: cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style',
1087        text: cap[0]
1088      });
1089      continue;
1090    }
1091
1092    // def
1093    if ((!bq && top) && (cap = this.rules.def.exec(src))) {
1094      src = src.substring(cap[0].length);
1095      this.tokens.links[cap[1].toLowerCase()] = {
1096        href: cap[2],
1097        title: cap[3]
1098      };
1099      continue;
1100    }
1101
1102    // table (gfm)
1103    if (top && (cap = this.rules.table.exec(src))) {
1104      src = src.substring(cap[0].length);
1105
1106      item = {
1107        type: 'table',
1108        header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
1109        align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
1110        cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
1111      };
1112
1113      for (i = 0; i < item.align.length; i++) {
1114        if (/^ *-+: *$/.test(item.align[i])) {
1115          item.align[i] = 'right';
1116        } else if (/^ *:-+: *$/.test(item.align[i])) {
1117          item.align[i] = 'center';
1118        } else if (/^ *:-+ *$/.test(item.align[i])) {
1119          item.align[i] = 'left';
1120        } else {
1121          item.align[i] = null;
1122        }
1123      }
1124
1125      for (i = 0; i < item.cells.length; i++) {
1126        item.cells[i] = item.cells[i]
1127          .replace(/^ *\| *| *\| *$/g, '')
1128          .split(/ *\| */);
1129      }
1130
1131      this.tokens.push(item);
1132
1133      continue;
1134    }
1135
1136    // top-level paragraph
1137    if (top && (cap = this.rules.paragraph.exec(src))) {
1138      src = src.substring(cap[0].length);
1139      this.tokens.push({
1140        type: 'paragraph',
1141        text: cap[1].charAt(cap[1].length - 1) === '\n'
1142          ? cap[1].slice(0, -1)
1143          : cap[1]
1144      });
1145      continue;
1146    }
1147
1148    // text
1149    if (cap = this.rules.text.exec(src)) {
1150      // Top-level should never reach here.
1151      src = src.substring(cap[0].length);
1152      this.tokens.push({
1153        type: 'text',
1154        text: cap[0]
1155      });
1156      continue;
1157    }
1158
1159    if (src) {
1160      throw new
1161        Error('Infinite loop on byte: ' + src.charCodeAt(0));
1162    }
1163  }
1164
1165  return this.tokens;
1166};
1167
1168/**
1169 * Inline-Level Grammar
1170 */
1171
1172var inline = {
1173  escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
1174  autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
1175  url: noop,
1176  tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
1177  link: /^!?\[(inside)\]\(href\)/,
1178  reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
1179  nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
1180  strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
1181  em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
1182  code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
1183  br: /^ {2,}\n(?!\s*$)/,
1184  del: noop,
1185  text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
1186};
1187
1188inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
1189inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
1190
1191inline.link = replace(inline.link)
1192  ('inside', inline._inside)
1193  ('href', inline._href)
1194  ();
1195
1196inline.reflink = replace(inline.reflink)
1197  ('inside', inline._inside)
1198  ();
1199
1200/**
1201 * Normal Inline Grammar
1202 */
1203
1204inline.normal = merge({}, inline);
1205
1206/**
1207 * Pedantic Inline Grammar
1208 */
1209
1210inline.pedantic = merge({}, inline.normal, {
1211  strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
1212  em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
1213});
1214
1215/**
1216 * GFM Inline Grammar
1217 */
1218
1219inline.gfm = merge({}, inline.normal, {
1220  escape: replace(inline.escape)('])', '~|])')(),
1221  url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
1222  del: /^~~(?=\S)([\s\S]*?\S)~~/,
1223  text: replace(inline.text)
1224    (']|', '~]|')
1225    ('|', '|https?://|')
1226    ()
1227});
1228
1229/**
1230 * GFM + Line Breaks Inline Grammar
1231 */
1232
1233inline.breaks = merge({}, inline.gfm, {
1234  br: replace(inline.br)('{2,}', '*')(),
1235  text: replace(inline.gfm.text)('{2,}', '*')()
1236});
1237
1238/**
1239 * Inline Lexer & Compiler
1240 */
1241
1242function InlineLexer(links, options) {
1243  this.options = options || marked.defaults;
1244  this.links = links;
1245  this.rules = inline.normal;
1246  this.renderer = this.options.renderer || new Renderer;
1247  this.renderer.options = this.options;
1248
1249  if (!this.links) {
1250    throw new
1251      Error('Tokens array requires a `links` property.');
1252  }
1253
1254  if (this.options.gfm) {
1255    if (this.options.breaks) {
1256      this.rules = inline.breaks;
1257    } else {
1258      this.rules = inline.gfm;
1259    }
1260  } else if (this.options.pedantic) {
1261    this.rules = inline.pedantic;
1262  }
1263}
1264
1265/**
1266 * Expose Inline Rules
1267 */
1268
1269InlineLexer.rules = inline;
1270
1271/**
1272 * Static Lexing/Compiling Method
1273 */
1274
1275InlineLexer.output = function(src, links, options) {
1276  var inline = new InlineLexer(links, options);
1277  return inline.output(src);
1278};
1279
1280/**
1281 * Lexing/Compiling
1282 */
1283
1284InlineLexer.prototype.output = function(src) {
1285  var out = ''
1286    , link
1287    , text
1288    , href
1289    , cap;
1290
1291  while (src) {
1292    // escape
1293    if (cap = this.rules.escape.exec(src)) {
1294      src = src.substring(cap[0].length);
1295      out += cap[1];
1296      continue;
1297    }
1298
1299    // autolink
1300    if (cap = this.rules.autolink.exec(src)) {
1301      src = src.substring(cap[0].length);
1302      if (cap[2] === '@') {
1303        text = cap[1].charAt(6) === ':'
1304          ? this.mangle(cap[1].substring(7))
1305          : this.mangle(cap[1]);
1306        href = this.mangle('mailto:') + text;
1307      } else {
1308        text = escape(cap[1]);
1309        href = text;
1310      }
1311      out += this.renderer.link(href, null, text);
1312      continue;
1313    }
1314
1315    // url (gfm)
1316    if (!this.inLink && (cap = this.rules.url.exec(src))) {
1317      src = src.substring(cap[0].length);
1318      text = escape(cap[1]);
1319      href = text;
1320      out += this.renderer.link(href, null, text);
1321      continue;
1322    }
1323
1324    // tag
1325    if (cap = this.rules.tag.exec(src)) {
1326      if (!this.inLink && /^<a /i.test(cap[0])) {
1327        this.inLink = true;
1328      } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
1329        this.inLink = false;
1330      }
1331      src = src.substring(cap[0].length);
1332      out += this.options.sanitize
1333        ? escape(cap[0])
1334        : cap[0];
1335      continue;
1336    }
1337
1338    // link
1339    if (cap = this.rules.link.exec(src)) {
1340      src = src.substring(cap[0].length);
1341      this.inLink = true;
1342      out += this.outputLink(cap, {
1343        href: cap[2],
1344        title: cap[3]
1345      });
1346      this.inLink = false;
1347      continue;
1348    }
1349
1350    // reflink, nolink
1351    if ((cap = this.rules.reflink.exec(src))
1352        || (cap = this.rules.nolink.exec(src))) {
1353      src = src.substring(cap[0].length);
1354      link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
1355      link = this.links[link.toLowerCase()];
1356      if (!link || !link.href) {
1357        out += cap[0].charAt(0);
1358        src = cap[0].substring(1) + src;
1359        continue;
1360      }
1361      this.inLink = true;
1362      out += this.outputLink(cap, link);
1363      this.inLink = false;
1364      continue;
1365    }
1366
1367    // strong
1368    if (cap = this.rules.strong.exec(src)) {
1369      src = src.substring(cap[0].length);
1370      out += this.renderer.strong(this.output(cap[2] || cap[1]));
1371      continue;
1372    }
1373
1374    // em
1375    if (cap = this.rules.em.exec(src)) {
1376      src = src.substring(cap[0].length);
1377      out += this.renderer.em(this.output(cap[2] || cap[1]));
1378      continue;
1379    }
1380
1381    // code
1382    if (cap = this.rules.code.exec(src)) {
1383      src = src.substring(cap[0].length);
1384      out += this.renderer.codespan(escape(cap[2], true));
1385      continue;
1386    }
1387
1388    // br
1389    if (cap = this.rules.br.exec(src)) {
1390      src = src.substring(cap[0].length);
1391      out += this.renderer.br();
1392      continue;
1393    }
1394
1395    // del (gfm)
1396    if (cap = this.rules.del.exec(src)) {
1397      src = src.substring(cap[0].length);
1398      out += this.renderer.del(this.output(cap[1]));
1399      continue;
1400    }
1401
1402    // text
1403    if (cap = this.rules.text.exec(src)) {
1404      src = src.substring(cap[0].length);
1405      out += escape(this.smartypants(cap[0]));
1406      continue;
1407    }
1408
1409    if (src) {
1410      throw new
1411        Error('Infinite loop on byte: ' + src.charCodeAt(0));
1412    }
1413  }
1414
1415  return out;
1416};
1417
1418/**
1419 * Compile Link
1420 */
1421
1422InlineLexer.prototype.outputLink = function(cap, link) {
1423  var href = escape(link.href)
1424    , title = link.title ? escape(link.title) : null;
1425
1426  return cap[0].charAt(0) !== '!'
1427    ? this.renderer.link(href, title, this.output(cap[1]))
1428    : this.renderer.image(href, title, escape(cap[1]));
1429};
1430
1431/**
1432 * Smartypants Transformations
1433 */
1434
1435InlineLexer.prototype.smartypants = function(text) {
1436  if (!this.options.smartypants) return text;
1437  return text
1438    // em-dashes
1439    .replace(/--/g, '\u2014')
1440    // opening singles
1441    .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
1442    // closing singles & apostrophes
1443    .replace(/'/g, '\u2019')
1444    // opening doubles
1445    .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
1446    // closing doubles
1447    .replace(/"/g, '\u201d')
1448    // ellipses
1449    .replace(/\.{3}/g, '\u2026');
1450};
1451
1452/**
1453 * Mangle Links
1454 */
1455
1456InlineLexer.prototype.mangle = function(text) {
1457  var out = ''
1458    , l = text.length
1459    , i = 0
1460    , ch;
1461
1462  for (; i < l; i++) {
1463    ch = text.charCodeAt(i);
1464    if (Math.random() > 0.5) {
1465      ch = 'x' + ch.toString(16);
1466    }
1467    out += '&#' + ch + ';';
1468  }
1469
1470  return out;
1471};
1472
1473/**
1474 * Renderer
1475 */
1476
1477function Renderer(options) {
1478  this.options = options || {};
1479}
1480
1481Renderer.prototype.code = function(code, lang, escaped) {
1482  if (this.options.highlight) {
1483    var out = this.options.highlight(code, lang);
1484    if (out != null && out !== code) {
1485      escaped = true;
1486      code = out;
1487    }
1488  }
1489
1490  if (!lang) {
1491    return '<pre><code>'
1492      + (escaped ? code : escape(code, true))
1493      + '\n</code></pre>';
1494  }
1495
1496  return '<pre><code class="'
1497    + this.options.langPrefix
1498    + escape(lang, true)
1499    + '">'
1500    + (escaped ? code : escape(code, true))
1501    + '\n</code></pre>\n';
1502};
1503
1504Renderer.prototype.blockquote = function(quote) {
1505  return '<blockquote>\n' + quote + '</blockquote>\n';
1506};
1507
1508Renderer.prototype.html = function(html) {
1509  return html;
1510};
1511
1512Renderer.prototype.heading = function(text, level, raw) {
1513  return '<h'
1514    + level
1515    + ' id="'
1516    + this.options.headerPrefix
1517    + raw.toLowerCase().replace(/[^\w]+/g, '-')
1518    + '">'
1519    + text
1520    + '</h'
1521    + level
1522    + '>\n';
1523};
1524
1525Renderer.prototype.hr = function() {
1526  return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
1527};
1528
1529Renderer.prototype.list = function(body, ordered) {
1530  var type = ordered ? 'ol' : 'ul';
1531  return '<' + type + '>\n' + body + '</' + type + '>\n';
1532};
1533
1534Renderer.prototype.listitem = function(text) {
1535  return '<li>' + text + '</li>\n';
1536};
1537
1538Renderer.prototype.paragraph = function(text) {
1539  return '<p>' + text + '</p>\n';
1540};
1541
1542Renderer.prototype.table = function(header, body) {
1543  return '<table>\n'
1544    + '<thead>\n'
1545    + header
1546    + '</thead>\n'
1547    + '<tbody>\n'
1548    + body
1549    + '</tbody>\n'
1550    + '</table>\n';
1551};
1552
1553Renderer.prototype.tablerow = function(content) {
1554  return '<tr>\n' + content + '</tr>\n';
1555};
1556
1557Renderer.prototype.tablecell = function(content, flags) {
1558  var type = flags.header ? 'th' : 'td';
1559  var tag = flags.align
1560    ? '<' + type + ' style="text-align:' + flags.align + '">'
1561    : '<' + type + '>';
1562  return tag + content + '</' + type + '>\n';
1563};
1564
1565// span level renderer
1566Renderer.prototype.strong = function(text) {
1567  return '<strong>' + text + '</strong>';
1568};
1569
1570Renderer.prototype.em = function(text) {
1571  return '<em>' + text + '</em>';
1572};
1573
1574Renderer.prototype.codespan = function(text) {
1575  return '<code>' + text + '</code>';
1576};
1577
1578Renderer.prototype.br = function() {
1579  return this.options.xhtml ? '<br/>' : '<br>';
1580};
1581
1582Renderer.prototype.del = function(text) {
1583  return '<del>' + text + '</del>';
1584};
1585
1586Renderer.prototype.link = function(href, title, text) {
1587  if (this.options.sanitize) {
1588    try {
1589      var prot = decodeURIComponent(unescape(href))
1590        .replace(/[^\w:]/g, '')
1591        .toLowerCase();
1592    } catch (e) {
1593      return '';
1594    }
1595    if (prot.indexOf('javascript:') === 0) {
1596      return '';
1597    }
1598  }
1599  var out = '<a href="' + href + '"';
1600  if (title) {
1601    out += ' title="' + title + '"';
1602  }
1603  out += '>' + text + '</a>';
1604  return out;
1605};
1606
1607Renderer.prototype.image = function(href, title, text) {
1608  var out = '<img src="' + href + '" alt="' + text + '"';
1609  if (title) {
1610    out += ' title="' + title + '"';
1611  }
1612  out += this.options.xhtml ? '/>' : '>';
1613  return out;
1614};
1615
1616/**
1617 * Parsing & Compiling
1618 */
1619
1620function Parser(options) {
1621  this.tokens = [];
1622  this.token = null;
1623  this.options = options || marked.defaults;
1624  this.options.renderer = this.options.renderer || new Renderer;
1625  this.renderer = this.options.renderer;
1626  this.renderer.options = this.options;
1627}
1628
1629/**
1630 * Static Parse Method
1631 */
1632
1633Parser.parse = function(src, options, renderer) {
1634  var parser = new Parser(options, renderer);
1635  return parser.parse(src);
1636};
1637
1638/**
1639 * Parse Loop
1640 */
1641
1642Parser.prototype.parse = function(src) {
1643  this.inline = new InlineLexer(src.links, this.options, this.renderer);
1644  this.tokens = src.reverse();
1645
1646  var out = '';
1647  while (this.next()) {
1648    out += this.tok();
1649  }
1650
1651  return out;
1652};
1653
1654/**
1655 * Next Token
1656 */
1657
1658Parser.prototype.next = function() {
1659  return this.token = this.tokens.pop();
1660};
1661
1662/**
1663 * Preview Next Token
1664 */
1665
1666Parser.prototype.peek = function() {
1667  return this.tokens[this.tokens.length - 1] || 0;
1668};
1669
1670/**
1671 * Parse Text Tokens
1672 */
1673
1674Parser.prototype.parseText = function() {
1675  var body = this.token.text;
1676
1677  while (this.peek().type === 'text') {
1678    body += '\n' + this.next().text;
1679  }
1680
1681  return this.inline.output(body);
1682};
1683
1684/**
1685 * Parse Current Token
1686 */
1687
1688Parser.prototype.tok = function() {
1689  switch (this.token.type) {
1690    case 'space': {
1691      return '';
1692    }
1693    case 'hr': {
1694      return this.renderer.hr();
1695    }
1696    case 'heading': {
1697      return this.renderer.heading(
1698        this.inline.output(this.token.text),
1699        this.token.depth,
1700        this.token.text);
1701    }
1702    case 'code': {
1703      return this.renderer.code(this.token.text,
1704        this.token.lang,
1705        this.token.escaped);
1706    }
1707    case 'table': {
1708      var header = ''
1709        , body = ''
1710        , i
1711        , row
1712        , cell
1713        , flags
1714        , j;
1715
1716      // header
1717      cell = '';
1718      for (i = 0; i < this.token.header.length; i++) {
1719        flags = { header: true, align: this.token.align[i] };
1720        cell += this.renderer.tablecell(
1721          this.inline.output(this.token.header[i]),
1722          { header: true, align: this.token.align[i] }
1723        );
1724      }
1725      header += this.renderer.tablerow(cell);
1726
1727      for (i = 0; i < this.token.cells.length; i++) {
1728        row = this.token.cells[i];
1729
1730        cell = '';
1731        for (j = 0; j < row.length; j++) {
1732          cell += this.renderer.tablecell(
1733            this.inline.output(row[j]),
1734            { header: false, align: this.token.align[j] }
1735          );
1736        }
1737
1738        body += this.renderer.tablerow(cell);
1739      }
1740      return this.renderer.table(header, body);
1741    }
1742    case 'blockquote_start': {
1743      var body = '';
1744
1745      while (this.next().type !== 'blockquote_end') {
1746        body += this.tok();
1747      }
1748
1749      return this.renderer.blockquote(body);
1750    }
1751    case 'list_start': {
1752      var body = ''
1753        , ordered = this.token.ordered;
1754
1755      while (this.next().type !== 'list_end') {
1756        body += this.tok();
1757      }
1758
1759      return this.renderer.list(body, ordered);
1760    }
1761    case 'list_item_start': {
1762      var body = '';
1763
1764      while (this.next().type !== 'list_item_end') {
1765        body += this.token.type === 'text'
1766          ? this.parseText()
1767          : this.tok();
1768      }
1769
1770      return this.renderer.listitem(body);
1771    }
1772    case 'loose_item_start': {
1773      var body = '';
1774
1775      while (this.next().type !== 'list_item_end') {
1776        body += this.tok();
1777      }
1778
1779      return this.renderer.listitem(body);
1780    }
1781    case 'html': {
1782      var html = !this.token.pre && !this.options.pedantic
1783        ? this.inline.output(this.token.text)
1784        : this.token.text;
1785      return this.renderer.html(html);
1786    }
1787    case 'paragraph': {
1788      return this.renderer.paragraph(this.inline.output(this.token.text));
1789    }
1790    case 'text': {
1791      return this.renderer.paragraph(this.parseText());
1792    }
1793  }
1794};
1795
1796/**
1797 * Helpers
1798 */
1799
1800function escape(html, encode) {
1801  return html
1802    .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
1803    .replace(/</g, '&lt;')
1804    .replace(/>/g, '&gt;')
1805    .replace(/"/g, '&quot;')
1806    .replace(/'/g, '&#39;');
1807}
1808
1809function unescape(html) {
1810  return html.replace(/&([#\w]+);/g, function(_, n) {
1811    n = n.toLowerCase();
1812    if (n === 'colon') return ':';
1813    if (n.charAt(0) === '#') {
1814      return n.charAt(1) === 'x'
1815        ? String.fromCharCode(parseInt(n.substring(2), 16))
1816        : String.fromCharCode(+n.substring(1));
1817    }
1818    return '';
1819  });
1820}
1821
1822function replace(regex, opt) {
1823  regex = regex.source;
1824  opt = opt || '';
1825  return function self(name, val) {
1826    if (!name) return new RegExp(regex, opt);
1827    val = val.source || val;
1828    val = val.replace(/(^|[^\[])\^/g, '$1');
1829    regex = regex.replace(name, val);
1830    return self;
1831  };
1832}
1833
1834function noop() {}
1835noop.exec = noop;
1836
1837function merge(obj) {
1838  var i = 1
1839    , target
1840    , key;
1841
1842  for (; i < arguments.length; i++) {
1843    target = arguments[i];
1844    for (key in target) {
1845      if (Object.prototype.hasOwnProperty.call(target, key)) {
1846        obj[key] = target[key];
1847      }
1848    }
1849  }
1850
1851  return obj;
1852}
1853
1854
1855/**
1856 * Marked
1857 */
1858
1859function marked(src, opt, callback) {
1860  if (callback || typeof opt === 'function') {
1861    if (!callback) {
1862      callback = opt;
1863      opt = null;
1864    }
1865
1866    opt = merge({}, marked.defaults, opt || {});
1867
1868    var highlight = opt.highlight
1869      , tokens
1870      , pending
1871      , i = 0;
1872
1873    try {
1874      tokens = Lexer.lex(src, opt)
1875    } catch (e) {
1876      return callback(e);
1877    }
1878
1879    pending = tokens.length;
1880
1881    var done = function() {
1882      var out, err;
1883
1884      try {
1885        out = Parser.parse(tokens, opt);
1886      } catch (e) {
1887        err = e;
1888      }
1889
1890      opt.highlight = highlight;
1891
1892      return err
1893        ? callback(err)
1894        : callback(null, out);
1895    };
1896
1897    if (!highlight || highlight.length < 3) {
1898      return done();
1899    }
1900
1901    delete opt.highlight;
1902
1903    if (!pending) return done();
1904
1905    for (; i < tokens.length; i++) {
1906      (function(token) {
1907        if (token.type !== 'code') {
1908          return --pending || done();
1909        }
1910        return highlight(token.text, token.lang, function(err, code) {
1911          if (code == null || code === token.text) {
1912            return --pending || done();
1913          }
1914          token.text = code;
1915          token.escaped = true;
1916          --pending || done();
1917        });
1918      })(tokens[i]);
1919    }
1920
1921    return;
1922  }
1923  try {
1924    if (opt) opt = merge({}, marked.defaults, opt);
1925    return Parser.parse(Lexer.lex(src, opt), opt);
1926  } catch (e) {
1927    e.message += '\nPlease report this to https://github.com/chjj/marked.';
1928    if ((opt || marked.defaults).silent) {
1929      return '<p>An error occured:</p><pre>'
1930        + escape(e.message + '', true)
1931        + '</pre>';
1932    }
1933    throw e;
1934  }
1935}
1936
1937/**
1938 * Options
1939 */
1940
1941marked.options =
1942marked.setOptions = function(opt) {
1943  merge(marked.defaults, opt);
1944  return marked;
1945};
1946
1947marked.defaults = {
1948  gfm: true,
1949  tables: true,
1950  breaks: false,
1951  pedantic: false,
1952  sanitize: false,
1953  smartLists: false,
1954  silent: false,
1955  highlight: null,
1956  langPrefix: 'lang-',
1957  smartypants: false,
1958  headerPrefix: '',
1959  renderer: new Renderer,
1960  xhtml: false
1961};
1962
1963/**
1964 * Expose
1965 */
1966
1967marked.Parser = Parser;
1968marked.parser = Parser.parse;
1969
1970marked.Renderer = Renderer;
1971
1972marked.Lexer = Lexer;
1973marked.lexer = Lexer.lex;
1974
1975marked.InlineLexer = InlineLexer;
1976marked.inlineLexer = InlineLexer.output;
1977
1978marked.parse = marked;
1979
1980if (typeof exports === 'object') {
1981  module.exports = marked;
1982} else if (typeof define === 'function' && define.amd) {
1983  define(function() { return marked; });
1984} else {
1985  this.marked = marked;
1986}
1987
1988}).call(function() {
1989  return this || (typeof window !== 'undefined' ? window : global);
1990}());
1991;
1992
1993
1994  Polymer('marked-element', {
1995
1996    text: '',
1997
1998    attached: function() {
1999      marked.setOptions({
2000        highlight: this.highlight.bind(this)
2001      });
2002      if (!this.text) {
2003        this.text = this.innerHTML;
2004      }
2005    },
2006
2007    textChanged: function () {
2008      this.innerHTML = marked(this.text);
2009    },
2010
2011    highlight: function(code, lang) {
2012      var event = this.fire('marked-js-highlight', {code: code, lang: lang});
2013      return event.detail.code || code;
2014    }
2015
2016  });
2017
2018;
2019// Copyright (C) 2006 Google Inc.
2020//
2021// Licensed under the Apache License, Version 2.0 (the "License");
2022// you may not use this file except in compliance with the License.
2023// You may obtain a copy of the License at
2024//
2025//      http://www.apache.org/licenses/LICENSE-2.0
2026//
2027// Unless required by applicable law or agreed to in writing, software
2028// distributed under the License is distributed on an "AS IS" BASIS,
2029// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2030// See the License for the specific language governing permissions and
2031// limitations under the License.
2032
2033
2034/**
2035 * @fileoverview
2036 * some functions for browser-side pretty printing of code contained in html.
2037 *
2038 * <p>
2039 * For a fairly comprehensive set of languages see the
2040 * <a href="http://google-code-prettify.googlecode.com/svn/trunk/README.html#langs">README</a>
2041 * file that came with this source.  At a minimum, the lexer should work on a
2042 * number of languages including C and friends, Java, Python, Bash, SQL, HTML,
2043 * XML, CSS, Javascript, and Makefiles.  It works passably on Ruby, PHP and Awk
2044 * and a subset of Perl, but, because of commenting conventions, doesn't work on
2045 * Smalltalk, Lisp-like, or CAML-like languages without an explicit lang class.
2046 * <p>
2047 * Usage: <ol>
2048 * <li> include this source file in an html page via
2049 *   {@code <script type="text/javascript" src="/path/to/prettify.js"><\/script>}
2050 * <li> define style rules.  See the example page for examples.
2051 * <li> mark the {@code <pre>} and {@code <code>} tags in your source with
2052 *    {@code class=prettyprint.}
2053 *    You can also use the (html deprecated) {@code <xmp>} tag, but the pretty
2054 *    printer needs to do more substantial DOM manipulations to support that, so
2055 *    some css styles may not be preserved.
2056 * </ol>
2057 * That's it.  I wanted to keep the API as simple as possible, so there's no
2058 * need to specify which language the code is in, but if you wish, you can add
2059 * another class to the {@code <pre>} or {@code <code>} element to specify the
2060 * language, as in {@code <pre class="prettyprint lang-java">}.  Any class that
2061 * starts with "lang-" followed by a file extension, specifies the file type.
2062 * See the "lang-*.js" files in this directory for code that implements
2063 * per-language file handlers.
2064 * <p>
2065 * Change log:<br>
2066 * cbeust, 2006/08/22
2067 * <blockquote>
2068 *   Java annotations (start with "@") are now captured as literals ("lit")
2069 * </blockquote>
2070 * @requires console
2071 */
2072
2073// JSLint declarations
2074/*global console, document, navigator, setTimeout, window, define */
2075
2076/**
2077 * Split {@code prettyPrint} into multiple timeouts so as not to interfere with
2078 * UI events.
2079 * If set to {@code false}, {@code prettyPrint()} is synchronous.
2080 */
2081window['PR_SHOULD_USE_CONTINUATION'] = true;
2082
2083/**
2084 * Find all the {@code <pre>} and {@code <code>} tags in the DOM with
2085 * {@code class=prettyprint} and prettify them.
2086 *
2087 * @param {Function?} opt_whenDone if specified, called when the last entry
2088 *     has been finished.
2089 */
2090var prettyPrintOne;
2091/**
2092 * Pretty print a chunk of code.
2093 *
2094 * @param {string} sourceCodeHtml code as html
2095 * @return {string} code as html, but prettier
2096 */
2097var prettyPrint;
2098
2099
2100(function () {
2101  var win = window;
2102  // Keyword lists for various languages.
2103  // We use things that coerce to strings to make them compact when minified
2104  // and to defeat aggressive optimizers that fold large string constants.
2105  var FLOW_CONTROL_KEYWORDS = ["break,continue,do,else,for,if,return,while"];
2106  var C_KEYWORDS = [FLOW_CONTROL_KEYWORDS,"auto,case,char,const,default," +
2107      "double,enum,extern,float,goto,int,long,register,short,signed,sizeof," +
2108      "static,struct,switch,typedef,union,unsigned,void,volatile"];
2109  var COMMON_KEYWORDS = [C_KEYWORDS,"catch,class,delete,false,import," +
2110      "new,operator,private,protected,public,this,throw,true,try,typeof"];
2111  var CPP_KEYWORDS = [COMMON_KEYWORDS,"alignof,align_union,asm,axiom,bool," +
2112      "concept,concept_map,const_cast,constexpr,decltype," +
2113      "dynamic_cast,explicit,export,friend,inline,late_check," +
2114      "mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast," +
2115      "template,typeid,typename,using,virtual,where"];
2116  var JAVA_KEYWORDS = [COMMON_KEYWORDS,
2117      "abstract,boolean,byte,extends,final,finally,implements,import," +
2118      "instanceof,null,native,package,strictfp,super,synchronized,throws," +
2119      "transient"];
2120  var CSHARP_KEYWORDS = [JAVA_KEYWORDS,
2121      "as,base,by,checked,decimal,delegate,descending,dynamic,event," +
2122      "fixed,foreach,from,group,implicit,in,interface,internal,into,is,let," +
2123      "lock,object,out,override,orderby,params,partial,readonly,ref,sbyte," +
2124      "sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort," +
2125      "var,virtual,where"];
2126  var COFFEE_KEYWORDS = "all,and,by,catch,class,else,extends,false,finally," +
2127      "for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then," +
2128      "throw,true,try,unless,until,when,while,yes";
2129  var JSCRIPT_KEYWORDS = [COMMON_KEYWORDS,
2130      "debugger,eval,export,function,get,null,set,undefined,var,with," +
2131      "Infinity,NaN"];
2132  var PERL_KEYWORDS = "caller,delete,die,do,dump,elsif,eval,exit,foreach,for," +
2133      "goto,if,import,last,local,my,next,no,our,print,package,redo,require," +
2134      "sub,undef,unless,until,use,wantarray,while,BEGIN,END";
2135  var PYTHON_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "and,as,assert,class,def,del," +
2136      "elif,except,exec,finally,from,global,import,in,is,lambda," +
2137      "nonlocal,not,or,pass,print,raise,try,with,yield," +
2138      "False,True,None"];
2139  var RUBY_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "alias,and,begin,case,class," +
2140      "def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo," +
2141      "rescue,retry,self,super,then,true,undef,unless,until,when,yield," +
2142      "BEGIN,END"];
2143  var SH_KEYWORDS = [FLOW_CONTROL_KEYWORDS, "case,done,elif,esac,eval,fi," +
2144      "function,in,local,set,then,until"];
2145  var ALL_KEYWORDS = [
2146      CPP_KEYWORDS, CSHARP_KEYWORDS, JSCRIPT_KEYWORDS, PERL_KEYWORDS +
2147      PYTHON_KEYWORDS, RUBY_KEYWORDS, SH_KEYWORDS];
2148  var C_TYPES = /^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/;
2149
2150  // token style names.  correspond to css classes
2151  /**
2152   * token style for a string literal
2153   * @const
2154   */
2155  var PR_STRING = 'str';
2156  /**
2157   * token style for a keyword
2158   * @const
2159   */
2160  var PR_KEYWORD = 'kwd';
2161  /**
2162   * token style for a comment
2163   * @const
2164   */
2165  var PR_COMMENT = 'com';
2166  /**
2167   * token style for a type
2168   * @const
2169   */
2170  var PR_TYPE = 'typ';
2171  /**
2172   * token style for a literal value.  e.g. 1, null, true.
2173   * @const
2174   */
2175  var PR_LITERAL = 'lit';
2176  /**
2177   * token style for a punctuation string.
2178   * @const
2179   */
2180  var PR_PUNCTUATION = 'pun';
2181  /**
2182   * token style for plain text.
2183   * @const
2184   */
2185  var PR_PLAIN = 'pln';
2186
2187  /**
2188   * token style for an sgml tag.
2189   * @const
2190   */
2191  var PR_TAG = 'tag';
2192  /**
2193   * token style for a markup declaration such as a DOCTYPE.
2194   * @const
2195   */
2196  var PR_DECLARATION = 'dec';
2197  /**
2198   * token style for embedded source.
2199   * @const
2200   */
2201  var PR_SOURCE = 'src';
2202  /**
2203   * token style for an sgml attribute name.
2204   * @const
2205   */
2206  var PR_ATTRIB_NAME = 'atn';
2207  /**
2208   * token style for an sgml attribute value.
2209   * @const
2210   */
2211  var PR_ATTRIB_VALUE = 'atv';
2212
2213  /**
2214   * A class that indicates a section of markup that is not code, e.g. to allow
2215   * embedding of line numbers within code listings.
2216   * @const
2217   */
2218  var PR_NOCODE = 'nocode';
2219
2220
2221
2222/**
2223 * A set of tokens that can precede a regular expression literal in
2224 * javascript
2225 * http://web.archive.org/web/20070717142515/http://www.mozilla.org/js/language/js20/rationale/syntax.html
2226 * has the full list, but I've removed ones that might be problematic when
2227 * seen in languages that don't support regular expression literals.
2228 *
2229 * <p>Specifically, I've removed any keywords that can't precede a regexp
2230 * literal in a syntactically legal javascript program, and I've removed the
2231 * "in" keyword since it's not a keyword in many languages, and might be used
2232 * as a count of inches.
2233 *
2234 * <p>The link above does not accurately describe EcmaScript rules since
2235 * it fails to distinguish between (a=++/b/i) and (a++/b/i) but it works
2236 * very well in practice.
2237 *
2238 * @private
2239 * @const
2240 */
2241var REGEXP_PRECEDER_PATTERN = '(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<<?=?|>>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*';
2242
2243// CAVEAT: this does not properly handle the case where a regular
2244// expression immediately follows another since a regular expression may
2245// have flags for case-sensitivity and the like.  Having regexp tokens
2246// adjacent is not valid in any language I'm aware of, so I'm punting.
2247// TODO: maybe style special characters inside a regexp as punctuation.
2248
2249
2250  /**
2251   * Given a group of {@link RegExp}s, returns a {@code RegExp} that globally
2252   * matches the union of the sets of strings matched by the input RegExp.
2253   * Since it matches globally, if the input strings have a start-of-input
2254   * anchor (/^.../), it is ignored for the purposes of unioning.
2255   * @param {Array.<RegExp>} regexs non multiline, non-global regexs.
2256   * @return {RegExp} a global regex.
2257   */
2258  function combinePrefixPatterns(regexs) {
2259    var capturedGroupIndex = 0;
2260
2261    var needToFoldCase = false;
2262    var ignoreCase = false;
2263    for (var i = 0, n = regexs.length; i < n; ++i) {
2264      var regex = regexs[i];
2265      if (regex.ignoreCase) {
2266        ignoreCase = true;
2267      } else if (/[a-z]/i.test(regex.source.replace(
2268                     /\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi, ''))) {
2269        needToFoldCase = true;
2270        ignoreCase = false;
2271        break;
2272      }
2273    }
2274
2275    var escapeCharToCodeUnit = {
2276      'b': 8,
2277      't': 9,
2278      'n': 0xa,
2279      'v': 0xb,
2280      'f': 0xc,
2281      'r': 0xd
2282    };
2283
2284    function decodeEscape(charsetPart) {
2285      var cc0 = charsetPart.charCodeAt(0);
2286      if (cc0 !== 92 /* \\ */) {
2287        return cc0;
2288      }
2289      var c1 = charsetPart.charAt(1);
2290      cc0 = escapeCharToCodeUnit[c1];
2291      if (cc0) {
2292        return cc0;
2293      } else if ('0' <= c1 && c1 <= '7') {
2294        return parseInt(charsetPart.substring(1), 8);
2295      } else if (c1 === 'u' || c1 === 'x') {
2296        return parseInt(charsetPart.substring(2), 16);
2297      } else {
2298        return charsetPart.charCodeAt(1);
2299      }
2300    }
2301
2302    function encodeEscape(charCode) {
2303      if (charCode < 0x20) {
2304        return (charCode < 0x10 ? '\\x0' : '\\x') + charCode.toString(16);
2305      }
2306      var ch = String.fromCharCode(charCode);
2307      return (ch === '\\' || ch === '-' || ch === ']' || ch === '^')
2308          ? "\\" + ch : ch;
2309    }
2310
2311    function caseFoldCharset(charSet) {
2312      var charsetParts = charSet.substring(1, charSet.length - 1).match(
2313          new RegExp(
2314              '\\\\u[0-9A-Fa-f]{4}'
2315              + '|\\\\x[0-9A-Fa-f]{2}'
2316              + '|\\\\[0-3][0-7]{0,2}'
2317              + '|\\\\[0-7]{1,2}'
2318              + '|\\\\[\\s\\S]'
2319              + '|-'
2320              + '|[^-\\\\]',
2321              'g'));
2322      var ranges = [];
2323      var inverse = charsetParts[0] === '^';
2324
2325      var out = ['['];
2326      if (inverse) { out.push('^'); }
2327
2328      for (var i = inverse ? 1 : 0, n = charsetParts.length; i < n; ++i) {
2329        var p = charsetParts[i];
2330        if (/\\[bdsw]/i.test(p)) {  // Don't muck with named groups.
2331          out.push(p);
2332        } else {
2333          var start = decodeEscape(p);
2334          var end;
2335          if (i + 2 < n && '-' === charsetParts[i + 1]) {
2336            end = decodeEscape(charsetParts[i + 2]);
2337            i += 2;
2338          } else {
2339            end = start;
2340          }
2341          ranges.push([start, end]);
2342          // If the range might intersect letters, then expand it.
2343          // This case handling is too simplistic.
2344          // It does not deal with non-latin case folding.
2345          // It works for latin source code identifiers though.
2346          if (!(end < 65 || start > 122)) {
2347            if (!(end < 65 || start > 90)) {
2348              ranges.push([Math.max(65, start) | 32, Math.min(end, 90) | 32]);
2349            }
2350            if (!(end < 97 || start > 122)) {
2351              ranges.push([Math.max(97, start) & ~32, Math.min(end, 122) & ~32]);
2352            }
2353          }
2354        }
2355      }
2356
2357      // [[1, 10], [3, 4], [8, 12], [14, 14], [16, 16], [17, 17]]
2358      // -> [[1, 12], [14, 14], [16, 17]]
2359      ranges.sort(function (a, b) { return (a[0] - b[0]) || (b[1]  - a[1]); });
2360      var consolidatedRanges = [];
2361      var lastRange = [];
2362      for (var i = 0; i < ranges.length; ++i) {
2363        var range = ranges[i];
2364        if (range[0] <= lastRange[1] + 1) {
2365          lastRange[1] = Math.max(lastRange[1], range[1]);
2366        } else {
2367          consolidatedRanges.push(lastRange = range);
2368        }
2369      }
2370
2371      for (var i = 0; i < consolidatedRanges.length; ++i) {
2372        var range = consolidatedRanges[i];
2373        out.push(encodeEscape(range[0]));
2374        if (range[1] > range[0]) {
2375          if (range[1] + 1 > range[0]) { out.push('-'); }
2376          out.push(encodeEscape(range[1]));
2377        }
2378      }
2379      out.push(']');
2380      return out.join('');
2381    }
2382
2383    function allowAnywhereFoldCaseAndRenumberGroups(regex) {
2384      // Split into character sets, escape sequences, punctuation strings
2385      // like ('(', '(?:', ')', '^'), and runs of characters that do not
2386      // include any of the above.
2387      var parts = regex.source.match(
2388          new RegExp(
2389              '(?:'
2390              + '\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]'  // a character set
2391              + '|\\\\u[A-Fa-f0-9]{4}'  // a unicode escape
2392              + '|\\\\x[A-Fa-f0-9]{2}'  // a hex escape
2393              + '|\\\\[0-9]+'  // a back-reference or octal escape
2394              + '|\\\\[^ux0-9]'  // other escape sequence
2395              + '|\\(\\?[:!=]'  // start of a non-capturing group
2396              + '|[\\(\\)\\^]'  // start/end of a group, or line start
2397              + '|[^\\x5B\\x5C\\(\\)\\^]+'  // run of other characters
2398              + ')',
2399              'g'));
2400      var n = parts.length;
2401
2402      // Maps captured group numbers to the number they will occupy in
2403      // the output or to -1 if that has not been determined, or to
2404      // undefined if they need not be capturing in the output.
2405      var capturedGroups = [];
2406
2407      // Walk over and identify back references to build the capturedGroups
2408      // mapping.
2409      for (var i = 0, groupIndex = 0; i < n; ++i) {
2410        var p = parts[i];
2411        if (p === '(') {
2412          // groups are 1-indexed, so max group index is count of '('
2413          ++groupIndex;
2414        } else if ('\\' === p.charAt(0)) {
2415          var decimalValue = +p.substring(1);
2416          if (decimalValue) {
2417            if (decimalValue <= groupIndex) {
2418              capturedGroups[decimalValue] = -1;
2419            } else {
2420              // Replace with an unambiguous escape sequence so that
2421              // an octal escape sequence does not turn into a backreference
2422              // to a capturing group from an earlier regex.
2423              parts[i] = encodeEscape(decimalValue);
2424            }
2425          }
2426        }
2427      }
2428
2429      // Renumber groups and reduce capturing groups to non-capturing groups
2430      // where possible.
2431      for (var i = 1; i < capturedGroups.length; ++i) {
2432        if (-1 === capturedGroups[i]) {
2433          capturedGroups[i] = ++capturedGroupIndex;
2434        }
2435      }
2436      for (var i = 0, groupIndex = 0; i < n; ++i) {
2437        var p = parts[i];
2438        if (p === '(') {
2439          ++groupIndex;
2440          if (!capturedGroups[groupIndex]) {
2441            parts[i] = '(?:';
2442          }
2443        } else if ('\\' === p.charAt(0)) {
2444          var decimalValue = +p.substring(1);
2445          if (decimalValue && decimalValue <= groupIndex) {
2446            parts[i] = '\\' + capturedGroups[decimalValue];
2447          }
2448        }
2449      }
2450
2451      // Remove any prefix anchors so that the output will match anywhere.
2452      // ^^ really does mean an anchored match though.
2453      for (var i = 0; i < n; ++i) {
2454        if ('^' === parts[i] && '^' !== parts[i + 1]) { parts[i] = ''; }
2455      }
2456
2457      // Expand letters to groups to handle mixing of case-sensitive and
2458      // case-insensitive patterns if necessary.
2459      if (regex.ignoreCase && needToFoldCase) {
2460        for (var i = 0; i < n; ++i) {
2461          var p = parts[i];
2462          var ch0 = p.charAt(0);
2463          if (p.length >= 2 && ch0 === '[') {
2464            parts[i] = caseFoldCharset(p);
2465          } else if (ch0 !== '\\') {
2466            // TODO: handle letters in numeric escapes.
2467            parts[i] = p.replace(
2468                /[a-zA-Z]/g,
2469                function (ch) {
2470                  var cc = ch.charCodeAt(0);
2471                  return '[' + String.fromCharCode(cc & ~32, cc | 32) + ']';
2472                });
2473          }
2474        }
2475      }
2476
2477      return parts.join('');
2478    }
2479
2480    var rewritten = [];
2481    for (var i = 0, n = regexs.length; i < n; ++i) {
2482      var regex = regexs[i];
2483      if (regex.global || regex.multiline) { throw new Error('' + regex); }
2484      rewritten.push(
2485          '(?:' + allowAnywhereFoldCaseAndRenumberGroups(regex) + ')');
2486    }
2487
2488    return new RegExp(rewritten.join('|'), ignoreCase ? 'gi' : 'g');
2489  }
2490
2491
2492  /**
2493   * Split markup into a string of source code and an array mapping ranges in
2494   * that string to the text nodes in which they appear.
2495   *
2496   * <p>
2497   * The HTML DOM structure:</p>
2498   * <pre>
2499   * (Element   "p"
2500   *   (Element "b"
2501   *     (Text  "print "))       ; #1
2502   *   (Text    "'Hello '")      ; #2
2503   *   (Element "br")            ; #3
2504   *   (Text    "  + 'World';")) ; #4
2505   * </pre>
2506   * <p>
2507   * corresponds to the HTML
2508   * {@code <p><b>print </b>'Hello '<br>  + 'World';</p>}.</p>
2509   *
2510   * <p>
2511   * It will produce the output:</p>
2512   * <pre>
2513   * {
2514   *   sourceCode: "print 'Hello '\n  + 'World';",
2515   *   //                     1          2
2516   *   //           012345678901234 5678901234567
2517   *   spans: [0, #1, 6, #2, 14, #3, 15, #4]
2518   * }
2519   * </pre>
2520   * <p>
2521   * where #1 is a reference to the {@code "print "} text node above, and so
2522   * on for the other text nodes.
2523   * </p>
2524   *
2525   * <p>
2526   * The {@code} spans array is an array of pairs.  Even elements are the start
2527   * indices of substrings, and odd elements are the text nodes (or BR elements)
2528   * that contain the text for those substrings.
2529   * Substrings continue until the next index or the end of the source.
2530   * </p>
2531   *
2532   * @param {Node} node an HTML DOM subtree containing source-code.
2533   * @param {boolean} isPreformatted true if white-space in text nodes should
2534   *    be considered significant.
2535   * @return {Object} source code and the text nodes in which they occur.
2536   */
2537  function extractSourceSpans(node, isPreformatted) {
2538    var nocode = /(?:^|\s)nocode(?:\s|$)/;
2539
2540    var chunks = [];
2541    var length = 0;
2542    var spans = [];
2543    var k = 0;
2544
2545    function walk(node) {
2546      switch (node.nodeType) {
2547        case 1:  // Element
2548          if (nocode.test(node.className)) { return; }
2549          for (var child = node.firstChild; child; child = child.nextSibling) {
2550            walk(child);
2551          }
2552          var nodeName = node.nodeName.toLowerCase();
2553          if ('br' === nodeName || 'li' === nodeName) {
2554            chunks[k] = '\n';
2555            spans[k << 1] = length++;
2556            spans[(k++ << 1) | 1] = node;
2557          }
2558          break;
2559        case 3: case 4:  // Text
2560          var text = node.nodeValue;
2561          if (text.length) {
2562            if (!isPreformatted) {
2563              text = text.replace(/[ \t\r\n]+/g, ' ');
2564            } else {
2565              text = text.replace(/\r\n?/g, '\n');  // Normalize newlines.
2566            }
2567            // TODO: handle tabs here?
2568            chunks[k] = text;
2569            spans[k << 1] = length;
2570            length += text.length;
2571            spans[(k++ << 1) | 1] = node;
2572          }
2573          break;
2574      }
2575    }
2576
2577    walk(node);
2578
2579    return {
2580      sourceCode: chunks.join('').replace(/\n$/, ''),
2581      spans: spans
2582    };
2583  }
2584
2585
2586  /**
2587   * Apply the given language handler to sourceCode and add the resulting
2588   * decorations to out.
2589   * @param {number} basePos the index of sourceCode within the chunk of source
2590   *    whose decorations are already present on out.
2591   */
2592  function appendDecorations(basePos, sourceCode, langHandler, out) {
2593    if (!sourceCode) { return; }
2594    var job = {
2595      sourceCode: sourceCode,
2596      basePos: basePos
2597    };
2598    langHandler(job);
2599    out.push.apply(out, job.decorations);
2600  }
2601
2602  var notWs = /\S/;
2603
2604  /**
2605   * Given an element, if it contains only one child element and any text nodes
2606   * it contains contain only space characters, return the sole child element.
2607   * Otherwise returns undefined.
2608   * <p>
2609   * This is meant to return the CODE element in {@code <pre><code ...>} when
2610   * there is a single child element that contains all the non-space textual
2611   * content, but not to return anything where there are multiple child elements
2612   * as in {@code <pre><code>...</code><code>...</code></pre>} or when there
2613   * is textual content.
2614   */
2615  function childContentWrapper(element) {
2616    var wrapper = undefined;
2617    for (var c = element.firstChild; c; c = c.nextSibling) {
2618      var type = c.nodeType;
2619      wrapper = (type === 1)  // Element Node
2620          ? (wrapper ? element : c)
2621          : (type === 3)  // Text Node
2622          ? (notWs.test(c.nodeValue) ? element : wrapper)
2623          : wrapper;
2624    }
2625    return wrapper === element ? undefined : wrapper;
2626  }
2627
2628  /** Given triples of [style, pattern, context] returns a lexing function,
2629    * The lexing function interprets the patterns to find token boundaries and
2630    * returns a decoration list of the form
2631    * [index_0, style_0, index_1, style_1, ..., index_n, style_n]
2632    * where index_n is an index into the sourceCode, and style_n is a style
2633    * constant like PR_PLAIN.  index_n-1 <= index_n, and style_n-1 applies to
2634    * all characters in sourceCode[index_n-1:index_n].
2635    *
2636    * The stylePatterns is a list whose elements have the form
2637    * [style : string, pattern : RegExp, DEPRECATED, shortcut : string].
2638    *
2639    * Style is a style constant like PR_PLAIN, or can be a string of the
2640    * form 'lang-FOO', where FOO is a language extension describing the
2641    * language of the portion of the token in $1 after pattern executes.
2642    * E.g., if style is 'lang-lisp', and group 1 contains the text
2643    * '(hello (world))', then that portion of the token will be passed to the
2644    * registered lisp handler for formatting.
2645    * The text before and after group 1 will be restyled using this decorator
2646    * so decorators should take care that this doesn't result in infinite
2647    * recursion.  For example, the HTML lexer rule for SCRIPT elements looks
2648    * something like ['lang-js', /<[s]cript>(.+?)<\/script>/].  This may match
2649    * '<script>foo()<\/script>', which would cause the current decorator to
2650    * be called with '<script>' which would not match the same rule since
2651    * group 1 must not be empty, so it would be instead styled as PR_TAG by
2652    * the generic tag rule.  The handler registered for the 'js' extension would
2653    * then be called with 'foo()', and finally, the current decorator would
2654    * be called with '<\/script>' which would not match the original rule and
2655    * so the generic tag rule would identify it as a tag.
2656    *
2657    * Pattern must only match prefixes, and if it matches a prefix, then that
2658    * match is considered a token with the same style.
2659    *
2660    * Context is applied to the last non-whitespace, non-comment token
2661    * recognized.
2662    *
2663    * Shortcut is an optional string of characters, any of which, if the first
2664    * character, gurantee that this pattern and only this pattern matches.
2665    *
2666    * @param {Array} shortcutStylePatterns patterns that always start with
2667    *   a known character.  Must have a shortcut string.
2668    * @param {Array} fallthroughStylePatterns patterns that will be tried in
2669    *   order if the shortcut ones fail.  May have shortcuts.
2670    *
2671    * @return {function (Object)} a
2672    *   function that takes source code and returns a list of decorations.
2673    */
2674  function createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns) {
2675    var shortcuts = {};
2676    var tokenizer;
2677    (function () {
2678      var allPatterns = shortcutStylePatterns.concat(fallthroughStylePatterns);
2679      var allRegexs = [];
2680      var regexKeys = {};
2681      for (var i = 0, n = allPatterns.length; i < n; ++i) {
2682        var patternParts = allPatterns[i];
2683        var shortcutChars = patternParts[3];
2684        if (shortcutChars) {
2685          for (var c = shortcutChars.length; --c >= 0;) {
2686            shortcuts[shortcutChars.charAt(c)] = patternParts;
2687          }
2688        }
2689        var regex = patternParts[1];
2690        var k = '' + regex;
2691        if (!regexKeys.hasOwnProperty(k)) {
2692          allRegexs.push(regex);
2693          regexKeys[k] = null;
2694        }
2695      }
2696      allRegexs.push(/[\0-\uffff]/);
2697      tokenizer = combinePrefixPatterns(allRegexs);
2698    })();
2699
2700    var nPatterns = fallthroughStylePatterns.length;
2701
2702    /**
2703     * Lexes job.sourceCode and produces an output array job.decorations of
2704     * style classes preceded by the position at which they start in
2705     * job.sourceCode in order.
2706     *
2707     * @param {Object} job an object like <pre>{
2708     *    sourceCode: {string} sourceText plain text,
2709     *    basePos: {int} position of job.sourceCode in the larger chunk of
2710     *        sourceCode.
2711     * }</pre>
2712     */
2713    var decorate = function (job) {
2714      var sourceCode = job.sourceCode, basePos = job.basePos;
2715      /** Even entries are positions in source in ascending order.  Odd enties
2716        * are style markers (e.g., PR_COMMENT) that run from that position until
2717        * the end.
2718        * @type {Array.<number|string>}
2719        */
2720      var decorations = [basePos, PR_PLAIN];
2721      var pos = 0;  // index into sourceCode
2722      var tokens = sourceCode.match(tokenizer) || [];
2723      var styleCache = {};
2724
2725      for (var ti = 0, nTokens = tokens.length; ti < nTokens; ++ti) {
2726        var token = tokens[ti];
2727        var style = styleCache[token];
2728        var match = void 0;
2729
2730        var isEmbedded;
2731        if (typeof style === 'string') {
2732          isEmbedded = false;
2733        } else {
2734          var patternParts = shortcuts[token.charAt(0)];
2735          if (patternParts) {
2736            match = token.match(patternParts[1]);
2737            style = patternParts[0];
2738          } else {
2739            for (var i = 0; i < nPatterns; ++i) {
2740              patternParts = fallthroughStylePatterns[i];
2741              match = token.match(patternParts[1]);
2742              if (match) {
2743                style = patternParts[0];
2744                break;
2745              }
2746            }
2747
2748            if (!match) {  // make sure that we make progress
2749              style = PR_PLAIN;
2750            }
2751          }
2752
2753          isEmbedded = style.length >= 5 && 'lang-' === style.substring(0, 5);
2754          if (isEmbedded && !(match && typeof match[1] === 'string')) {
2755            isEmbedded = false;
2756            style = PR_SOURCE;
2757          }
2758
2759          if (!isEmbedded) { styleCache[token] = style; }
2760        }
2761
2762        var tokenStart = pos;
2763        pos += token.length;
2764
2765        if (!isEmbedded) {
2766          decorations.push(basePos + tokenStart, style);
2767        } else {  // Treat group 1 as an embedded block of source code.
2768          var embeddedSource = match[1];
2769          var embeddedSourceStart = token.indexOf(embeddedSource);
2770          var embeddedSourceEnd = embeddedSourceStart + embeddedSource.length;
2771          if (match[2]) {
2772            // If embeddedSource can be blank, then it would match at the
2773            // beginning which would cause us to infinitely recurse on the
2774            // entire token, so we catch the right context in match[2].
2775            embeddedSourceEnd = token.length - match[2].length;
2776            embeddedSourceStart = embeddedSourceEnd - embeddedSource.length;
2777          }
2778          var lang = style.substring(5);
2779          // Decorate the left of the embedded source
2780          appendDecorations(
2781              basePos + tokenStart,
2782              token.substring(0, embeddedSourceStart),
2783              decorate, decorations);
2784          // Decorate the embedded source
2785          appendDecorations(
2786              basePos + tokenStart + embeddedSourceStart,
2787              embeddedSource,
2788              langHandlerForExtension(lang, embeddedSource),
2789              decorations);
2790          // Decorate the right of the embedded section
2791          appendDecorations(
2792              basePos + tokenStart + embeddedSourceEnd,
2793              token.substring(embeddedSourceEnd),
2794              decorate, decorations);
2795        }
2796      }
2797      job.decorations = decorations;
2798    };
2799    return decorate;
2800  }
2801
2802  /** returns a function that produces a list of decorations from source text.
2803    *
2804    * This code treats ", ', and ` as string delimiters, and \ as a string
2805    * escape.  It does not recognize perl's qq() style strings.
2806    * It has no special handling for double delimiter escapes as in basic, or
2807    * the tripled delimiters used in python, but should work on those regardless
2808    * although in those cases a single string literal may be broken up into
2809    * multiple adjacent string literals.
2810    *
2811    * It recognizes C, C++, and shell style comments.
2812    *
2813    * @param {Object} options a set of optional parameters.
2814    * @return {function (Object)} a function that examines the source code
2815    *     in the input job and builds the decoration list.
2816    */
2817  function sourceDecorator(options) {
2818    var shortcutStylePatterns = [], fallthroughStylePatterns = [];
2819    if (options['tripleQuotedStrings']) {
2820      // '''multi-line-string''', 'single-line-string', and double-quoted
2821      shortcutStylePatterns.push(
2822          [PR_STRING,  /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
2823           null, '\'"']);
2824    } else if (options['multiLineStrings']) {
2825      // 'multi-line-string', "multi-line-string"
2826      shortcutStylePatterns.push(
2827          [PR_STRING,  /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
2828           null, '\'"`']);
2829    } else {
2830      // 'single-line-string', "single-line-string"
2831      shortcutStylePatterns.push(
2832          [PR_STRING,
2833           /^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
2834           null, '"\'']);
2835    }
2836    if (options['verbatimStrings']) {
2837      // verbatim-string-literal production from the C# grammar.  See issue 93.
2838      fallthroughStylePatterns.push(
2839          [PR_STRING, /^@\"(?:[^\"]|\"\")*(?:\"|$)/, null]);
2840    }
2841    var hc = options['hashComments'];
2842    if (hc) {
2843      if (options['cStyleComments']) {
2844        if (hc > 1) {  // multiline hash comments
2845          shortcutStylePatterns.push(
2846              [PR_COMMENT, /^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/, null, '#']);
2847        } else {
2848          // Stop C preprocessor declarations at an unclosed open comment
2849          shortcutStylePatterns.push(
2850              [PR_COMMENT, /^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\r\n]*)/,
2851               null, '#']);
2852        }
2853        // #include <stdio.h>
2854        fallthroughStylePatterns.push(
2855            [PR_STRING,
2856             /^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,
2857             null]);
2858      } else {
2859        shortcutStylePatterns.push([PR_COMMENT, /^#[^\r\n]*/, null, '#']);
2860      }
2861    }
2862    if (options['cStyleComments']) {
2863      fallthroughStylePatterns.push([PR_COMMENT, /^\/\/[^\r\n]*/, null]);
2864      fallthroughStylePatterns.push(
2865          [PR_COMMENT, /^\/\*[\s\S]*?(?:\*\/|$)/, null]);
2866    }
2867    if (options['regexLiterals']) {
2868      /**
2869       * @const
2870       */
2871      var REGEX_LITERAL = (
2872          // A regular expression literal starts with a slash that is
2873          // not followed by * or / so that it is not confused with
2874          // comments.
2875          '/(?=[^/*])'
2876          // and then contains any number of raw characters,
2877          + '(?:[^/\\x5B\\x5C]'
2878          // escape sequences (\x5C),
2879          +    '|\\x5C[\\s\\S]'
2880          // or non-nesting character sets (\x5B\x5D);
2881          +    '|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+'
2882          // finally closed by a /.
2883          + '/');
2884      fallthroughStylePatterns.push(
2885          ['lang-regex',
2886           new RegExp('^' + REGEXP_PRECEDER_PATTERN + '(' + REGEX_LITERAL + ')')
2887           ]);
2888    }
2889
2890    var types = options['types'];
2891    if (types) {
2892      fallthroughStylePatterns.push([PR_TYPE, types]);
2893    }
2894
2895    var keywords = ("" + options['keywords']).replace(/^ | $/g, '');
2896    if (keywords.length) {
2897      fallthroughStylePatterns.push(
2898          [PR_KEYWORD,
2899           new RegExp('^(?:' + keywords.replace(/[\s,]+/g, '|') + ')\\b'),
2900           null]);
2901    }
2902
2903    shortcutStylePatterns.push([PR_PLAIN,       /^\s+/, null, ' \r\n\t\xA0']);
2904
2905    var punctuation =
2906      // The Bash man page says
2907
2908      // A word is a sequence of characters considered as a single
2909      // unit by GRUB. Words are separated by metacharacters,
2910      // which are the following plus space, tab, and newline: { }
2911      // | & $ ; < >
2912      // ...
2913
2914      // A word beginning with # causes that word and all remaining
2915      // characters on that line to be ignored.
2916
2917      // which means that only a '#' after /(?:^|[{}|&$;<>\s])/ starts a
2918      // comment but empirically
2919      // $ echo {#}
2920      // {#}
2921      // $ echo \$#
2922      // $#
2923      // $ echo }#
2924      // }#
2925
2926      // so /(?:^|[|&;<>\s])/ is more appropriate.
2927
2928      // http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html#SEC3
2929      // suggests that this definition is compatible with a
2930      // default mode that tries to use a single token definition
2931      // to recognize both bash/python style comments and C
2932      // preprocessor directives.
2933
2934      // This definition of punctuation does not include # in the list of
2935      // follow-on exclusions, so # will not be broken before if preceeded
2936      // by a punctuation character.  We could try to exclude # after
2937      // [|&;<>] but that doesn't seem to cause many major problems.
2938      // If that does turn out to be a problem, we should change the below
2939      // when hc is truthy to include # in the run of punctuation characters
2940      // only when not followint [|&;<>].
2941      /^.[^\s\w\.$@\'\"\`\/\\]*/;
2942
2943    fallthroughStylePatterns.push(
2944        // TODO(mikesamuel): recognize non-latin letters and numerals in idents
2945        [PR_LITERAL,     /^@[a-z_$][a-z_$@0-9]*/i, null],
2946        [PR_TYPE,        /^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/, null],
2947        [PR_PLAIN,       /^[a-z_$][a-z_$@0-9]*/i, null],
2948        [PR_LITERAL,
2949         new RegExp(
2950             '^(?:'
2951             // A hex number
2952             + '0x[a-f0-9]+'
2953             // or an octal or decimal number,
2954             + '|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)'
2955             // possibly in scientific notation
2956             + '(?:e[+\\-]?\\d+)?'
2957             + ')'
2958             // with an optional modifier like UL for unsigned long
2959             + '[a-z]*', 'i'),
2960         null, '0123456789'],
2961        // Don't treat escaped quotes in bash as starting strings.  See issue 144.
2962        [PR_PLAIN,       /^\\[\s\S]?/, null],
2963        [PR_PUNCTUATION, punctuation, null]);
2964
2965    return createSimpleLexer(shortcutStylePatterns, fallthroughStylePatterns);
2966  }
2967
2968  var decorateSource = sourceDecorator({
2969        'keywords': ALL_KEYWORDS,
2970        'hashComments': true,
2971        'cStyleComments': true,
2972        'multiLineStrings': true,
2973        'regexLiterals': true
2974      });
2975
2976  /**
2977   * Given a DOM subtree, wraps it in a list, and puts each line into its own
2978   * list item.
2979   *
2980   * @param {Node} node modified in place.  Its content is pulled into an
2981   *     HTMLOListElement, and each line is moved into a separate list item.
2982   *     This requires cloning elements, so the input might not have unique
2983   *     IDs after numbering.
2984   * @param {boolean} isPreformatted true iff white-space in text nodes should
2985   *     be treated as significant.
2986   */
2987  function numberLines(node, opt_startLineNum, isPreformatted) {
2988    var nocode = /(?:^|\s)nocode(?:\s|$)/;
2989    var lineBreak = /\r\n?|\n/;
2990
2991    var document = node.ownerDocument;
2992
2993    var li = document.createElement('li');
2994    while (node.firstChild) {
2995      li.appendChild(node.firstChild);
2996    }
2997    // An array of lines.  We split below, so this is initialized to one
2998    // un-split line.
2999    var listItems = [li];
3000
3001    function walk(node) {
3002      switch (node.nodeType) {
3003        case 1:  // Element
3004          if (nocode.test(node.className)) { break; }
3005          if ('br' === node.nodeName) {
3006            breakAfter(node);
3007            // Discard the <BR> since it is now flush against a </LI>.
3008            if (node.parentNode) {
3009              node.parentNode.removeChild(node);
3010            }
3011          } else {
3012            for (var child = node.firstChild; child; child = child.nextSibling) {
3013              walk(child);
3014            }
3015          }
3016          break;
3017        case 3: case 4:  // Text
3018          if (isPreformatted) {
3019            var text = node.nodeValue;
3020            var match = text.match(lineBreak);
3021            if (match) {
3022              var firstLine = text.substring(0, match.index);
3023              node.nodeValue = firstLine;
3024              var tail = text.substring(match.index + match[0].length);
3025              if (tail) {
3026                var parent = node.parentNode;
3027                parent.insertBefore(
3028                    document.createTextNode(tail), node.nextSibling);
3029              }
3030              breakAfter(node);
3031              if (!firstLine) {
3032                // Don't leave blank text nodes in the DOM.
3033                node.parentNode.removeChild(node);
3034              }
3035            }
3036          }
3037          break;
3038      }
3039    }
3040
3041    // Split a line after the given node.
3042    function breakAfter(lineEndNode) {
3043      // If there's nothing to the right, then we can skip ending the line
3044      // here, and move root-wards since splitting just before an end-tag
3045      // would require us to create a bunch of empty copies.
3046      while (!lineEndNode.nextSibling) {
3047        lineEndNode = lineEndNode.parentNode;
3048        if (!lineEndNode) { return; }
3049      }
3050
3051      function breakLeftOf(limit, copy) {
3052        // Clone shallowly if this node needs to be on both sides of the break.
3053        var rightSide = copy ? limit.cloneNode(false) : limit;
3054        var parent = limit.parentNode;
3055        if (parent) {
3056          // We clone the parent chain.
3057          // This helps us resurrect important styling elements that cross lines.
3058          // E.g. in <i>Foo<br>Bar</i>
3059          // should be rewritten to <li><i>Foo</i></li><li><i>Bar</i></li>.
3060          var parentClone = breakLeftOf(parent, 1);
3061          // Move the clone and everything to the right of the original
3062          // onto the cloned parent.
3063          var next = limit.nextSibling;
3064          parentClone.appendChild(rightSide);
3065          for (var sibling = next; sibling; sibling = next) {
3066            next = sibling.nextSibling;
3067            parentClone.appendChild(sibling);
3068          }
3069        }
3070        return rightSide;
3071      }
3072
3073      var copiedListItem = breakLeftOf(lineEndNode.nextSibling, 0);
3074
3075      // Walk the parent chain until we reach an unattached LI.
3076      for (var parent;
3077           // Check nodeType since IE invents document fragments.
3078           (parent = copiedListItem.parentNode) && parent.nodeType === 1;) {
3079        copiedListItem = parent;
3080      }
3081      // Put it on the list of lines for later processing.
3082      listItems.push(copiedListItem);
3083    }
3084
3085    // Split lines while there are lines left to split.
3086    for (var i = 0;  // Number of lines that have been split so far.
3087         i < listItems.length;  // length updated by breakAfter calls.
3088         ++i) {
3089      walk(listItems[i]);
3090    }
3091
3092    // Make sure numeric indices show correctly.
3093    if (opt_startLineNum === (opt_startLineNum|0)) {
3094      listItems[0].setAttribute('value', opt_startLineNum);
3095    }
3096
3097    var ol = document.createElement('ol');
3098    ol.className = 'linenums';
3099    var offset = Math.max(0, ((opt_startLineNum - 1 /* zero index */)) | 0) || 0;
3100    for (var i = 0, n = listItems.length; i < n; ++i) {
3101      li = listItems[i];
3102      // Stick a class on the LIs so that stylesheets can
3103      // color odd/even rows, or any other row pattern that
3104      // is co-prime with 10.
3105      li.className = 'L' + ((i + offset) % 10);
3106      if (!li.firstChild) {
3107        li.appendChild(document.createTextNode('\xA0'));
3108      }
3109      ol.appendChild(li);
3110    }
3111
3112    node.appendChild(ol);
3113  }
3114
3115  /**
3116   * Breaks {@code job.sourceCode} around style boundaries in
3117   * {@code job.decorations} and modifies {@code job.sourceNode} in place.
3118   * @param {Object} job like <pre>{
3119   *    sourceCode: {string} source as plain text,
3120   *    spans: {Array.<number|Node>} alternating span start indices into source
3121   *       and the text node or element (e.g. {@code <BR>}) corresponding to that
3122   *       span.
3123   *    decorations: {Array.<number|string} an array of style classes preceded
3124   *       by the position at which they start in job.sourceCode in order
3125   * }</pre>
3126   * @private
3127   */
3128  function recombineTagsAndDecorations(job) {
3129    var isIE8OrEarlier = /\bMSIE\s(\d+)/.exec(navigator.userAgent);
3130    isIE8OrEarlier = isIE8OrEarlier && +isIE8OrEarlier[1] <= 8;
3131    var newlineRe = /\n/g;
3132
3133    var source = job.sourceCode;
3134    var sourceLength = source.length;
3135    // Index into source after the last code-unit recombined.
3136    var sourceIndex = 0;
3137
3138    var spans = job.spans;
3139    var nSpans = spans.length;
3140    // Index into spans after the last span which ends at or before sourceIndex.
3141    var spanIndex = 0;
3142
3143    var decorations = job.decorations;
3144    var nDecorations = decorations.length;
3145    // Index into decorations after the last decoration which ends at or before
3146    // sourceIndex.
3147    var decorationIndex = 0;
3148
3149    // Remove all zero-length decorations.
3150    decorations[nDecorations] = sourceLength;
3151    var decPos, i;
3152    for (i = decPos = 0; i < nDecorations;) {
3153      if (decorations[i] !== decorations[i + 2]) {
3154        decorations[decPos++] = decorations[i++];
3155        decorations[decPos++] = decorations[i++];
3156      } else {
3157        i += 2;
3158      }
3159    }
3160    nDecorations = decPos;
3161
3162    // Simplify decorations.
3163    for (i = decPos = 0; i < nDecorations;) {
3164      var startPos = decorations[i];
3165      // Conflate all adjacent decorations that use the same style.
3166      var startDec = decorations[i + 1];
3167      var end = i + 2;
3168      while (end + 2 <= nDecorations && decorations[end + 1] === startDec) {
3169        end += 2;
3170      }
3171      decorations[decPos++] = startPos;
3172      decorations[decPos++] = startDec;
3173      i = end;
3174    }
3175
3176    nDecorations = decorations.length = decPos;
3177
3178    var sourceNode = job.sourceNode;
3179    var oldDisplay;
3180    if (sourceNode) {
3181      oldDisplay = sourceNode.style.display;
3182      sourceNode.style.display = 'none';
3183    }
3184    try {
3185      var decoration = null;
3186      while (spanIndex < nSpans) {
3187        var spanStart = spans[spanIndex];
3188        var spanEnd = spans[spanIndex + 2] || sourceLength;
3189
3190        var decEnd = decorations[decorationIndex + 2] || sourceLength;
3191
3192        var end = Math.min(spanEnd, decEnd);
3193
3194        var textNode = spans[spanIndex + 1];
3195        var styledText;
3196        if (textNode.nodeType !== 1  // Don't muck with <BR>s or <LI>s
3197            // Don't introduce spans around empty text nodes.
3198            && (styledText = source.substring(sourceIndex, end))) {
3199          // This may seem bizarre, and it is.  Emitting LF on IE causes the
3200          // code to display with spaces instead of line breaks.
3201          // Emitting Windows standard issue linebreaks (CRLF) causes a blank
3202          // space to appear at the beginning of every line but the first.
3203          // Emitting an old Mac OS 9 line separator makes everything spiffy.
3204          if (isIE8OrEarlier) {
3205            styledText = styledText.replace(newlineRe, '\r');
3206          }
3207          textNode.nodeValue = styledText;
3208          var document = textNode.ownerDocument;
3209          var span = document.createElement('span');
3210          span.className = decorations[decorationIndex + 1];
3211          var parentNode = textNode.parentNode;
3212          parentNode.replaceChild(span, textNode);
3213          span.appendChild(textNode);
3214          if (sourceIndex < spanEnd) {  // Split off a text node.
3215            spans[spanIndex + 1] = textNode
3216                // TODO: Possibly optimize by using '' if there's no flicker.
3217                = document.createTextNode(source.substring(end, spanEnd));
3218            parentNode.insertBefore(textNode, span.nextSibling);
3219          }
3220        }
3221
3222        sourceIndex = end;
3223
3224        if (sourceIndex >= spanEnd) {
3225          spanIndex += 2;
3226        }
3227        if (sourceIndex >= decEnd) {
3228          decorationIndex += 2;
3229        }
3230      }
3231    } finally {
3232      if (sourceNode) {
3233        sourceNode.style.display = oldDisplay;
3234      }
3235    }
3236  }
3237
3238
3239  /** Maps language-specific file extensions to handlers. */
3240  var langHandlerRegistry = {};
3241  /** Register a language handler for the given file extensions.
3242    * @param {function (Object)} handler a function from source code to a list
3243    *      of decorations.  Takes a single argument job which describes the
3244    *      state of the computation.   The single parameter has the form
3245    *      {@code {
3246    *        sourceCode: {string} as plain text.
3247    *        decorations: {Array.<number|string>} an array of style classes
3248    *                     preceded by the position at which they start in
3249    *                     job.sourceCode in order.
3250    *                     The language handler should assigned this field.
3251    *        basePos: {int} the position of source in the larger source chunk.
3252    *                 All positions in the output decorations array are relative
3253    *                 to the larger source chunk.
3254    *      } }
3255    * @param {Array.<string>} fileExtensions
3256    */
3257  function registerLangHandler(handler, fileExtensions) {
3258    for (var i = fileExtensions.length; --i >= 0;) {
3259      var ext = fileExtensions[i];
3260      if (!langHandlerRegistry.hasOwnProperty(ext)) {
3261        langHandlerRegistry[ext] = handler;
3262      } else if (win['console']) {
3263        console['warn']('cannot override language handler %s', ext);
3264      }
3265    }
3266  }
3267  function langHandlerForExtension(extension, source) {
3268    if (!(extension && langHandlerRegistry.hasOwnProperty(extension))) {
3269      // Treat it as markup if the first non whitespace character is a < and
3270      // the last non-whitespace character is a >.
3271      extension = /^\s*</.test(source)
3272          ? 'default-markup'
3273          : 'default-code';
3274    }
3275    return langHandlerRegistry[extension];
3276  }
3277  registerLangHandler(decorateSource, ['default-code']);
3278  registerLangHandler(
3279      createSimpleLexer(
3280          [],
3281          [
3282           [PR_PLAIN,       /^[^<?]+/],
3283           [PR_DECLARATION, /^<!\w[^>]*(?:>|$)/],
3284           [PR_COMMENT,     /^<\!--[\s\S]*?(?:-\->|$)/],
3285           // Unescaped content in an unknown language
3286           ['lang-',        /^<\?([\s\S]+?)(?:\?>|$)/],
3287           ['lang-',        /^<%([\s\S]+?)(?:%>|$)/],
3288           [PR_PUNCTUATION, /^(?:<[%?]|[%?]>)/],
3289           ['lang-',        /^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],
3290           // Unescaped content in javascript.  (Or possibly vbscript).
3291           ['lang-js',      /^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],
3292           // Contains unescaped stylesheet content
3293           ['lang-css',     /^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],
3294           ['lang-in.tag',  /^(<\/?[a-z][^<>]*>)/i]
3295          ]),
3296      ['default-markup', 'htm', 'html', 'mxml', 'xhtml', 'xml', 'xsl']);
3297  registerLangHandler(
3298      createSimpleLexer(
3299          [
3300           [PR_PLAIN,        /^[\s]+/, null, ' \t\r\n'],
3301           [PR_ATTRIB_VALUE, /^(?:\"[^\"]*\"?|\'[^\']*\'?)/, null, '\"\'']
3302           ],
3303          [
3304           [PR_TAG,          /^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],
3305           [PR_ATTRIB_NAME,  /^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],
3306           ['lang-uq.val',   /^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],
3307           [PR_PUNCTUATION,  /^[=<>\/]+/],
3308           ['lang-js',       /^on\w+\s*=\s*\"([^\"]+)\"/i],
3309           ['lang-js',       /^on\w+\s*=\s*\'([^\']+)\'/i],
3310           ['lang-js',       /^on\w+\s*=\s*([^\"\'>\s]+)/i],
3311           ['lang-css',      /^style\s*=\s*\"([^\"]+)\"/i],
3312           ['lang-css',      /^style\s*=\s*\'([^\']+)\'/i],
3313           ['lang-css',      /^style\s*=\s*([^\"\'>\s]+)/i]
3314           ]),
3315      ['in.tag']);
3316  registerLangHandler(
3317      createSimpleLexer([], [[PR_ATTRIB_VALUE, /^[\s\S]+/]]), ['uq.val']);
3318  registerLangHandler(sourceDecorator({
3319          'keywords': CPP_KEYWORDS,
3320          'hashComments': true,
3321          'cStyleComments': true,
3322          'types': C_TYPES
3323        }), ['c', 'cc', 'cpp', 'cxx', 'cyc', 'm']);
3324  registerLangHandler(sourceDecorator({
3325          'keywords': 'null,true,false'
3326        }), ['json']);
3327  registerLangHandler(sourceDecorator({
3328          'keywords': CSHARP_KEYWORDS,
3329          'hashComments': true,
3330          'cStyleComments': true,
3331          'verbatimStrings': true,
3332          'types': C_TYPES
3333        }), ['cs']);
3334  registerLangHandler(sourceDecorator({
3335          'keywords': JAVA_KEYWORDS,
3336          'cStyleComments': true
3337        }), ['java']);
3338  registerLangHandler(sourceDecorator({
3339          'keywords': SH_KEYWORDS,
3340          'hashComments': true,
3341          'multiLineStrings': true
3342        }), ['bsh', 'csh', 'sh']);
3343  registerLangHandler(sourceDecorator({
3344          'keywords': PYTHON_KEYWORDS,
3345          'hashComments': true,
3346          'multiLineStrings': true,
3347          'tripleQuotedStrings': true
3348        }), ['cv', 'py']);
3349  registerLangHandler(sourceDecorator({
3350          'keywords': PERL_KEYWORDS,
3351          'hashComments': true,
3352          'multiLineStrings': true,
3353          'regexLiterals': true
3354        }), ['perl', 'pl', 'pm']);
3355  registerLangHandler(sourceDecorator({
3356          'keywords': RUBY_KEYWORDS,
3357          'hashComments': true,
3358          'multiLineStrings': true,
3359          'regexLiterals': true
3360        }), ['rb']);
3361  registerLangHandler(sourceDecorator({
3362          'keywords': JSCRIPT_KEYWORDS,
3363          'cStyleComments': true,
3364          'regexLiterals': true
3365        }), ['js']);
3366  registerLangHandler(sourceDecorator({
3367          'keywords': COFFEE_KEYWORDS,
3368          'hashComments': 3,  // ### style block comments
3369          'cStyleComments': true,
3370          'multilineStrings': true,
3371          'tripleQuotedStrings': true,
3372          'regexLiterals': true
3373        }), ['coffee']);
3374  registerLangHandler(
3375      createSimpleLexer([], [[PR_STRING, /^[\s\S]+/]]), ['regex']);
3376
3377  function applyDecorator(job) {
3378    var opt_langExtension = job.langExtension;
3379
3380    try {
3381      // Extract tags, and convert the source code to plain text.
3382      var sourceAndSpans = extractSourceSpans(job.sourceNode, job.pre);
3383      /** Plain text. @type {string} */
3384      var source = sourceAndSpans.sourceCode;
3385      job.sourceCode = source;
3386      job.spans = sourceAndSpans.spans;
3387      job.basePos = 0;
3388
3389      // Apply the appropriate language handler
3390      langHandlerForExtension(opt_langExtension, source)(job);
3391
3392      // Integrate the decorations and tags back into the source code,
3393      // modifying the sourceNode in place.
3394      recombineTagsAndDecorations(job);
3395    } catch (e) {
3396      if (win['console']) {
3397        console['log'](e && e['stack'] ? e['stack'] : e);
3398      }
3399    }
3400  }
3401
3402  /**
3403   * @param sourceCodeHtml {string} The HTML to pretty print.
3404   * @param opt_langExtension {string} The language name to use.
3405   *     Typically, a filename extension like 'cpp' or 'java'.
3406   * @param opt_numberLines {number|boolean} True to number lines,
3407   *     or the 1-indexed number of the first line in sourceCodeHtml.
3408   */
3409  function prettyPrintOne(sourceCodeHtml, opt_langExtension, opt_numberLines) {
3410    var container = document.createElement('pre');
3411    // This could cause images to load and onload listeners to fire.
3412    // E.g. <img onerror="alert(1337)" src="nosuchimage.png">.
3413    // We assume that the inner HTML is from a trusted source.
3414    container.innerHTML = sourceCodeHtml;
3415    if (opt_numberLines) {
3416      numberLines(container, opt_numberLines, true);
3417    }
3418
3419    var job = {
3420      langExtension: opt_langExtension,
3421      numberLines: opt_numberLines,
3422      sourceNode: container,
3423      pre: 1
3424    };
3425    applyDecorator(job);
3426    return container.innerHTML;
3427  }
3428
3429  function prettyPrint(opt_whenDone) {
3430    function byTagName(tn) { return document.getElementsByTagName(tn); }
3431    // fetch a list of nodes to rewrite
3432    var codeSegments = [byTagName('pre'), byTagName('code'), byTagName('xmp')];
3433    var elements = [];
3434    for (var i = 0; i < codeSegments.length; ++i) {
3435      for (var j = 0, n = codeSegments[i].length; j < n; ++j) {
3436        elements.push(codeSegments[i][j]);
3437      }
3438    }
3439    codeSegments = null;
3440
3441    var clock = Date;
3442    if (!clock['now']) {
3443      clock = { 'now': function () { return +(new Date); } };
3444    }
3445
3446    // The loop is broken into a series of continuations to make sure that we
3447    // don't make the browser unresponsive when rewriting a large page.
3448    var k = 0;
3449    var prettyPrintingJob;
3450
3451    var langExtensionRe = /\blang(?:uage)?-([\w.]+)(?!\S)/;
3452    var prettyPrintRe = /\bprettyprint\b/;
3453    var prettyPrintedRe = /\bprettyprinted\b/;
3454    var preformattedTagNameRe = /pre|xmp/i;
3455    var codeRe = /^code$/i;
3456    var preCodeXmpRe = /^(?:pre|code|xmp)$/i;
3457
3458    function doWork() {
3459      var endTime = (win['PR_SHOULD_USE_CONTINUATION'] ?
3460                     clock['now']() + 250 /* ms */ :
3461                     Infinity);
3462      for (; k < elements.length && clock['now']() < endTime; k++) {
3463        var cs = elements[k];
3464        var className = cs.className;
3465        if (prettyPrintRe.test(className)
3466            // Don't redo this if we've already done it.
3467            // This allows recalling pretty print to just prettyprint elements
3468            // that have been added to the page since last call.
3469            && !prettyPrintedRe.test(className)) {
3470
3471          // make sure this is not nested in an already prettified element
3472          var nested = false;
3473          for (var p = cs.parentNode; p; p = p.parentNode) {
3474            var tn = p.tagName;
3475            if (preCodeXmpRe.test(tn)
3476                && p.className && prettyPrintRe.test(p.className)) {
3477              nested = true;
3478              break;
3479            }
3480          }
3481          if (!nested) {
3482            // Mark done.  If we fail to prettyprint for whatever reason,
3483            // we shouldn't try again.
3484            cs.className += ' prettyprinted';
3485
3486            // If the classes includes a language extensions, use it.
3487            // Language extensions can be specified like
3488            //     <pre class="prettyprint lang-cpp">
3489            // the language extension "cpp" is used to find a language handler
3490            // as passed to PR.registerLangHandler.
3491            // HTML5 recommends that a language be specified using "language-"
3492            // as the prefix instead.  Google Code Prettify supports both.
3493            // http://dev.w3.org/html5/spec-author-view/the-code-element.html
3494            var langExtension = className.match(langExtensionRe);
3495            // Support <pre class="prettyprint"><code class="language-c">
3496            var wrapper;
3497            if (!langExtension && (wrapper = childContentWrapper(cs))
3498                && codeRe.test(wrapper.tagName)) {
3499              langExtension = wrapper.className.match(langExtensionRe);
3500            }
3501
3502            if (langExtension) { langExtension = langExtension[1]; }
3503
3504            var preformatted;
3505            if (preformattedTagNameRe.test(cs.tagName)) {
3506              preformatted = 1;
3507            } else {
3508              var currentStyle = cs['currentStyle'];
3509              var whitespace = (
3510                  currentStyle
3511                  ? currentStyle['whiteSpace']
3512                  : (document.defaultView
3513                     && document.defaultView.getComputedStyle)
3514                  ? document.defaultView.getComputedStyle(cs, null)
3515                  .getPropertyValue('white-space')
3516                  : 0);
3517              preformatted = whitespace
3518                  && 'pre' === whitespace.substring(0, 3);
3519            }
3520
3521            // Look for a class like linenums or linenums:<n> where <n> is the
3522            // 1-indexed number of the first line.
3523            var lineNums = cs.className.match(/\blinenums\b(?::(\d+))?/);
3524            lineNums = lineNums
3525                ? lineNums[1] && lineNums[1].length ? +lineNums[1] : true
3526                : false;
3527            if (lineNums) { numberLines(cs, lineNums, preformatted); }
3528
3529            // do the pretty printing
3530            prettyPrintingJob = {
3531              langExtension: langExtension,
3532              sourceNode: cs,
3533              numberLines: lineNums,
3534              pre: preformatted
3535            };
3536            applyDecorator(prettyPrintingJob);
3537          }
3538        }
3539      }
3540      if (k < elements.length) {
3541        // finish up in a continuation
3542        setTimeout(doWork, 250);
3543      } else if (opt_whenDone) {
3544        opt_whenDone();
3545      }
3546    }
3547
3548    doWork();
3549  }
3550
3551  /**
3552   * Contains functions for creating and registering new language handlers.
3553   * @type {Object}
3554   */
3555  var PR = win['PR'] = {
3556        'createSimpleLexer': createSimpleLexer,
3557        'registerLangHandler': registerLangHandler,
3558        'sourceDecorator': sourceDecorator,
3559        'PR_ATTRIB_NAME': PR_ATTRIB_NAME,
3560        'PR_ATTRIB_VALUE': PR_ATTRIB_VALUE,
3561        'PR_COMMENT': PR_COMMENT,
3562        'PR_DECLARATION': PR_DECLARATION,
3563        'PR_KEYWORD': PR_KEYWORD,
3564        'PR_LITERAL': PR_LITERAL,
3565        'PR_NOCODE': PR_NOCODE,
3566        'PR_PLAIN': PR_PLAIN,
3567        'PR_PUNCTUATION': PR_PUNCTUATION,
3568        'PR_SOURCE': PR_SOURCE,
3569        'PR_STRING': PR_STRING,
3570        'PR_TAG': PR_TAG,
3571        'PR_TYPE': PR_TYPE,
3572        'prettyPrintOne': win['prettyPrintOne'] = prettyPrintOne,
3573        'prettyPrint': win['prettyPrint'] = prettyPrint
3574      };
3575
3576  // Make PR available via the Asynchronous Module Definition (AMD) API.
3577  // Per https://github.com/amdjs/amdjs-api/wiki/AMD:
3578  // The Asynchronous Module Definition (AMD) API specifies a
3579  // mechanism for defining modules such that the module and its
3580  // dependencies can be asynchronously loaded.
3581  // ...
3582  // To allow a clear indicator that a global define function (as
3583  // needed for script src browser loading) conforms to the AMD API,
3584  // any global define function SHOULD have a property called "amd"
3585  // whose value is an object. This helps avoid conflict with any
3586  // other existing JavaScript code that could have defined a define()
3587  // function that does not conform to the AMD API.
3588  if (typeof define === "function" && define['amd']) {
3589    define(function () {
3590      return PR;
3591    });
3592  }
3593})();
3594;
3595(function(scope) {
3596
3597  var ContextFreeParser = {
3598    parse: function(text) {
3599      var top = {};
3600      var entities = [];
3601      var current = top;
3602      var subCurrent = {};
3603
3604      var scriptDocCommentClause = '\\/\\*\\*([\\s\\S]*?)\\*\\/';
3605      var htmlDocCommentClause = '<!--([\\s\\S]*?)-->';
3606
3607      // matches text between /** and */ inclusive and <!-- and --> inclusive
3608      var docCommentRegex = new RegExp(scriptDocCommentClause + '|' + htmlDocCommentClause, 'g');
3609
3610      // acquire all script doc comments
3611      var docComments = text.match(docCommentRegex) || [];
3612
3613      // each match represents a single block of doc comments
3614      docComments.forEach(function(m) {
3615        // unify line ends, remove all comment characters, split into individual lines
3616        var lines = m.replace(/\r\n/g, '\n').replace(/^\s*\/\*\*|^\s*\*\/|^\s*\* ?|^\s*\<\!-\-|^s*\-\-\>/gm, '').split('\n');
3617
3618        // pragmas (@-rules) must occur on a line by themselves
3619        var pragmas = [];
3620        // filter lines whose first non-whitespace character is @ into the pragma list
3621        // (and out of the `lines` array)
3622        lines = lines.filter(function(l) {
3623          var m = l.match(/\s*@([\w-]*) (.*)/);
3624          if (!m) {
3625            return true;
3626          }
3627          pragmas.push(m);
3628        });
3629
3630        // collect all other text into a single block
3631        var code = lines.join('\n');
3632
3633        // process pragmas
3634        pragmas.forEach(function(m) {
3635          var pragma = m[1], content = m[2];
3636          switch (pragma) {
3637
3638            // currently all entities are either @class or @element
3639            case 'class':
3640            case 'element':
3641              current = {
3642                name: content,
3643                description: code
3644              };
3645              entities.push(current);
3646              break;
3647
3648            // an entity may have these describable sub-features
3649            case 'attribute':
3650            case 'property':
3651            case 'method':
3652            case 'event':
3653              subCurrent = {
3654                name: content,
3655                description: code
3656              };
3657              var label = pragma == 'property' ? 'properties' : pragma + 's';
3658              makePragma(current, label, subCurrent);
3659              break;
3660
3661            // sub-feature pragmas
3662            case 'default':
3663            case 'type':
3664              subCurrent[pragma] = content;
3665              break;
3666
3667            // everything else
3668            default:
3669              current[pragma] = content;
3670              break;
3671          }
3672        });
3673
3674        // utility function, yay hoisting
3675        function makePragma(object, pragma, content) {
3676          var p$ = object;
3677          var p = p$[pragma];
3678          if (!p) {
3679            p$[pragma] = p = [];
3680          }
3681          p.push(content);
3682        }
3683
3684      });
3685
3686      if (entities.length === 0) {
3687        entities.push({name: 'Entity', description: '**Undocumented**'});
3688      }
3689      return entities;
3690    }
3691  };
3692
3693  if (typeof module !== 'undefined' && module.exports) {
3694    module.exports = ContextFreeParser;
3695  } else {
3696    scope.ContextFreeParser = ContextFreeParser;
3697  }
3698
3699})(this);;
3700
3701
3702    Polymer('core-xhr', {
3703
3704      /**
3705       * Sends a HTTP request to the server and returns the XHR object.
3706       *
3707       * @method request
3708       * @param {Object} inOptions
3709       *    @param {String} inOptions.url The url to which the request is sent.
3710       *    @param {String} inOptions.method The HTTP method to use, default is GET.
3711       *    @param {boolean} inOptions.sync By default, all requests are sent asynchronously. To send synchronous requests, set to true.
3712       *    @param {Object} inOptions.params Data to be sent to the server.
3713       *    @param {Object} inOptions.body The content for the request body for POST method.
3714       *    @param {Object} inOptions.headers HTTP request headers.
3715       *    @param {String} inOptions.responseType The response type. Default is 'text'.
3716       *    @param {boolean} inOptions.withCredentials Whether or not to send credentials on the request. Default is false.
3717       *    @param {Object} inOptions.callback Called when request is completed.
3718       * @returns {Object} XHR object.
3719       */
3720      request: function(options) {
3721        var xhr = new XMLHttpRequest();
3722        var url = options.url;
3723        var method = options.method || 'GET';
3724        var async = !options.sync;
3725        //
3726        var params = this.toQueryString(options.params);
3727        if (params && method == 'GET') {
3728          url += (url.indexOf('?') > 0 ? '&' : '?') + params;
3729        }
3730        var xhrParams = this.isBodyMethod(method) ? (options.body || params) : null;
3731        //
3732        xhr.open(method, url, async);
3733        if (options.responseType) {
3734          xhr.responseType = options.responseType;
3735        }
3736        if (options.withCredentials) {
3737          xhr.withCredentials = true;
3738        }
3739        this.makeReadyStateHandler(xhr, options.callback);
3740        this.setRequestHeaders(xhr, options.headers);
3741        xhr.send(xhrParams);
3742        if (!async) {
3743          xhr.onreadystatechange(xhr);
3744        }
3745        return xhr;
3746      },
3747
3748      toQueryString: function(params) {
3749        var r = [];
3750        for (var n in params) {
3751          var v = params[n];
3752          n = encodeURIComponent(n);
3753          r.push(v == null ? n : (n + '=' + encodeURIComponent(v)));
3754        }
3755        return r.join('&');
3756      },
3757
3758      isBodyMethod: function(method) {
3759        return this.bodyMethods[(method || '').toUpperCase()];
3760      },
3761
3762      bodyMethods: {
3763        POST: 1,
3764        PUT: 1,
3765        DELETE: 1
3766      },
3767
3768      makeReadyStateHandler: function(xhr, callback) {
3769        xhr.onreadystatechange = function() {
3770          if (xhr.readyState == 4) {
3771            callback && callback.call(null, xhr.response, xhr);
3772          }
3773        };
3774      },
3775
3776      setRequestHeaders: function(xhr, headers) {
3777        if (headers) {
3778          for (var name in headers) {
3779            xhr.setRequestHeader(name, headers[name]);
3780          }
3781        }
3782      }
3783
3784    });
3785
3786  ;
3787
3788
3789  Polymer('core-ajax', {
3790    /**
3791     * Fired when a response is received.
3792     *
3793     * @event core-response
3794     */
3795
3796    /**
3797     * Fired when an error is received.
3798     *
3799     * @event core-error
3800     */
3801
3802    /**
3803     * Fired whenever a response or an error is received.
3804     *
3805     * @event core-complete
3806     */
3807
3808    /**
3809     * The URL target of the request.
3810     *
3811     * @attribute url
3812     * @type string
3813     * @default ''
3814     */
3815    url: '',
3816
3817    /**
3818     * Specifies what data to store in the `response` property, and
3819     * to deliver as `event.response` in `response` events.
3820     *
3821     * One of:
3822     *
3823     *    `text`: uses `XHR.responseText`.
3824     *
3825     *    `xml`: uses `XHR.responseXML`.
3826     *
3827     *    `json`: uses `XHR.responseText` parsed as JSON.
3828     *
3829     *    `arraybuffer`: uses `XHR.response`.
3830     *
3831     *    `blob`: uses `XHR.response`.
3832     *
3833     *    `document`: uses `XHR.response`.
3834     *
3835     * @attribute handleAs
3836     * @type string
3837     * @default 'text'
3838     */
3839    handleAs: '',
3840
3841    /**
3842     * If true, automatically performs an Ajax request when either `url` or `params` changes.
3843     *
3844     * @attribute auto
3845     * @type boolean
3846     * @default false
3847     */
3848    auto: false,
3849
3850    /**
3851     * Parameters to send to the specified URL, as JSON.
3852     *
3853     * @attribute params
3854     * @type string (JSON)
3855     * @default ''
3856     */
3857    params: '',
3858
3859    /**
3860     * Returns the response object.
3861     *
3862     * @attribute response
3863     * @type Object
3864     * @default null
3865     */
3866    response: null,
3867
3868    /**
3869     * The HTTP method to use such as 'GET', 'POST', 'PUT', or 'DELETE'.
3870     * Default is 'GET'.
3871     *
3872     * @attribute method
3873     * @type string
3874     * @default ''
3875     */
3876    method: '',
3877
3878    /**
3879     * HTTP request headers to send.
3880     *
3881     * Example:
3882     *
3883     *     <core-ajax
3884     *         auto
3885     *         url="http://somesite.com"
3886     *         headers='{"X-Requested-With": "XMLHttpRequest"}'
3887     *         handleAs="json"
3888     *         on-core-response="{{handleResponse}}"></core-ajax>
3889     *
3890     * @attribute headers
3891     * @type Object
3892     * @default null
3893     */
3894    headers: null,
3895
3896    /**
3897     * Optional raw body content to send when method === "POST".
3898     *
3899     * Example:
3900     *
3901     *     <core-ajax method="POST" auto url="http://somesite.com"
3902     *         body='{"foo":1, "bar":2}'>
3903     *     </core-ajax>
3904     *
3905     * @attribute body
3906     * @type Object
3907     * @default null
3908     */
3909    body: null,
3910
3911    /**
3912     * Content type to use when sending data.
3913     *
3914     * @attribute contentType
3915     * @type string
3916     * @default 'application/x-www-form-urlencoded'
3917     */
3918    contentType: 'application/x-www-form-urlencoded',
3919
3920    /**
3921     * Set the withCredentials flag on the request.
3922     *
3923     * @attribute withCredentials
3924     * @type boolean
3925     * @default false
3926     */
3927    withCredentials: false,
3928
3929    /**
3930     * Additional properties to send to core-xhr.
3931     *
3932     * Can be set to an object containing default properties
3933     * to send as arguments to the `core-xhr.request()` method
3934     * which implements the low-level communication.
3935     *
3936     * @property xhrArgs
3937     * @type Object
3938     * @default null
3939     */
3940    xhrArgs: null,
3941
3942    ready: function() {
3943      this.xhr = document.createElement('core-xhr');
3944    },
3945
3946    receive: function(response, xhr) {
3947      if (this.isSuccess(xhr)) {
3948        this.processResponse(xhr);
3949      } else {
3950        this.error(xhr);
3951      }
3952      this.complete(xhr);
3953    },
3954
3955    isSuccess: function(xhr) {
3956      var status = xhr.status || 0;
3957      return !status || (status >= 200 && status < 300);
3958    },
3959
3960    processResponse: function(xhr) {
3961      var response = this.evalResponse(xhr);
3962      this.response = response;
3963      this.fire('core-response', {response: response, xhr: xhr});
3964    },
3965
3966    error: function(xhr) {
3967      var response = xhr.status + ': ' + xhr.responseText;
3968      this.fire('core-error', {response: response, xhr: xhr});
3969    },
3970
3971    complete: function(xhr) {
3972      this.fire('core-complete', {response: xhr.status, xhr: xhr});
3973    },
3974
3975    evalResponse: function(xhr) {
3976      return this[(this.handleAs || 'text') + 'Handler'](xhr);
3977    },
3978
3979    xmlHandler: function(xhr) {
3980      return xhr.responseXML;
3981    },
3982
3983    textHandler: function(xhr) {
3984      return xhr.responseText;
3985    },
3986
3987    jsonHandler: function(xhr) {
3988      var r = xhr.responseText;
3989      try {
3990        return JSON.parse(r);
3991      } catch (x) {
3992        return r;
3993      }
3994    },
3995
3996    documentHandler: function(xhr) {
3997      return xhr.response;
3998    },
3999
4000    blobHandler: function(xhr) {
4001      return xhr.response;
4002    },
4003
4004    arraybufferHandler: function(xhr) {
4005      return xhr.response;
4006    },
4007
4008    urlChanged: function() {
4009      if (!this.handleAs) {
4010        var ext = String(this.url).split('.').pop();
4011        switch (ext) {
4012          case 'json':
4013            this.handleAs = 'json';
4014            break;
4015        }
4016      }
4017      this.autoGo();
4018    },
4019
4020    paramsChanged: function() {
4021      this.autoGo();
4022    },
4023
4024    autoChanged: function() {
4025      this.autoGo();
4026    },
4027
4028    // TODO(sorvell): multiple side-effects could call autoGo
4029    // during one micro-task, use a job to have only one action
4030    // occur
4031    autoGo: function() {
4032      if (this.auto) {
4033        this.goJob = this.job(this.goJob, this.go, 0);
4034      }
4035    },
4036
4037    /**
4038     * Performs an Ajax request to the specified URL.
4039     *
4040     * @method go
4041     */
4042    go: function() {
4043      var args = this.xhrArgs || {};
4044      // TODO(sjmiles): we may want XHR to default to POST if body is set
4045      args.body = this.body || args.body;
4046      args.params = this.params || args.params;
4047      if (args.params && typeof(args.params) == 'string') {
4048        args.params = JSON.parse(args.params);
4049      }
4050      args.headers = this.headers || args.headers || {};
4051      if (args.headers && typeof(args.headers) == 'string') {
4052        args.headers = JSON.parse(args.headers);
4053      }
4054      if (this.contentType) {
4055        args.headers['content-type'] = this.contentType;
4056      }
4057      if (this.handleAs === 'arraybuffer' || this.handleAs === 'blob' ||
4058          this.handleAs === 'document') {
4059        args.responseType = this.handleAs;
4060      }
4061      args.withCredentials = this.withCredentials;
4062      args.callback = this.receive.bind(this);
4063      args.url = this.url;
4064      args.method = this.method;
4065      return args.url && this.xhr.request(args);
4066    }
4067
4068  });
4069
4070;
4071
4072
4073  Polymer('context-free-parser', {
4074
4075    text: null,
4076
4077    textChanged: function() {
4078      if (this.text) {
4079        var entities = ContextFreeParser.parse(this.text);
4080        if (!entities || entities.length === 0) {
4081          entities = [
4082            {name: this.url.split('/').pop(), description: '**Undocumented**'}
4083          ];
4084        }
4085        this.data = { classes: entities };
4086      }
4087    },
4088
4089    dataChanged: function() {
4090      this.fire('data-ready');
4091    }
4092
4093  });
4094
4095;
4096
4097
4098    Polymer('core-doc-page', {
4099
4100      hilight: function(event, detail, sender) {
4101        detail.code = prettyPrintOne((detail.code || '').replace(/</g,'&lt;').replace(/>/g,'&gt;'));
4102      },
4103
4104      homepageFilter: function(data) {
4105        if (!data) {
4106          return '';
4107        }
4108        if (!data.homepage || data.homepage === 'github.io') {
4109          return '//polymer.github.io/' + data.name;
4110        } else {
4111          return data.homepage;
4112        }
4113      }
4114
4115    });
4116
4117  ;
4118
4119    Polymer('core-selection', {
4120      /**
4121       * If true, multiple selections are allowed.
4122       *
4123       * @attribute multi
4124       * @type boolean
4125       * @default false
4126       */
4127      multi: false,
4128      ready: function() {
4129        this.clear();
4130      },
4131      clear: function() {
4132        this.selection = [];
4133      },
4134      /**
4135       * Retrieves the selected item(s).
4136       * @method getSelection
4137       * @returns Returns the selected item(s). If the multi property is true,
4138       * getSelection will return an array, otherwise it will return
4139       * the selected item or undefined if there is no selection.
4140      */
4141      getSelection: function() {
4142        return this.multi ? this.selection : this.selection[0];
4143      },
4144      /**
4145       * Indicates if a given item is selected.
4146       * @method isSelected
4147       * @param {any} item The item whose selection state should be checked.
4148       * @returns Returns true if `item` is selected.
4149      */
4150      isSelected: function(item) {
4151        return this.selection.indexOf(item) >= 0;
4152      },
4153      setItemSelected: function(item, isSelected) {
4154        if (item !== undefined && item !== null) {
4155          if (isSelected) {
4156            this.selection.push(item);
4157          } else {
4158            var i = this.selection.indexOf(item);
4159            if (i >= 0) {
4160              this.selection.splice(i, 1);
4161            }
4162          }
4163          this.fire("core-select", {isSelected: isSelected, item: item});
4164        }
4165      },
4166      /**
4167       * Set the selection state for a given `item`. If the multi property
4168       * is true, then the selected state of `item` will be toggled; otherwise
4169       * the `item` will be selected.
4170       * @method select
4171       * @param {any} item: The item to select.
4172      */
4173      select: function(item) {
4174        if (this.multi) {
4175          this.toggle(item);
4176        } else if (this.getSelection() !== item) {
4177          this.setItemSelected(this.getSelection(), false);
4178          this.setItemSelected(item, true);
4179        }
4180      },
4181      /**
4182       * Toggles the selection state for `item`.
4183       * @method toggle
4184       * @param {any} item: The item to toggle.
4185      */
4186      toggle: function(item) {
4187        this.setItemSelected(item, !this.isSelected(item));
4188      }
4189    });
4190  ;
4191
4192
4193    Polymer('core-selector', {
4194
4195      /**
4196       * Gets or sets the selected element.  Default to use the index
4197       * of the item element.
4198       *
4199       * If you want a specific attribute value of the element to be
4200       * used instead of index, set "valueattr" to that attribute name.
4201       *
4202       * Example:
4203       *
4204       *     <core-selector valueattr="label" selected="foo">
4205       *       <div label="foo"></div>
4206       *       <div label="bar"></div>
4207       *       <div label="zot"></div>
4208       *     </core-selector>
4209       *
4210       * In multi-selection this should be an array of values.
4211       *
4212       * Example:
4213       *
4214       *     <core-selector id="selector" valueattr="label" multi>
4215       *       <div label="foo"></div>
4216       *       <div label="bar"></div>
4217       *       <div label="zot"></div>
4218       *     </core-selector>
4219       *
4220       *     this.$.selector.selected = ['foo', 'zot'];
4221       *
4222       * @attribute selected
4223       * @type Object
4224       * @default null
4225       */
4226      selected: null,
4227
4228      /**
4229       * If true, multiple selections are allowed.
4230       *
4231       * @attribute multi
4232       * @type boolean
4233       * @default false
4234       */
4235      multi: false,
4236
4237      /**
4238       * Specifies the attribute to be used for "selected" attribute.
4239       *
4240       * @attribute valueattr
4241       * @type string
4242       * @default 'name'
4243       */
4244      valueattr: 'name',
4245
4246      /**
4247       * Specifies the CSS class to be used to add to the selected element.
4248       *
4249       * @attribute selectedClass
4250       * @type string
4251       * @default 'core-selected'
4252       */
4253      selectedClass: 'core-selected',
4254
4255      /**
4256       * Specifies the property to be used to set on the selected element
4257       * to indicate its active state.
4258       *
4259       * @attribute selectedProperty
4260       * @type string
4261       * @default ''
4262       */
4263      selectedProperty: '',
4264
4265      /**
4266       * Specifies the attribute to set on the selected element to indicate
4267       * its active state.
4268       *
4269       * @attribute selectedAttribute
4270       * @type string
4271       * @default 'active'
4272       */
4273      selectedAttribute: 'active',
4274
4275      /**
4276       * Returns the currently selected element. In multi-selection this returns
4277       * an array of selected elements.
4278       *
4279       * @attribute selectedItem
4280       * @type Object
4281       * @default null
4282       */
4283      selectedItem: null,
4284
4285      /**
4286       * In single selection, this returns the model associated with the
4287       * selected element.
4288       *
4289       * @attribute selectedModel
4290       * @type Object
4291       * @default null
4292       */
4293      selectedModel: null,
4294
4295      /**
4296       * In single selection, this returns the selected index.
4297       *
4298       * @attribute selectedIndex
4299       * @type number
4300       * @default -1
4301       */
4302      selectedIndex: -1,
4303
4304      /**
4305       * The target element that contains items.  If this is not set
4306       * core-selector is the container.
4307       *
4308       * @attribute target
4309       * @type Object
4310       * @default null
4311       */
4312      target: null,
4313
4314      /**
4315       * This can be used to query nodes from the target node to be used for
4316       * selection items.  Note this only works if the 'target' property is set.
4317       *
4318       * Example:
4319       *
4320       *     <core-selector target="{{$.myForm}}" itemsSelector="input[type=radio]"></core-selector>
4321       *     <form id="myForm">
4322       *       <label><input type="radio" name="color" value="red"> Red</label> <br>
4323       *       <label><input type="radio" name="color" value="green"> Green</label> <br>
4324       *       <label><input type="radio" name="color" value="blue"> Blue</label> <br>
4325       *       <p>color = {{color}}</p>
4326       *     </form>
4327       *
4328       * @attribute itemSelector
4329       * @type string
4330       * @default ''
4331       */
4332      itemsSelector: '',
4333
4334      /**
4335       * The event that would be fired from the item element to indicate
4336       * it is being selected.
4337       *
4338       * @attribute activateEvent
4339       * @type string
4340       * @default 'tap'
4341       */
4342      activateEvent: 'tap',
4343
4344      /**
4345       * Set this to true to disallow changing the selection via the
4346       * `activateEvent`.
4347       *
4348       * @attribute notap
4349       * @type boolean
4350       * @default false
4351       */
4352      notap: false,
4353
4354      ready: function() {
4355        this.activateListener = this.activateHandler.bind(this);
4356        this.observer = new MutationObserver(this.updateSelected.bind(this));
4357        if (!this.target) {
4358          this.target = this;
4359        }
4360      },
4361
4362      get items() {
4363        if (!this.target) {
4364          return [];
4365        }
4366        var nodes = this.target !== this ? (this.itemsSelector ?
4367            this.target.querySelectorAll(this.itemsSelector) :
4368                this.target.children) : this.$.items.getDistributedNodes();
4369        return Array.prototype.filter.call(nodes || [], function(n) {
4370          return n && n.localName !== 'template';
4371        });
4372      },
4373
4374      targetChanged: function(old) {
4375        if (old) {
4376          this.removeListener(old);
4377          this.observer.disconnect();
4378          this.clearSelection();
4379        }
4380        if (this.target) {
4381          this.addListener(this.target);
4382          this.observer.observe(this.target, {childList: true});
4383          this.updateSelected();
4384        }
4385      },
4386
4387      addListener: function(node) {
4388        node.addEventListener(this.activateEvent, this.activateListener);
4389      },
4390
4391      removeListener: function(node) {
4392        node.removeEventListener(this.activateEvent, this.activateListener);
4393      },
4394
4395      get selection() {
4396        return this.$.selection.getSelection();
4397      },
4398
4399      selectedChanged: function() {
4400        this.updateSelected();
4401      },
4402
4403      updateSelected: function() {
4404        this.validateSelected();
4405        if (this.multi) {
4406          this.clearSelection();
4407          this.selected && this.selected.forEach(function(s) {
4408            this.valueToSelection(s);
4409          }, this);
4410        } else {
4411          this.valueToSelection(this.selected);
4412        }
4413      },
4414
4415      validateSelected: function() {
4416        // convert to an array for multi-selection
4417        if (this.multi && !Array.isArray(this.selected) &&
4418            this.selected !== null && this.selected !== undefined) {
4419          this.selected = [this.selected];
4420        }
4421      },
4422
4423      clearSelection: function() {
4424        if (this.multi) {
4425          this.selection.slice().forEach(function(s) {
4426            this.$.selection.setItemSelected(s, false);
4427          }, this);
4428        } else {
4429          this.$.selection.setItemSelected(this.selection, false);
4430        }
4431        this.selectedItem = null;
4432        this.$.selection.clear();
4433      },
4434
4435      valueToSelection: function(value) {
4436        var item = (value === null || value === undefined) ?
4437            null : this.items[this.valueToIndex(value)];
4438        this.$.selection.select(item);
4439      },
4440
4441      updateSelectedItem: function() {
4442        this.selectedItem = this.selection;
4443      },
4444
4445      selectedItemChanged: function() {
4446        if (this.selectedItem) {
4447          var t = this.selectedItem.templateInstance;
4448          this.selectedModel = t ? t.model : undefined;
4449        } else {
4450          this.selectedModel = null;
4451        }
4452        this.selectedIndex = this.selectedItem ?
4453            parseInt(this.valueToIndex(this.selected)) : -1;
4454      },
4455
4456      valueToIndex: function(value) {
4457        // find an item with value == value and return it's index
4458        for (var i=0, items=this.items, c; (c=items[i]); i++) {
4459          if (this.valueForNode(c) == value) {
4460            return i;
4461          }
4462        }
4463        // if no item found, the value itself is probably the index
4464        return value;
4465      },
4466
4467      valueForNode: function(node) {
4468        return node[this.valueattr] || node.getAttribute(this.valueattr);
4469      },
4470
4471      // events fired from <core-selection> object
4472      selectionSelect: function(e, detail) {
4473        this.updateSelectedItem();
4474        if (detail.item) {
4475          this.applySelection(detail.item, detail.isSelected);
4476        }
4477      },
4478
4479      applySelection: function(item, isSelected) {
4480        if (this.selectedClass) {
4481          item.classList.toggle(this.selectedClass, isSelected);
4482        }
4483        if (this.selectedProperty) {
4484          item[this.selectedProperty] = isSelected;
4485        }
4486        if (this.selectedAttribute && item.setAttribute) {
4487          if (isSelected) {
4488            item.setAttribute(this.selectedAttribute, '');
4489          } else {
4490            item.removeAttribute(this.selectedAttribute);
4491          }
4492        }
4493      },
4494
4495      // event fired from host
4496      activateHandler: function(e) {
4497        if (!this.notap) {
4498          var i = this.findDistributedTarget(e.target, this.items);
4499          if (i >= 0) {
4500            var item = this.items[i];
4501            var s = this.valueForNode(item) || i;
4502            if (this.multi) {
4503              if (this.selected) {
4504                this.addRemoveSelected(s);
4505              } else {
4506                this.selected = [s];
4507              }
4508            } else {
4509              this.selected = s;
4510            }
4511            this.asyncFire('core-activate', {item: item});
4512          }
4513        }
4514      },
4515
4516      addRemoveSelected: function(value) {
4517        var i = this.selected.indexOf(value);
4518        if (i >= 0) {
4519          this.selected.splice(i, 1);
4520        } else {
4521          this.selected.push(value);
4522        }
4523        this.valueToSelection(value);
4524      },
4525
4526      findDistributedTarget: function(target, nodes) {
4527        // find first ancestor of target (including itself) that
4528        // is in nodes, if any
4529        while (target && target != this) {
4530          var i = Array.prototype.indexOf.call(nodes, target);
4531          if (i >= 0) {
4532            return i;
4533          }
4534          target = target.parentNode;
4535        }
4536      }
4537    });
4538  ;
4539
4540  Polymer('core-menu',{});
4541;
4542
4543
4544  Polymer('core-item', {
4545
4546    /**
4547     * The URL of an image for the icon.
4548     *
4549     * @attribute src
4550     * @type string
4551     * @default ''
4552     */
4553
4554    /**
4555     * Specifies the icon from the Polymer icon set.
4556     *
4557     * @attribute icon
4558     * @type string
4559     * @default ''
4560     */
4561
4562    /**
4563     * Specifies the label for the menu item.
4564     *
4565     * @attribute label
4566     * @type string
4567     * @default ''
4568     */
4569
4570  });
4571
4572;
4573
4574
4575    Polymer('core-doc-toc', {
4576
4577      searchAction: function() {
4578        this.$.searchBar.style.opacity = 1;
4579        this.$.searchBar.style.display = '';
4580      },
4581
4582      closeSearchAction: function() {
4583        this.$.searchBar.style.opacity = 0;
4584        this.$.searchBar.style.display = 'none';
4585      }
4586
4587    });
4588
4589  ;
4590
4591
4592    Polymer('core-doc-viewer', {
4593      /**
4594       * A single file to parse for docs
4595       *
4596       * @attribute url
4597       * @type String
4598       * @default ''
4599       */
4600
4601      /**
4602       * Class documentation extracted from the parser
4603       *
4604       * @property classes
4605       * @type Array
4606       * @default []
4607       */
4608      classes: [],
4609
4610      /**
4611       * Files to parse for docs
4612       *
4613       * @attribute sources
4614       * @type Array
4615       * @default []
4616       */
4617      sources: [],
4618
4619      ready: function() {
4620        window.addEventListener('hashchange', this.parseLocationHash.bind(this));
4621        this.parseLocationHash();
4622      },
4623
4624      parseLocationHash: function() {
4625        this.route = window.location.hash.slice(1);
4626      },
4627
4628      routeChanged: function() {
4629        this.validateRoute();
4630      },
4631
4632      validateRoute: function() {
4633        if (this.route) {
4634          this.classes.some(function(c) {
4635            if (c.name === this.route) {
4636              this.data = c;
4637              this.route = '';
4638              return;
4639            }
4640          }, this);
4641        }
4642      },
4643
4644      selectedChanged: function() {
4645        this.data = this.classes[this.selected];
4646      },
4647
4648      parserDataReady: function(event) {
4649        this.assimilateData(event.target.data);
4650      },
4651
4652      assimilateData: function(data) {
4653        this.classes = this.classes.concat(data.classes);
4654        this.classes.sort(function(a, b) {
4655          var na = a && a.name.toLowerCase(), nb = b && b.name.toLowerCase();
4656          return (na < nb) ? -1 : (na == nb) ? 0 : 1;
4657        });
4658        if (!this.data && !this.route && this.classes.length) {
4659          this.data = this.classes[0];
4660        }
4661        if (this.classes.length > 1) {
4662          this.$.toc.style.display = 'block';
4663        }
4664        this.validateRoute();
4665      }
4666
4667    });
4668
4669  ;
4670
4671
4672    Polymer('core-component-page', {
4673
4674      moduleName: '',
4675      // TODO(sjmiles): needed this to force Object type for deserialization
4676      sources: [],
4677
4678      ready: function() {
4679        this.moduleName = this.moduleName || this.findModuleName();
4680      },
4681
4682      moduleNameChanged: function() {
4683        document.title = this.moduleName;
4684        this.url = !this.sources.length && this.moduleName ? this.moduleName + '.html' : '';
4685      },
4686
4687      findModuleName: function() {
4688        var path = location.pathname.split('/');
4689        var name = path.pop() || path.pop();
4690        if (name.indexOf('.html') >= 0) {
4691          name = path.pop();
4692        }
4693        return name || '';
4694      }
4695
4696    });
4697
4698