npm-polymer-elements
Version:
Polymer Elements package for npm
270 lines (229 loc) • 10.2 kB
HTML
<!--
@license
Copyright (c) 2015 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<link rel="import" href="../polymer/polymer.html">
<link rel="import" href="../marked-element/marked-element.html">
<link rel="import" href="../paper-button/paper-button.html">
<link rel="import" href="../paper-styles/color.html">
<link rel="import" href="../paper-styles/shadow.html">
<link rel="import" href="../paper-styles/typography.html">
<link rel="import" href="../prism-element/prism-highlighter.html">
<link rel="import" href="iron-doc-property.html">
<link rel="import" href="iron-doc-viewer-styles.html">
<!--
Renders documentation describing an element's API.
`iron-doc-viewer` renders element and behavior descriptions as extracted by
[Hydrolysis](https://github.com/PolymerLabs/hydrolysis). You can provide them
either via binding...
<iron-doc-viewer descriptor="{{elementDescriptor}}"></iron-doc-viewer>
...or by placing the element descriptor in JSON as the text content of an
`iron-doc-viewer`:
<iron-doc-viewer>
{
"is": "awesome-sauce",
"properties": [
{"name": "isAwesome", "type": "boolean", "desc": "Is it awesome?"},
]
}
</iron-doc-viewer>
However, be aware that due to current limitations in Polymer 0.8, _changes_ to
the text content will not be respected, only the initial value will be loaded.
If you wish to update the documented element, please set it via the `descriptor`
property.
@demo demo/index.html Basic Demo
-->
<dom-module id="iron-doc-viewer">
<template>
<style include="iron-doc-viewer-styles"></style>
<prism-highlighter></prism-highlighter>
<section id="summary" class="card" hidden$="[[!descriptor.desc]]">
<marked-element markdown="{{descriptor.desc}}">
<div class="markdown-html"></div>
</marked-element>
</section>
<nav id="api">
<header>API Reference</header>
<paper-button id="togglePrivate"
on-tap="_togglePrivate">{{_privateToggleLabel}}</paper-button>
</nav>
<section id="[[_formatAnchor(prefix,'properties')]]" class="card" hidden$="{{_noneToShow(_showPrivate,_properties)}}">
<header><a href="#[[_formatAnchor(prefix,'properties')]]" class="deeplink">Properties</a></header>
<template is="dom-repeat" items="{{_properties}}" hidden$="{{!_properties.length}}">
<iron-doc-property anchor-id="[[_formatAnchor(prefix,'property',item.name)]]" descriptor="{{item}}"></iron-doc-property>
</template>
</section>
<section id="[[_formatAnchor(prefix,'methods')]]" class="card" hidden$="{{_noneToShow(_showPrivate,_methods)}}">
<header><a href="#[[_formatAnchor(prefix,'methods')]]" class="deeplink">Methods</a></header>
<template is="dom-repeat" items="{{_methods}}">
<iron-doc-property anchor-id="[[_formatAnchor(prefix,'method',item.name)]]" descriptor="{{item}}"></iron-doc-property>
</template>
</section>
<section id="[[_formatAnchor(prefix,'events')]]" class="card" hidden$="{{_noneToShow(_showPrivate,_events)}}">
<header><a href="#[[_formatAnchor(prefix,'events')]" class="deeplink">Events</a></header>
<template is="dom-repeat" items="{{_events}}">
<iron-doc-property anchor-id="[[_formatAnchor(prefix,'event',item.name)]]" descriptor="{{item}}"></iron-doc-property>
</template>
</section>
<section id="[[_formatAnchor(prefix,'behaviors')]]" class="card" hidden$="{{_hideBehaviors(_behaviors)}}">
<header><a href="#[[_formatAnchor(prefix,'behaviors')]]" class="deeplink">Behaviors</a></header>
<template is="dom-repeat" items="{{_behaviors}}">
<p on-click="_broadcastBehavior">{{item}}</p>
</template>
</section>
</template>
<script>
(function() {
Polymer({
is: 'iron-doc-viewer',
properties: {
/**
* The [Hydrolysis](https://github.com/PolymerLabs/hydrolysis)-generated
* element descriptor to display details for.
*
* Alternatively, the element descriptor can be provided as JSON via the text content
* of this element.
*
* @type {hydrolysis.ElementDescriptor}
*/
descriptor: {
type: Object,
observer: '_descriptorChanged',
},
/**
* Prefix for fragment identifiers used in anchors.
* For static routing `iron-component-page` can
* set this to a string identifying the current component.
*/
prefix: {
type: String,
value: ''
},
/** Whether private properties should be hidden or shown. */
_showPrivate: {
type: Boolean,
value: false,
observer: '_showPrivateChanged',
},
/** The label to show for the Private API toggle. */
_privateToggleLabel: String,
/**
* Broadcast when another component is clicked on
* @param {String} detail name of the component
* iron-doc-viewer container should load component if possible
* @event iron-doc-viewer-component-selected
*/
},
ready: function() {
var jsonDescriptor = this._loadJson();
// Note that this is only an error during element creation. You are free
// to stomp over the descriptor after it is ready.
if (jsonDescriptor && this.descriptor) {
console.error(
this,
'received both a bound descriptor:', this.descriptor,
'and JSON descriptor:', this._jsonDescriptor,
'Please provide only one');
throw new Error(
'<iron-doc-viewer> accepts either a bound or JSON descriptor; not both');
}
if (jsonDescriptor) {
this.descriptor = jsonDescriptor;
}
},
/**
* Loads a hydrolysis element descriptor (as JSON) from the text content of
* this element, if present.
*
* @return {hydrolysis.ElementDescriptor} The parsed descriptor, or `null`.
*/
_loadJson: function() {
var textContent = '';
Array.prototype.forEach.call(Polymer.dom(this).childNodes, function(node) {
textContent = textContent + node.textContent;
});
textContent = textContent.trim();
if (textContent === '') return null;
try {
return JSON.parse(textContent);
} catch(error) {
console.error('Failure when parsing JSON:', textContent, error);
throw error;
}
},
/** Converts `descriptor` into our template-friendly `_model`. */
_descriptorChanged: function() {
if (!this.descriptor) return;
// Split the documented properties between functions and other types.
var properties = [];
var methods = [];
for (var i = 0, property; property = this.descriptor.properties[i]; i++) {
(property.type === 'Function' ? methods : properties).push(property);
}
this._properties = properties;
this._methods = methods;
this._events = this.descriptor.events || [];
this._behaviors = this.descriptor.behaviors || [];
this.toggleAttribute('abstract', this.descriptor.abstract);
},
/**
* Scrolls to the currently selected anchor, as identified
* by the URL hash. Whichever element or script is in charge
* of routing should call this method on initial page load and
* on hashchange events.
*/
scrollToAnchor: function(hash) {
// ToDo: handle linking to private members
if (hash && hash.length > 1) {
// ensure all dom-repeats have rendered.
Polymer.dom.flush();
var anchorId = window.location.hash.slice(1);
var elementToFocus = this.$$('[anchor-id="' + anchorId + '"]');
if (elementToFocus) {
elementToFocus.scrollIntoView();
}
}
},
_collapsedChanged: function() {
this._collapseToggleLabel = this._collapsed ? 'expand' : 'collapse';
// Bound values aren't exposed to dom-repeat's scope.
var properties = this.querySelectorAll('iron-doc-property');
for (var i = 0, property; property = properties[i]; i++) {
property.collapsed = this._collapsed;
}
},
_toggleCollapsed: function() {
this._collapsed = !this._collapsed;
},
_showPrivateChanged: function() {
this._privateToggleLabel = (this._showPrivate ? 'hide' : 'show') + ' private API';
this.toggleClass('show-private', this._showPrivate);
},
_togglePrivate: function() {
this._showPrivate = !this._showPrivate;
},
_noneToShow: function(showPrivate, items) {
for (var i = 0; i < items.length; i++) {
if (showPrivate || !items[i].private) return false;
}
return true;
},
_formatAnchor: function(prefix, type, membername) {
var suffix = membername ? '-' + membername : '';
return prefix + type + suffix;
},
_hideBehaviors: function(behaviors) {
return behaviors === null || behaviors.length === 0;
},
_broadcastBehavior: function(ev) {
this.fire('iron-doc-viewer-component-selected', ev.target._templateInstance.item);
}
});
})();
</script>
</dom-module>