Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(96)

Unified Diff: third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js

Issue 1082403004: Import Polymer 0.8 and several key elements. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Also remove polymer/explainer Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js
diff --git a/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js
new file mode 100644
index 0000000000000000000000000000000000000000..f69af1855e5f7e4a317c54865f9bc0d41933340b
--- /dev/null
+++ b/third_party/polymer/v0_8/components-chromium/polymer/src/lib/annotations/annotations-extracted.js
@@ -0,0 +1,318 @@
+
+/**
+ * Scans a template to produce an annotation list that that associates
+ * metadata culled from markup with tree locations
+ * metadata and information to associate the metadata with nodes in an instance.
+ *
+ * Supported expressions include:
+ *
+ * Double-mustache annotations in text content. The annotation must be the only
+ * content in the tag, compound expressions are not supported.
+ *
+ * <[tag]>{{annotation}}<[tag]>
+ *
+ * Double-escaped annotations in an attribute, either {{}} or [[]].
+ *
+ * <[tag] someAttribute="{{annotation}}" another="[[annotation]]"><[tag]>
+ *
+ * `on-` style event declarations.
+ *
+ * <[tag] on-<event-name>="annotation"><[tag]>
+ *
+ * Note that the `annotations` feature does not implement any behaviors
+ * associated with these expressions, it only captures the data.
+ *
+ * Generated data-structure:
+ *
+ * [
+ * {
+ * id: '<id>',
+ * events: [
+ * {
+ * name: '<name>'
+ * value: '<annotation>'
+ * }, ...
+ * ],
+ * bindings: [
+ * {
+ * kind: ['text'|'attribute'],
+ * mode: ['{'|'['],
+ * name: '<name>'
+ * value: '<annotation>'
+ * }, ...
+ * ],
+ * // TODO(sjmiles): this is annotation-parent, not node-parent
+ * parent: <reference to parent annotation object>,
+ * index: <integer index in parent's childNodes collection>
+ * },
+ * ...
+ * ]
+ *
+ * @class Template feature
+ */
+
+ // null-array (shared empty array to avoid null-checks)
+ Polymer.nar = [];
+
+ Polymer.Annotations = {
+
+ // preprocess-time
+
+ // construct and return a list of annotation records
+ // by scanning `template`'s content
+ //
+ parseAnnotations: function(template) {
+ var list = [];
+ var content = template._content || template.content;
+ this._parseNodeAnnotations(content, list);
+ return list;
+ },
+
+ // add annotations gleaned from subtree at `node` to `list`
+ _parseNodeAnnotations: function(node, list) {
+ return node.nodeType === Node.TEXT_NODE ?
+ this._parseTextNodeAnnotation(node, list) :
+ // TODO(sjmiles): are there other nodes we may encounter
+ // that are not TEXT_NODE but also not ELEMENT?
+ this._parseElementAnnotations(node, list);
+ },
+
+ // add annotations gleaned from TextNode `node` to `list`
+ _parseTextNodeAnnotation: function(node, list) {
+ var v = node.textContent, escape = v.slice(0, 2);
+ if (escape === '{{' || escape === '[[') {
+ // NOTE: use a space here so the textNode remains; some browsers
+ // (IE) evacipate an empty textNode.
+ node.textContent = ' ';
+ var annote = {
+ bindings: [{
+ kind: 'text',
+ mode: escape[0],
+ value: v.slice(2, -2)
+ }]
+ };
+ list.push(annote);
+ return annote;
+ }
+ },
+
+ // add annotations gleaned from Element `node` to `list`
+ _parseElementAnnotations: function(element, list) {
+ var annote = {
+ bindings: [],
+ events: []
+ };
+ this._parseChildNodesAnnotations(element, annote, list);
+ // TODO(sjmiles): is this for non-ELEMENT nodes? If so, we should
+ // change the contract of this method, or filter these out above.
+ if (element.attributes) {
+ this._parseNodeAttributeAnnotations(element, annote, list);
+ // TODO(sorvell): ad hoc callback for doing work on elements while
+ // leveraging annotator's tree walk.
+ // Consider adding an node callback registry and moving specific
+ // processing out of this module.
+ if (this.prepElement) {
+ this.prepElement(element);
+ }
+ }
+ if (annote.bindings.length || annote.events.length || annote.id) {
+ list.push(annote);
+ }
+ return annote;
+ },
+
+ // add annotations gleaned from children of `root` to `list`, `root`'s
+ // `annote` is supplied as it is the annote.parent of added annotations
+ _parseChildNodesAnnotations: function(root, annote, list, callback) {
+ if (root.firstChild) {
+ for (var i=0, node=root.firstChild; node; node=node.nextSibling, i++){
+ if (node.localName === 'template' &&
+ !node.hasAttribute('preserve-content')) {
+ this._parseTemplate(node, i, list, annote);
+ }
+ //
+ var childAnnotation = this._parseNodeAnnotations(node, list, callback);
+ if (childAnnotation) {
+ childAnnotation.parent = annote;
+ childAnnotation.index = i;
+ }
+ }
+ }
+ },
+
+ // 1. Parse annotations from the template and memoize them on
+ // content._notes (recurses into nested templates)
+ // 2. Parse template bindings for parent.* properties and memoize them on
+ // content._parentProps
+ // 3. Create bindings in current scope's annotation list to template for
+ // parent props found in template
+ // 4. Remove template.content and store it in annotation list, where it
+ // will be the responsibility of the host to set it back to the template
+ // (this is both an optimization to avoid re-stamping nested template
+ // children and avoids a bug in Chrome where nested template children
+ // upgrade)
+ _parseTemplate: function(node, index, list, parent) {
+ // TODO(sjmiles): simply altering the .content reference didn't
+ // work (there was some confusion, might need verification)
+ var content = document.createDocumentFragment();
+ content._notes = this.parseAnnotations(node);
+ content.appendChild(node.content);
+ // Special-case treatment of 'parent.*' props for nested templates
+ // Automatically bind `prop` on host to `_parent_prop` on template
+ // for any `parent.prop`'s encountered in template binding; it is
+ // responsibility of the template implementation to forward
+ // these properties as appropriate
+ var bindings = [];
+ this._discoverTemplateParentProps(content);
+ for (var prop in content._parentProps) {
+ bindings.push({
+ index: index,
+ kind: 'property',
+ mode: '{',
+ name: '_parent_' + prop,
+ value: prop
+ });
+ }
+ // TODO(sjmiles): using `nar` to avoid unnecessary allocation;
+ // in general the handling of these arrays needs some cleanup
+ // in this module
+ list.push({
+ bindings: bindings,
+ events: Polymer.nar,
+ templateContent: content,
+ parent: parent,
+ index: index
+ });
+ },
+
+ // Finds all parent.* properties in template content and stores
+ // the path members in content._parentPropChain, which is an array
+ // of maps listing the properties of parent templates required at
+ // each level. Each outer template merges inner _parentPropChains to
+ // propagate inner parent property needs to outer templates.
+ // The top-level parent props from the chain (corresponding to this
+ // template) are stored in content._parentProps.
+ _discoverTemplateParentProps: function(content) {
+ var chain = content._parentPropChain = [];
+ content._notes.forEach(function(n) {
+ // Find all bindings to parent.* and spread them into _parentPropChain
+ n.bindings.forEach(function(b) {
+ var m;
+ if (m = b.value.match(/parent\.((parent\.)*[^.]*)/)) {
+ var parts = m[1].split('.');
+ for (var i=0; i<parts.length; i++) {
+ var pp = chain[i] || (chain[i] = {});
+ pp[parts[i]] = true;
+ }
+ }
+ });
+ // Merge child _parentPropChain[n+1] into this _parentPropChain[n]
+ if (n.templateContent) {
+ var tpp = n.templateContent._parentPropChain;
+ for (var i=1; i<tpp.length; i++) {
+ if (tpp[i]) {
+ var pp = chain[i-1] || (chain[i-1] = {});
+ Polymer.Base.simpleMixin(pp, tpp[i]);
+ }
+ }
+ }
+ });
+ // Store this template's parentProps map
+ content._parentProps = chain[0];
+ },
+
+ // add annotation data from attributes to the `annotation` for node `node`
+ // TODO(sjmiles): the distinction between an `annotation` and
+ // `annotation data` is not as clear as it could be
+ // Walk attributes backwards, since removeAttribute can be vetoed by
+ // IE in certain cases (e.g. <input value="foo">), resulting in the
+ // attribute staying in the attributes list
+ _parseNodeAttributeAnnotations: function(node, annotation) {
+ for (var i=node.attributes.length-1, a; (a=node.attributes[i]); i--) {
+ var n = a.name, v = a.value;
+ // id
+ if (n === 'id') {
+ annotation.id = v;
+ }
+ // events (on-*)
+ else if (n.slice(0, 3) === 'on-') {
+ node.removeAttribute(n);
+ annotation.events.push({
+ name: n.slice(3),
+ value: v
+ });
+ }
+ // bindings (other attributes)
+ else {
+ var b = this._parseNodeAttributeAnnotation(node, n, v);
+ if (b) {
+ annotation.bindings.push(b);
+ }
+ }
+ }
+ },
+
+ // construct annotation data from a generic attribute, or undefined
+ _parseNodeAttributeAnnotation: function(node, n, v) {
+ var mode = '', escape = v.slice(0, 2), name = n;
+ if (escape === '{{' || escape === '[[') {
+ // Mode (one-way or two)
+ mode = escape[0];
+ v = v.slice(2, -2);
+ // Negate
+ var not = false;
+ if (v[0] == '!') {
+ v = v.substring(1);
+ not = true;
+ }
+ // Attribute or property
+ var kind = 'property';
+ if (n[n.length-1] == '$') {
+ name = n.slice(0, -1);
+ kind = 'attribute';
+ }
+ // Custom notification event
+ var notifyEvent, colon;
+ if (mode == '{' && (colon = v.indexOf('::')) > 0) {
+ notifyEvent = v.substring(colon + 2);
+ v = v.substring(0, colon);
+ }
+ // Remove annotation
+ node.removeAttribute(n);
+ // Case hackery: attributes are lower-case, but bind targets
+ // (properties) are case sensitive. Gambit is to map dash-case to
+ // camel-case: `foo-bar` becomes `fooBar`.
+ // Attribute bindings are excepted.
+ if (kind === 'property') {
+ name = Polymer.CaseMap.dashToCamelCase(name);
+ }
+ return {
+ kind: kind,
+ mode: mode,
+ name: name,
+ value: v,
+ negate: not,
+ event: notifyEvent
+ };
+ }
+ },
+
+ // instance-time
+
+ _localSubTree: function(node, host) {
+ return (node === host) ? node.childNodes :
+ (node.lightChildren || node.childNodes);
+ },
+
+ findAnnotatedNode: function(root, annote) {
+ // recursively ascend tree until we hit root
+ var parent = annote.parent &&
+ Polymer.Annotations.findAnnotatedNode(root, annote.parent);
+ // unwind the stack, returning the indexed node at each level
+ return !parent ? root :
+ Polymer.Annotations._localSubTree(parent, root)[annote.index];
+ }
+
+ };
+
+

Powered by Google App Engine
This is Rietveld 408576698