Skip to content

Commit

Permalink
Merge pull request #10 from PolymerLabs/element_metadata
Browse files Browse the repository at this point in the history
Element metadata parsing
  • Loading branch information
garlicnation committed Feb 19, 2015
2 parents e49f202 + aad30e3 commit 1a18973
Show file tree
Hide file tree
Showing 13 changed files with 842 additions and 63 deletions.
12 changes: 5 additions & 7 deletions bower.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
{
"name": "hydrolysis",
"private": true,
"dependencies": {
"devDependencies": {
"core-asset": "PolymerLabs/core-asset#master",
"fetch": "fetch#master",
"designer2": "PolymerLabs/designer2#master",
"polymer": "Polymer/polymer#0.8-preview",
"webcomponentsjs": "webcomponents/webcomponentsjs#master"
},
"devDependencies": {
"web-component-tester": "Polymer/web-component-tester#master"
"webcomponentsjs": "webcomponents/webcomponentsjs#master",
"web-component-tester": "*"
}
}
}
67 changes: 67 additions & 0 deletions demo/demo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<script src="../../webcomponentsjs/webcomponents-lite.js"></script>
<script src="../hydrolysis.js"></script>
<link rel="import" href="../../polymer/polymer.html">
<link rel="import" href="../../core-asset/core-asset.html">

