/** * @license * Copyright (c) 2014 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 */ (function(scope) { var ContextFreeParser = { parse: function(text) { var top = {}; var entities = []; var current = top; var subCurrent = {}; var scriptDocCommentClause = '\\/\\*\\*([\\s\\S]*?)\\*\\/'; var htmlDocCommentClause = ''; // matches text between /** and */ inclusive and inclusive var docCommentRegex = new RegExp(scriptDocCommentClause + '|' + htmlDocCommentClause, 'g'); // acquire all script doc comments var docComments = text.match(docCommentRegex) || []; // each match represents a single block of doc comments docComments.forEach(function(m) { // unify line ends, remove all comment characters, split into individual lines var lines = m.replace(/\r\n/g, '\n').replace(/^\s*\/\*\*|^\s*\*\/|^\s*\* ?|^\s*\<\!-\-|^s*\-\-\>/gm, '').split('\n'); // pragmas (@-rules) must occur on a line by themselves var pragmas = []; // filter lines whose first non-whitespace character is @ into the pragma list // (and out of the `lines` array) lines = lines.filter(function(l) { var m = l.match(/\s*@([\w-]*) (.*)/); if (!m) { return true; } pragmas.push(m); }); // collect all other text into a single block var code = lines.join('\n'); // process pragmas pragmas.forEach(function(m) { var pragma = m[1], content = m[2]; switch (pragma) { // currently all entities are either @class or @element case 'class': case 'element': current = { name: content, description: code }; entities.push(current); break; // an entity may have these describable sub-features case 'attribute': case 'property': case 'method': case 'event': subCurrent = { name: content, description: code }; var label = pragma == 'property' ? 'properties' : pragma + 's'; makePragma(current, label, subCurrent); break; // sub-feature pragmas case 'default': case 'type': subCurrent[pragma] = content; break; case 'param': var eventParmsRe = /\{(.+)\}\s+(\w+[.\w+]+)\s+(.*)$/; var params = content.match(eventParmsRe); if (params) { var subEventObj = { type: params[1], name: params[2], description: params[3] }; makePragma(subCurrent, pragma + 's', subEventObj); } break; case 'extends': case 'mixins': var parts = content.split(' '); var subObj = { name: parts[0], url: parts[1] || null }; makePragma(current, pragma, subObj); break; case 'return': var returnRe = /\{(.+)\}\s+(.*)$/; var returnReResult = content.match(returnRe); if (returnReResult) { var subReturnObj = { type: returnReResult[1], description: returnReResult[2] }; subCurrent[pragma] = subReturnObj; } break; // everything else default: current[pragma] = content; break; } }); // utility function, yay hoisting function makePragma(object, pragma, content) { var p$ = object; var p = p$[pragma]; if (!p) { p$[pragma] = p = []; } p.push(content); } }); if (entities.length === 0) { entities.push({name: 'Entity', description: '**Undocumented**'}); } return entities; } }; if (typeof module !== 'undefined' && module.exports) { module.exports = ContextFreeParser; } else { scope.ContextFreeParser = ContextFreeParser; } })(this);