</head>
<body>
<core-asset
id="play"
href="../../designer2/elements/designer-playground/designer-playground.html">
</core-asset>
<core-asset
id="select"
href="../../designer2/elements/designer-selection/designer-selection.html">
</core-asset>
<core-asset
id="stage"
href="../../designer2/elements/designer-stage/designer-stage.html">
</core-asset>
<script>
window.setTimeout(function(){
"use strict";
var textarea = document.querySelector("textarea");
var hyd = require('hydrolysis');
var play = document.querySelector("#play").content;
var select = document.querySelector("#select").content;
var stage = document.querySelector("#stage").content;
function displayMetadata(content) {
var parsed = hyd.importParse(content);
for (var i = 0; i < parsed.script.length; i++) {
var script = parsed.script[i];
var inline = true;
var src;
// Check for inline script.
for (var j = 0; j < script.attrs.length; j++) {
var attr = script.attrs[i];
if (attr.name == "src") {
inline = false;
src = attr.value;
}
}
var parsedJs;
if (inline) {
parsedJs = hyd.jsParse(script.childNodes[0].value);
document.body.innerHTML += "<pre>" + JSON.stringify(parsedJs, null, ' ') + "</pre>";
} else {
// var asset = document.createElement('core-asset');
// asset.href=src;
// asset.addEventListener('content-loaded', function(e) {
// debugger;
// })
// // body.appendChil
// parsedJs = hyd.jsParse()
}
}
}
displayMetadata(play);
displayMetadata(select);
displayMetadata(stage);
}, 1000);
</script>
</body>
</html>
10 changes: 10 additions & 0 deletions hydrolysis.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!--
@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
-->
<script src="hydrolysis.js"></script>
15 changes: 9 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@
* 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
*/
var importParse = require('./lib/importParse');
var jsParse = require('./lib/jsParse');
(function(context){
"use strict"
var importParse = require('./lib/importParse');
var jsParse = require('./lib/jsParse');

module.exports = {
importParse: importParse,
jsParse: jsParse
};
context.exports = {
importParse: importParse,
jsParse: jsParse
};
}(module))
157 changes: 157 additions & 0 deletions lib/elementFinder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
(function(context){
"use strict";
var estraverse = require('estraverse');
var findAlias = require('./findAlias');

var elementFinder = function elementFinder(){
/**
* The list of elements exported by each traversed script.
*/
var elements = [];

/**
* The element being built during a traversal;
*/
var element;

/**
* a set of special case properties. these should only be called
* when we know we're inside an element definition.
* @type {Object}
*/
var propertyHandlers = {
is: function(node) {
if (node.type == "Literal") {
element.is = node.value;
}
},
published: function(node) {
this.publish(node);
},
publish: function(node) {
if (node.type != "ObjectExpression") {
return undefined;
}
for (var i = 0; i < node.properties.length; i++) {
var property = node.properties[i];
var prop = {published: true};
prop.name = objectKeyToString(property.key);
if (property.leadingComments && property.leadingComments.length > 0) {
prop.desc = property.leadingComments[property.leadingComments.length - 1].value;
}
prop.type = objectKeyToString(property.value);
if (prop.type) {
element.properties.push(prop);
continue;
}
if (property.value.type != "ObjectExpression") {
throw {
message: "Cant determine name for property key.",
location: node.loc.start
};
}
/**
* Parse the expression inside a publish object block.
* publish: {
* key: {
* type: String,
* notify: true
* }
* }
*/
for (var j = 0; j < property.value.properties.length; j++) {
var publishArg = property.value.properties[j];
var publishKey = objectKeyToString(publishArg.key);
if (publishKey == "type") {
prop.type = objectKeyToString(publishArg.value);
if (!prop.type) {
throw {
message: "Invalid type in publish block.",
location: publishArg.loc.start
};
}
continue;
}
if (publishKey == "notify") {
var val = publishArg.value;
if (val.type != "Literal" || val.value === undefined) {
throw {
message: "Notify expects a conditional.",
location: publishArg.loc.start
};
}
prop.notify = val.value;
}
}
element.properties.push(prop);
}
}
};

function objectKeyToString(key) {
if (key.type == "Identifier") {
return key.name;
}
if (key.type == "Literal") {
return key.value;
}
}


var visitors = {
enterCallExpression: function enterCallExpression(node, parent) {
var callee = node.callee;
if (callee.type == "Identifier") {
if (callee.name == "Polymer") {
element = {};
}
}
},
leaveCallExpression: function leaveCallExpression(node, parent) {
var callee = node.callee;
if (callee.type == "Identifier") {
if (callee.name == "Polymer") {
if (element) {
elements.push(element);
element = undefined;
}
}
}
},
enterObjectExpression: function enterObjectExpression(node, parent) {
if (element && !element.properties) {
element.properties = [];
for (var i = 0; i < node.properties.length; i++) {
var prop = node.properties[i];
var name = objectKeyToString(prop.key);
console.log(name);
if (!name) {
throw {
message: "Cant determine name for property key.",
location: node.loc.start
};
}

if (name in propertyHandlers) {
propertyHandlers[name](prop.value);
continue;
}
var property = {};
property.name = name;
if (prop.leadingComments && prop.leadingComments.length > 0) {
property.desc = prop.leadingComments[prop.leadingComments.length - 1].value;
}
if (prop.value.type == "FunctionExpression") {
property.type = "Function";
}
element.properties.push(property);
}
return estraverse.VisitorOption.Skip;
}
}
};
return {visitors: visitors, elements: elements};
};

context.exports = elementFinder;
}(module));
4 changes: 2 additions & 2 deletions lib/findAlias.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
(function(context){
"use strict"
"use strict";
var findAlias = function findAlias(names, aliases, name) {
return aliases[names.indexOf(name)];
}
};

context.exports = findAlias;
}(module));
8 changes: 5 additions & 3 deletions lib/importParse.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
*/
(function(context){
"use strict"
"use strict";
var Parser = require('parse5').Parser;

function addNode(node, registry) {
Expand Down Expand Up @@ -37,10 +37,12 @@
*/
var importParse = function importParse(htmlString){
var parser = new Parser();
var doc;
try {
var doc = parser.parse(htmlString);
doc = parser.parse(htmlString);
} catch (err) {
debugger;
console.log(err);
return null;
}

var registry = {template: [], script: [], style: []};
Expand Down
38 changes: 23 additions & 15 deletions lib/jsParse.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,46 @@
* Finds and annotates the Polymer() and modulate() calls in javascript.
*/
(function(context){
"use strict"
'use strict';
var esprima = require('esprima');
var estraverse = require('estraverse');

var modulateFinder = require('./modulateFinder');
var elementFinder = require('./elementFinder');

function traverse(visitors) {
var visitor;
function traverse(visitorRegistries) {
var visitor, visitorFunc;
function applyVisitors(name, node, parent) {
var returnVal;
for (var i = 0; i < visitorRegistries.length; i++) {
if (name in visitorRegistries[i]) {
returnVal = visitorRegistries[i][name](node, parent);
if (returnVal) {
return returnVal;
}
}
}
}
return {
enter: function(node, parent) {
visitor = "enter" + node.type;
//console.log(visitor);
if (visitor in visitors) {
return visitors[visitor](node, parent);
}
return applyVisitors(visitor, node, parent);
},
leave: function(node, parent) {
visitor = "leave" + node.type;
//console.log(visitor);
if (visitor in visitors) {
return visitors[visitor](node, parent);
}
return applyVisitors(visitor, node, parent);
}
}
};
}

var jsParse = function jsParse(jsString){
var script = esprima.parse(jsString, {attachComment: true, comment: true, loc: true});
var moduleFinder = modulateFinder();
var v = moduleFinder.visitors;
estraverse.traverse(script, traverse(v));
return {modules: moduleFinder.modules, elements: []};
var elFinder = elementFinder();
var moduleVisitors = moduleFinder.visitors;
var elementVisitors = elFinder.visitors;
estraverse.traverse(script, traverse([moduleVisitors, elementVisitors]));
return {modules: moduleFinder.modules, elements: elFinder.elements};
};

context.exports = jsParse;
Expand Down
Loading

0 comments on commit 1a18973

Please sign in to comment.