├── .jshintrc ├── Changelog.md ├── LICENSE ├── README.md ├── defaultPlugins └── compositionViews.js ├── genDoc.js ├── index.js ├── jsdoc ├── README.md ├── all.min.js ├── all.min.js.map ├── data.json ├── index-dev.html ├── index.html ├── lib │ ├── backbone │ │ └── backbone.js │ ├── bootstrap-3.2.0-dist │ │ ├── css │ │ │ ├── bootstrap-theme.css │ │ │ ├── bootstrap-theme.css.map │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ └── bootstrap.min.css │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ └── glyphicons-halflings-regular.woff │ │ └── js │ │ │ ├── bootstrap.js │ │ │ └── bootstrap.min.js │ ├── jquery │ │ └── jquery-2.0.3.min.js │ ├── marked │ │ └── marked.js │ ├── prettify │ │ ├── prettify.css │ │ └── prettify.js │ ├── toast │ │ └── toast.min.js │ ├── twitter-typeahead │ │ └── typeahead.bundle.js │ └── vis │ │ └── dist │ │ ├── img │ │ ├── network │ │ │ ├── acceptDeleteIcon.png │ │ │ ├── addNodeIcon.png │ │ │ ├── backIcon.png │ │ │ ├── connectIcon.png │ │ │ ├── cross.png │ │ │ ├── cross2.png │ │ │ ├── deleteIcon.png │ │ │ ├── downArrow.png │ │ │ ├── editIcon.png │ │ │ ├── leftArrow.png │ │ │ ├── minus.png │ │ │ ├── plus.png │ │ │ ├── rightArrow.png │ │ │ ├── upArrow.png │ │ │ └── zoomExtends.png │ │ └── timeline │ │ │ └── delete.png │ │ ├── vis.css │ │ ├── vis.js │ │ ├── vis.map │ │ ├── vis.min.css │ │ └── vis.min.js ├── libs.min.js ├── libs.min.js.map ├── src │ ├── JsDocMaker_browser.js │ ├── js │ │ ├── AbstractTreeView.js │ │ ├── AbstractView.js │ │ ├── Application.js │ │ ├── ApplicationView.js │ │ ├── ClassView.js │ │ ├── DependenciesView.js │ │ ├── FileView.js │ │ ├── HeaderView.js │ │ ├── HierarchyTreeView.js │ │ ├── IndexView.js │ │ ├── JsDocRouter.js │ │ ├── MethodView.js │ │ ├── ModuleView.js │ │ ├── ParseView.js │ │ ├── PropertyView.js │ │ ├── SearchView.js │ │ ├── SourcesView.js │ │ ├── TreeView.js │ │ └── TypesUtil.js │ ├── styles │ │ ├── class.less │ │ ├── header.less │ │ ├── index.less │ │ ├── main-layout.less │ │ ├── main.less │ │ ├── module.less │ │ ├── parse.less │ │ ├── sources.less │ │ ├── styles.css │ │ ├── tree.less │ │ └── types.less │ └── templates │ │ ├── application.html │ │ ├── class.html │ │ ├── classSummary.html │ │ ├── classes.html │ │ ├── dependencies.html │ │ ├── file.html │ │ ├── header.html │ │ ├── hierarchytree.html │ │ ├── index.html │ │ ├── method.html │ │ ├── module.html │ │ ├── modules.html │ │ ├── parse.html │ │ ├── project-metadata.html │ │ ├── property.html │ │ ├── search.html │ │ ├── sources.html │ │ ├── tree.html │ │ └── typeaheadSuggestion.html └── template-output.js ├── lib ├── Adapters │ ├── incrementalDOMAdapter.js │ ├── reactAdapter.js │ └── virtualDOMAdapter.js ├── codeGenerator.Attributes.js ├── codeGenerator.Base.js ├── codeGenerator.CustomHelpers.js ├── codeGenerator.Tags.js ├── codeGenerator.Utils.js ├── codeGenerator.js └── hookContainer.js ├── package.json ├── spec ├── combinationHandlebarsHTMLSpec.js ├── simpleHTMLAttributesSpec.js ├── simpleHTMLTagsSpec.js ├── simpleHandlebarsAttributesSpec.js ├── simpleHandlebarsTagsSpec.js └── support │ └── jasmine.json └── status.txt /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // JSHint Default Configuration File (as on JSHint website) 3 | // See http://jshint.com/docs/ for more details 4 | 5 | "maxerr" : 100, // {int} Maximum error before stopping 6 | 7 | // Enforcing 8 | "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) 9 | "camelcase" : false, // true: Identifiers must be in camelCase 10 | "curly" : true, // true: Require {} for every new block or scope 11 | "eqeqeq" : true, // true: Require triple equals (===) for comparison 12 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() 13 | "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. 14 | "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` 15 | "indent" : 4, // {int} Number of spaces to use for indentation 16 | "latedef" : false, // true: Require variables/functions to be defined before being used 17 | "newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()` 18 | "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` 19 | "noempty" : true, // true: Prohibit use of empty blocks 20 | "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. 21 | "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) 22 | "plusplus" : false, // true: Prohibit use of `++` & `--` 23 | "quotmark" : "single", // Quotation mark consistency: 24 | // false : do nothing (default) 25 | // true : ensure whatever is used is consistent 26 | // "single" : require single quotes 27 | // "double" : require double quotes 28 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) 29 | "unused" : true, // Unused variables: 30 | // true : all variables, last function parameter 31 | // "vars" : all variables only 32 | // "strict" : all variables, all function parameters 33 | "strict" : true, // true: Requires all functions run in ES5 Strict Mode 34 | "maxparams" : false, // {int} Max number of formal params allowed per function 35 | "maxdepth" : false, // {int} Max depth of nested blocks (within functions) 36 | "maxstatements" : false, // {int} Max number statements per function 37 | "maxcomplexity" : false, // {int} Max cyclomatic complexity per function 38 | "maxlen" : false, // {int} Max number of characters per line 39 | 40 | // Relaxing 41 | "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) 42 | "boss" : false, // true: Tolerate assignments where comparisons would be expected 43 | "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. 44 | "eqnull" : false, // true: Tolerate use of `== null` 45 | "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) 46 | "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) 47 | "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) 48 | // (ex: `for each`, multiple try/catch, function expression…) 49 | "evil" : false, // true: Tolerate use of `eval` and `new Function()` 50 | "expr" : false, // true: Tolerate `ExpressionStatement` as Programs 51 | "funcscope" : false, // true: Tolerate defining variables inside control statements 52 | "globalstrict" : false, // true: Allow global "use strict" (also enables 'strict') 53 | "iterator" : false, // true: Tolerate using the `__iterator__` property 54 | "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block 55 | "laxbreak" : false, // true: Tolerate possibly unsafe line breakings 56 | "laxcomma" : true, // true: Tolerate comma-first style coding 57 | "loopfunc" : false, // true: Tolerate functions being defined in loops 58 | "multistr" : false, // true: Tolerate multi-line strings 59 | "noyield" : false, // true: Tolerate generator functions with no yield statement in them. 60 | "notypeof" : false, // true: Tolerate invalid typeof operator values 61 | "proto" : false, // true: Tolerate using the `__proto__` property 62 | "scripturl" : false, // true: Tolerate script-targeted URLs 63 | "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` 64 | "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation 65 | "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` 66 | "validthis" : false, // true: Tolerate using this in a non-constructor function 67 | 68 | // Environments 69 | "browser" : false, // Web Browser (window, document, etc) 70 | "browserify" : false, // Browserify (node.js code in the browser) 71 | "couch" : false, // CouchDB 72 | "devel" : true, // Development/debugging (alert, confirm, etc) 73 | "dojo" : false, // Dojo Toolkit 74 | "jasmine" : false, // Jasmine 75 | "jquery" : false, // jQuery 76 | "mocha" : true, // Mocha 77 | "mootools" : false, // MooTools 78 | "node" : true, // Node.js 79 | "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) 80 | "phantom" : false, // PhantomJS 81 | "prototypejs" : false, // Prototype and Scriptaculous 82 | "qunit" : false, // QUnit 83 | "rhino" : false, // Rhino 84 | "shelljs" : false, // ShellJS 85 | "typed" : false, // Globals for typed array constructions 86 | "worker" : false, // Web Workers 87 | "wsh" : false, // Windows Scripting Host 88 | "yui" : false, // Yahoo User Interface 89 | 90 | // Custom Globals 91 | "globals" : {} // additional predefined global variables 92 | } -------------------------------------------------------------------------------- /Changelog.md: -------------------------------------------------------------------------------- 1 | #Changelog 2 | 3 | ##Version 0.1.0 (14-09-2015) 4 | * Added Adapters 5 | * Added basic React adapter 6 | * Generated first iteration of auto-generated-documentation 7 | 8 | ##Version 0.0.3 (23-08-2015) 9 | * Publically exposed plugins 10 | * Added some Unit Tests 11 | 12 | ##Version 0.0.2 (22-08-2015) 13 | * Fixed README documentation 14 | * Fixed code documentation 15 | 16 | ##Version 0.0.1 (21-08-2015) 17 | * Initial Version 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Mictian 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blueHTML 2 | Simple [handlebar] to [virtual-dom] converter 3 | [handlebar]:http://handlebarsjs.com/ 4 | [virtual-dom]:https://github.com/Matt-Esch/virtual-dom 5 | 6 | ## Overview 7 | 8 | Simple converter from HTML/Handlebars templates into virtual-dom. 9 | 10 | PR Accepted (Specially Unit Tests :D ) 11 | 12 | ## API & Samples 13 | 14 | ```javascript 15 | var blueHTML = require('bluehtml') 16 | , h = require('virtual-dom/h') 17 | , _ = require("underscore") 18 | 19 | 20 | var template_string = '

{{title}}

{{mainContent}}
' 21 | , virtual_dom = blueHTML.generateVirtualDOM(template_string, {notGenerateContext:true}) 22 | , context = { 23 | title: 'Test Title', 24 | mainContent: 'Hello word' 25 | }; 26 | 27 | console.log(virtual_dom); 28 | 29 | var eval_fn = "var ctx = " + JSON.stringify(context) + ';' + virtual_dom; 30 | 31 | var virtual_dom_output = eval(eval_fn); 32 | console.log(virtual_dom_output); 33 | 34 | ``` 35 | 36 | ## Motivation 37 | I personally believe in the one-way data-flow pattern is an excellent way to model user interaction 38 | and I think that from an architectural point of view it has a lot of advantages. 39 | 40 | Besides, all the great development that have been done with Virtual DOM 41 | technologies is something that cannot be ignored. Perhaps you can like it not, 42 | but for a performance point of view I think that React have leave it crystal clear. 43 | 44 | Although all the previous, I do not want to re-write all my Handlebars templates 45 | to JavaScript (JSX, HyperScript or whatever flavor you want) nor I think that designers should start 46 | writing JavaScript instead of HTML templates. 47 | All this VirtualDOM technologies are great, but this does not mean that we must change the way 48 | we have been working on, by the contrary, we can enhance the way we used to work. 49 | Take for instance a Backbone.js application with Handlebars (the way I work), in this case Handlebars is not used 50 | as a final representation of the HTML, but rather as a friendly way the designer can work with it. 51 | You will process your Handlebars template obtaining an output, point at which you 52 | will neither use this output as a final representation, and wrap it with jQuery or any other equivalent. 53 | 54 | So, my point is that we can use any other intermediate representation for our templates, 55 | jQuery, VirtualDOM or the one you think is better, as long as we keep a clear separation 56 | between what the aim of each part is. 57 | 58 | ## Documentation 59 | For a general overview please refer to the [Wiki](https://github.com/Mictian/blueHTML/wiki/General-Documentation) and more technical one please refer to the code which is fully documented. 60 | 61 | 62 | ## Changelog 63 | Go [Here](https://github.com/Mictian/blueHTML/blob/master/Changelog.md) to see the list of changes. 64 | 65 | # Contributors 66 | * juansilva (https://github.com/juansilva) 67 | 68 | # License 69 | The MIT License (MIT) 70 | 71 | Copyright (c) 2015 Mictian 72 | 73 | Permission is hereby granted, free of charge, to any person obtaining a copy 74 | of this software and associated documentation files (the "Software"), to deal 75 | in the Software without restriction, including without limitation the rights 76 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 77 | copies of the Software, and to permit persons to whom the Software is 78 | furnished to do so, subject to the following conditions: 79 | 80 | The above copyright notice and this permission notice shall be included in all 81 | copies or substantial portions of the Software. 82 | 83 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 84 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 85 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 86 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 87 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 88 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 89 | SOFTWARE. 90 | -------------------------------------------------------------------------------- /defaultPlugins/compositionViews.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML.DefaultPlugins 2 | var _ = require('underscore'); 3 | 4 | //@class CompositeViewPlugin @extend Plugin This plugin allows to composite views by adding a data-view attribute inside the Handlebars template 5 | module.exports = { 6 | //@method install Public method invoked by blueHTML when adding a new plugin. 7 | //@param {CodeGenerator} codeGenerator 8 | //@return {Void} 9 | install: function (codeGenerator) 10 | { 11 | 'use strict'; 12 | 13 | this.accumulatedAttributesCompositeViewNames = []; 14 | this.compositeViewNames = []; 15 | this.lastAttributesResult = ''; 16 | this.externalDependencyVariableName = 'children_views_dependencies'; 17 | 18 | codeGenerator.beforeAttributeHandlerExecuted.add({ 19 | name: 'Recollect data-view values' 20 | , execute: this.beforeAttributeHandlerCalled 21 | , priority: 10 22 | , self: this 23 | }); 24 | 25 | codeGenerator.afterAttributeCodeGeneration.add({ 26 | execute: this.augmentNodeChildrenForCompositeViews 27 | , name: 'Insert AST dataView nodes' 28 | , priority: 10 29 | , self: this 30 | }); 31 | 32 | codeGenerator.beforeAttributeCodeGeneration.add({ 33 | execute: this.cleanAttributeCompositeViews 34 | , name: 'Reset local state' 35 | , priority: 10 36 | , self: this 37 | }); 38 | 39 | codeGenerator.afterTagCodeGeneration.add({ 40 | execute: this.generateResult 41 | , name: 'Extend Generated code result' 42 | , priority: 10 43 | , self: this 44 | }); 45 | 46 | this.extensionMethods.pluginCompositeViewsContext = this; 47 | 48 | _.extend(codeGenerator.prototype, this.extensionMethods); 49 | }, 50 | 51 | //@method cleanAttributeCompositeViews 52 | //@return {Void} 53 | cleanAttributeCompositeViews: function () 54 | { 55 | 'use strict'; 56 | 57 | this.self.accumulatedAttributesCompositeViewNames = []; 58 | this.self.lastAttributesResult = ''; 59 | }, 60 | 61 | //@method generateResult Extend the final result to return the list of view named collected 62 | //@param {CodeGenerationResult} codeResult 63 | //@return {CodeGenerationResult} 64 | generateResult: function (codeResult) 65 | { 66 | codeResult.externalDependencies = codeResult.externalDependencies.concat(this.self.compositeViewNames); 67 | return codeResult; 68 | }, 69 | 70 | //@method beforeAttributeHandlerCalled Hook to accumulate data-view attributes 71 | //@param {AttributeASTNode} ast_node 72 | //@param {CodeGenerationContext} code_generation_context 73 | //@return {Void} 74 | beforeAttributeHandlerCalled: function (ast_node, code_generation_context) 75 | { 76 | 'use strict'; 77 | 78 | var self = this.self; 79 | 80 | if (ast_node.type === 'keyValue' && 'data-view' === ast_node.key) 81 | { 82 | var composite_view_name = '""'; 83 | 84 | //Generate view name (It can be compose by code invocation) 85 | _.each(ast_node.value, function (value_node) 86 | { 87 | if (value_node.type === 'singleValue' || 88 | (value_node.type === 'singleKey' && value_node.subType === 'extraSpaces' && value_node.value !== '')) 89 | { 90 | composite_view_name += '+"'+value_node.value+'"'; 91 | } 92 | else if (value_node.type === 'handlebars' && value_node.subType === 'ATTRREFERENCEEVALUATION') 93 | { 94 | var property_name = value_node.value.trim().substr(1); 95 | if (code_generation_context.currentContextName[property_name]) 96 | { 97 | composite_view_name += '+'+code_generation_context.currentContextName.contextName + '.' + property_name; 98 | } 99 | } 100 | }); 101 | 102 | self.accumulatedAttributesCompositeViewNames.push(composite_view_name); 103 | } 104 | }, 105 | 106 | //@method augmentNodeChildrenForCompositeViews Internal method to add for each NodeASTNode that has properties the can indicate that the node is a composite point 107 | // an extra child to express that composite point 108 | //@param {String} attributes_result 109 | //@param {CodeGenerationContext} code_generation_context 110 | //@return {Void} 111 | augmentNodeChildrenForCompositeViews: function (attributes_result, code_generation_context) 112 | { 113 | 'use strict'; 114 | 115 | var self = this.self 116 | , node_children = code_generation_context.astNode.children || []; 117 | 118 | _.each(self.accumulatedAttributesCompositeViewNames, function (require_composite_view) 119 | { 120 | node_children.push({ 121 | type: 'handlebars' 122 | , subType: 'CompositeView' 123 | , value: require_composite_view 124 | , parameters: attributes_result.value 125 | }); 126 | }); 127 | self.compositeViewNames = self.compositeViewNames.concat(self.accumulatedAttributesCompositeViewNames); 128 | 129 | code_generation_context.astNode.children = node_children; 130 | self.lastAttributesResult = attributes_result; 131 | }, 132 | 133 | extensionMethods: { 134 | 135 | //@method handlebarsCompositeView Handler for (extra added) composite nodes 136 | //@param {CodeGenerationContext} code_generation_context 137 | //@return {String} 138 | handlebarsCompositeView: function (code_generation_context) 139 | { 140 | 'use strict'; 141 | 142 | var self = this.pluginCompositeViewsContext; 143 | 144 | var invokable_fn = code_generation_context.externalDependenciesObjectName+'['+code_generation_context.astNode.value+']' 145 | , output_code = '' 146 | , generate_virtualdom = !!(code_generation_context.adapter && code_generation_context.adapter.name === 'VD') 147 | , generate_react = !!(code_generation_context.adapter && code_generation_context.adapter.name === 'R'); 148 | 149 | if (generate_virtualdom) 150 | { 151 | output_code = '(function (){ '+ 152 | 'if (_.isFunction('+invokable_fn+')) { return '+invokable_fn+'('+self.lastAttributesResult+'); }' + 153 | 'return []; })()'; 154 | } 155 | else if (generate_react) 156 | { 157 | output_code = '(function (){ '+ 158 | 'if (_.isFunction('+invokable_fn+')) { return React.createElement('+invokable_fn+'('+self.lastAttributesResult+'),null); }' + 159 | 'return []; })()'; 160 | } 161 | else 162 | { 163 | throw new Error('Composite Views Plugin is being used with an adapter that is not supported. Only VirtualDOM and React are supported by this plugin'); 164 | } 165 | 166 | if (code_generation_context.isInsideContext) 167 | { 168 | return code_generation_context.variableName + '=' + code_generation_context.variableName + '.concat('+output_code+');'; 169 | } 170 | 171 | return output_code; 172 | } 173 | } 174 | }; 175 | -------------------------------------------------------------------------------- /genDoc.js: -------------------------------------------------------------------------------- 1 | var ShortJsDoc = require('short-jsdoc') 2 | , rimraf = require('rimraf'); 3 | 4 | rimraf('./jsdoc/', function () 5 | { 6 | ShortJsDoc.make({ 7 | inputDirs: ['./lib', './index.js'] 8 | , output: 'jsdoc' 9 | , projectMetadata: './package.json' 10 | , vendor: [] 11 | }); 12 | }) 13 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML 2 | var codeGenerator = require('./lib/codeGenerator') 3 | , _ = require('underscore') 4 | , virtualDOMAdapter = require('./lib/Adapters/virtualDOMAdapter') 5 | , reactAdapter = require('./lib/Adapters/reactAdapter') 6 | , compositeViewPlugin = require('./defaultPlugins/compositionViews'); 7 | 8 | var local_parser = new codeGenerator() 9 | , defaultsAdapters = { 10 | 'VD': virtualDOMAdapter 11 | , 'R': reactAdapter 12 | }; 13 | 14 | //@class blueHTML 15 | module.exports = { 16 | //@property {CodeGenerator} codeGenerator 17 | codeGenerator: codeGenerator 18 | 19 | //@method generateVirtualDOM Shortcut method to easily start converting handlebarsX to virtual-dom 20 | //@param {String} string_html Handlebar HTML template 21 | //@param {VirtualDOMGenerationOptions} options List of option to configure the parsing process 22 | //@return {String} Final virtual-dom string code already wrapped in a functions 23 | , generateVirtualDOM: function (string_html, options) 24 | { 25 | 'use strict'; 26 | 27 | options = _.defaults(options || {}, { 28 | notGenerateContext: false 29 | , adapterName: 'VD' 30 | }); 31 | 32 | options.adapter = options.adapter || defaultsAdapters[options.adapterName]; 33 | 34 | var result = local_parser.generateCode(string_html, options); 35 | 36 | return result.value; 37 | } 38 | //@property {Object} defaultPlugins Each property of this object is of type Plugin 39 | , defaultPlugins: { 40 | 'compositeViews': compositeViewPlugin 41 | } 42 | //@property {Object} defaultsAdapters Each property of this object is of type Adapter 43 | , defaultsAdapters: defaultsAdapters 44 | //@method addCustomHandler Method used to define a new custom Handlebars Helper 45 | //@param {ExtenderCodeGeneratorObject} handlebars_custom_handlers 46 | //@return {Void} 47 | , addCustomHandler: local_parser.addCustomHandler 48 | //@method installPlugin Install a plugin inside the code generator 49 | //@param {Plugin} plugin_container 50 | //@return {Void} 51 | , installPlugin: local_parser.installPlugin 52 | }; 53 | 54 | 55 | // @class ExtenderCodeGeneratorObject Object used to extend any of the code generators. 56 | // In this object each property must be a function. Two kind of functions are supported: 57 | // * **Extension Functions**: These are functions that will take the parameters from the Code generator and output a string code. 58 | // This can be seen as a point to extend the code generator it self. 59 | // This functions are distinguish by the property name they are attached to. In this case the name MUST start with the word 'single' and MUST NOT be 'singleInstance' 60 | // Sample: 61 | // ```javascript 62 | // var blueHTML = require('blueHTML'); 63 | // blueHTML.addCustomHandler({ 64 | // 'singleTranslate': function (parsing_context, is_inside_context) 65 | // { 66 | // return 'h("div",[])'; 67 | // } 68 | // }); 69 | // ``` 70 | // In this sample, that function will be called each time that in the HTML code appears something like: 71 | 72 | // ```html 73 | // {{Translate 'some options'}} 74 | // ``` 75 | 76 | // Each function MUST fulfill the following signature: 77 | // **Function** where the output is string and the rest are the input parameter types. 78 | 79 | // For the previous codes, the output will be: 80 | // ```javascript 81 | // function render(ctx) 82 | // { 83 | // return h('span', {}, [h('div',[])]); 84 | // } 85 | // ``` 86 | 87 | // * **Helper Functions:** The second options are functions defined in almost the same way you define custom helpers in Handlebars. These functions are distinguish by the property name they are atteched to. In this case the name MUST start with the word 'singleInstance' 88 | 89 | // Sample: 90 | // ```javascript 91 | // var blueHTML = require('blueHTML'); 92 | // blueHTML.addCustomHandler({ 93 | // 'singleInstanceTranslate': function (string_key_to_translate) 94 | // { 95 | // return 'key not found :('; 96 | // } 97 | // }); 98 | // ``` 99 | // In this sample, that function will be called each time that in the HTML code appears something like: 100 | 101 | // ```html 102 | // {{Translate 'some options'}} 103 | // ``` 104 | 105 | // The big difference with previous functions is the signature. While extension function must have a rigid signature that will be called by the code generator, helper functions can have any signature. In the same way you did with Handlebars. 106 | 107 | // **Important Note:** 108 | // 1. As you can guess, this functions are prefixed with the word *single* as their aim is to handle single helpers. In order word, by the time being **generic block are not supported!!** 109 | // 2. The examples here applies to both Attributes and Tags 110 | 111 | -------------------------------------------------------------------------------- /jsdoc/README.md: -------------------------------------------------------------------------------- 1 | This is an html5 application generated by short-jsdoc that shows some project's jsdocs. 2 | 3 | The application is based on bootstrap, backbone, underscore templates, less. -------------------------------------------------------------------------------- /jsdoc/index-dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 70 | 71 | 72 | 73 | 74 | 75 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /jsdoc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /jsdoc/lib/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mictian/blueHTML/0036ff5b3e62662348e72a56831c327d4b77e38b/jsdoc/lib/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /jsdoc/lib/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mictian/blueHTML/0036ff5b3e62662348e72a56831c327d4b77e38b/jsdoc/lib/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /jsdoc/lib/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mictian/blueHTML/0036ff5b3e62662348e72a56831c327d4b77e38b/jsdoc/lib/bootstrap-3.2.0-dist/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /jsdoc/lib/prettify/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /jsdoc/lib/prettify/prettify.js: -------------------------------------------------------------------------------- 1 | !function(){var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; 2 | (function(){function S(a){function d(e){var b=e.charCodeAt(0);if(b!==92)return b;var a=e.charAt(1);return(b=r[a])?b:"0"<=a&&a<="7"?parseInt(e.substring(1),8):a==="u"||a==="x"?parseInt(e.substring(2),16):e.charCodeAt(1)}function g(e){if(e<32)return(e<16?"\\x0":"\\x")+e.toString(16);e=String.fromCharCode(e);return e==="\\"||e==="-"||e==="]"||e==="^"?"\\"+e:e}function b(e){var b=e.substring(1,e.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),e=[],a= 3 | b[0]==="^",c=["["];a&&c.push("^");for(var a=a?1:0,f=b.length;a122||(l<65||h>90||e.push([Math.max(65,h)|32,Math.min(l,90)|32]),l<97||h>122||e.push([Math.max(97,h)&-33,Math.min(l,122)&-33]))}}e.sort(function(e,a){return e[0]-a[0]||a[1]-e[1]});b=[];f=[];for(a=0;ah[0]&&(h[1]+1>h[0]&&c.push("-"),c.push(g(h[1])));c.push("]");return c.join("")}function s(e){for(var a=e.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),c=a.length,d=[],f=0,h=0;f=2&&e==="["?a[f]=b(l):e!=="\\"&&(a[f]=l.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return a.join("")}for(var x=0,m=!1,j=!1,k=0,c=a.length;k=5&&"lang-"===w.substring(0,5))&&!(t&&typeof t[1]==="string"))f=!1,w="src";f||(r[z]=w)}h=c;c+=z.length;if(f){f=t[1];var l=z.indexOf(f),B=l+f.length;t[2]&&(B=z.length-t[2].length,l=B-f.length);w=w.substring(5);H(j+h,z.substring(0,l),g,k);H(j+h+l,f,I(w,f),k);H(j+h+B,z.substring(B),g,k)}else k.push(j+h,w)}a.g=k}var b={},s;(function(){for(var g=a.concat(d),j=[],k={},c=0,i=g.length;c=0;)b[n.charAt(e)]=r;r=r[1];n=""+r;k.hasOwnProperty(n)||(j.push(r),k[n]=q)}j.push(/[\S\s]/);s=S(j)})();var x=d.length;return g}function v(a){var d=[],g=[];a.tripleQuotedStrings?d.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?d.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, 10 | q,"'\"`"]):d.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&g.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var b=a.hashComments;b&&(a.cStyleComments?(b>1?d.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):d.push(["com",/^#(?:(?:define|e(?:l|nd)if|else|error|ifn?def|include|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),g.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h(?:h|pp|\+\+)?|[a-z]\w*)>/,q])):d.push(["com", 11 | /^#[^\n\r]*/,q,"#"]));a.cStyleComments&&(g.push(["com",/^\/\/[^\n\r]*/,q]),g.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));if(b=a.regexLiterals){var s=(b=b>1?"":"\n\r")?".":"[\\S\\s]";g.push(["lang-regex",RegExp("^(?:^^\\.?|[+-]|[!=]=?=?|\\#|%=?|&&?=?|\\(|\\*=?|[+\\-]=|->|\\/=?|::?|<>?>?=?|,|;|\\?|@|\\[|~|{|\\^\\^?=?|\\|\\|?=?|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*("+("/(?=[^/*"+b+"])(?:[^/\\x5B\\x5C"+b+"]|\\x5C"+s+"|\\x5B(?:[^\\x5C\\x5D"+b+"]|\\x5C"+ 12 | s+")*(?:\\x5D|$))+/")+")")])}(b=a.types)&&g.push(["typ",b]);b=(""+a.keywords).replace(/^ | $/g,"");b.length&&g.push(["kwd",RegExp("^(?:"+b.replace(/[\s,]+/g,"|")+")\\b"),q]);d.push(["pln",/^\s+/,q," \r\n\t\u00a0"]);b="^.[^\\s\\w.$@'\"`/\\\\]*";a.regexLiterals&&(b+="(?!s*/)");g.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/, 13 | q],["pun",RegExp(b),q]);return C(d,g)}function J(a,d,g){function b(a){var c=a.nodeType;if(c==1&&!x.test(a.className))if("br"===a.nodeName)s(a),a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)b(a);else if((c==3||c==4)&&g){var d=a.nodeValue,i=d.match(m);if(i)c=d.substring(0,i.index),a.nodeValue=c,(d=d.substring(i.index+i[0].length))&&a.parentNode.insertBefore(j.createTextNode(d),a.nextSibling),s(a),c||a.parentNode.removeChild(a)}}function s(a){function b(a,c){var d= 14 | c?a.cloneNode(!1):a,e=a.parentNode;if(e){var e=b(e,1),g=a.nextSibling;e.appendChild(d);for(var i=g;i;i=g)g=i.nextSibling,e.appendChild(i)}return d}for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),d;(d=a.parentNode)&&d.nodeType===1;)a=d;c.push(a)}for(var x=/(?:^|\s)nocode(?:\s|$)/,m=/\r\n?|\n/,j=a.ownerDocument,k=j.createElement("li");a.firstChild;)k.appendChild(a.firstChild);for(var c=[k],i=0;i=0;){var b=d[g];F.hasOwnProperty(b)?D.console&&console.warn("cannot override language handler %s",b):F[b]=a}}function I(a,d){if(!a||!F.hasOwnProperty(a))a=/^\s*=l&&(b+=2);g>=B&&(r+=2)}}finally{if(f)f.style.display=h}}catch(u){D.console&&console.log(u&&u.stack||u)}}var D=window,y=["break,continue,do,else,for,if,return,while"],E=[[y,"auto,case,char,const,default,double,enum,extern,float,goto,inline,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], 18 | "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],M=[E,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,delegate,dynamic_cast,explicit,export,friend,generic,late_check,mutable,namespace,nullptr,property,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],N=[E,"abstract,assert,boolean,byte,extends,final,finally,implements,import,instanceof,interface,null,native,package,strictfp,super,synchronized,throws,transient"], 19 | O=[N,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,internal,into,is,let,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var,virtual,where"],E=[E,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],P=[y,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], 20 | Q=[y,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],W=[y,"as,assert,const,copy,drop,enum,extern,fail,false,fn,impl,let,log,loop,match,mod,move,mut,priv,pub,pure,ref,self,static,struct,true,trait,type,unsafe,use"],y=[y,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],R=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)\b/, 21 | V=/\S/,X=v({keywords:[M,O,E,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",P,Q,y],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),F={};p(X,["default-code"]);p(C([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-", 22 | /^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);p(C([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/], 23 | ["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);p(C([],[["atv",/^[\S\s]+/]]),["uq.val"]);p(v({keywords:M,hashComments:!0,cStyleComments:!0,types:R}),["c","cc","cpp","cxx","cyc","m"]);p(v({keywords:"null,true,false"}),["json"]);p(v({keywords:O,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:R}), 24 | ["cs"]);p(v({keywords:N,cStyleComments:!0}),["java"]);p(v({keywords:y,hashComments:!0,multiLineStrings:!0}),["bash","bsh","csh","sh"]);p(v({keywords:P,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),["cv","py","python"]);p(v({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:2}),["perl","pl","pm"]);p(v({keywords:Q, 25 | hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb","ruby"]);p(v({keywords:E,cStyleComments:!0,regexLiterals:!0}),["javascript","js"]);p(v({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,throw,true,try,unless,until,when,while,yes",hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);p(v({keywords:W,cStyleComments:!0,multilineStrings:!0}),["rc","rs","rust"]); 26 | p(C([],[["str",/^[\S\s]+/]]),["regex"]);var Y=D.PR={createSimpleLexer:C,registerLangHandler:p,sourceDecorator:v,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ",prettyPrintOne:D.prettyPrintOne=function(a,d,g){var b=document.createElement("div");b.innerHTML="
"+a+"
";b=b.firstChild;g&&J(b,g,!0);K({h:d,j:g,c:b,i:1}); 27 | return b.innerHTML},prettyPrint:D.prettyPrint=function(a,d){function g(){for(var b=D.PR_SHOULD_USE_CONTINUATION?c.now()+250:Infinity;i.content{position:relative}.vis.timeline .vispanel .shadow{position:absolute;width:100%;height:1px;box-shadow:0 0 10px rgba(0,0,0,.8)}.vis.timeline .vispanel .shadow.top{top:-1px;left:0}.vis.timeline .vispanel .shadow.bottom{bottom:-1px;left:0}.vis.timeline .labelset{position:relative;overflow:hidden;box-sizing:border-box}.vis.timeline .labelset .vlabel{position:relative;left:0;top:0;width:100%;color:#4d4d4d;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis.timeline .labelset .vlabel:last-child{border-bottom:none}.vis.timeline .labelset .vlabel .inner{display:inline-block;padding:5px}.vis.timeline .labelset .vlabel .inner.hidden{padding:0}.vis.timeline .itemset{position:relative;padding:0;margin:0;box-sizing:border-box}.vis.timeline .itemset .background,.vis.timeline .itemset .foreground{position:absolute;width:100%;height:100%;overflow:visible}.vis.timeline .axis{position:absolute;width:100%;height:0;left:0;z-index:1}.vis.timeline .foreground .group{position:relative;box-sizing:border-box;border-bottom:1px solid #bfbfbf}.vis.timeline .foreground .group:last-child{border-bottom:none}.vis.timeline .item{position:absolute;color:#1A1A1A;border-color:#97B0F8;border-width:1px;background-color:#D5DDF6;display:inline-block;padding:5px}.vis.timeline .item.selected{border-color:#FFC200;background-color:#FFF785;z-index:2}.vis.timeline .editable .item.selected{cursor:move}.vis.timeline .item.point.selected{background-color:#FFF785}.vis.timeline .item.box{text-align:center;border-style:solid;border-radius:2px}.vis.timeline .item.point{background:0 0}.vis.timeline .item.dot{position:absolute;padding:0;border-width:4px;border-style:solid;border-radius:4px}.vis.timeline .item.range{border-style:solid;border-radius:2px;box-sizing:border-box}.vis.timeline .item.background{overflow:hidden;border:none;background-color:rgba(213,221,246,.4);box-sizing:border-box;padding:0;margin:0}.vis.timeline .item.range .content{position:relative;display:inline-block;max-width:100%;overflow:hidden}.vis.timeline .item.background .content{position:absolute;display:inline-block;overflow:hidden;max-width:100%;margin:5px}.vis.timeline .item.line{padding:0;position:absolute;width:0;border-left-width:1px;border-left-style:solid}.vis.timeline .item .content{white-space:nowrap;overflow:hidden}.vis.timeline .item .delete{background:url(img/timeline/delete.png)top center no-repeat;position:absolute;width:24px;height:24px;top:0;right:-24px;cursor:pointer}.vis.timeline .item.range .drag-left{position:absolute;width:24px;max-width:20%;height:100%;top:0;left:-4px;cursor:w-resize}.vis.timeline .item.range .drag-right{position:absolute;width:24px;max-width:20%;height:100%;top:0;right:-4px;cursor:e-resize}.vis.timeline .timeaxis{position:relative;overflow:hidden}.vis.timeline .timeaxis.foreground{top:0;left:0;width:100%}.vis.timeline .timeaxis.background{position:absolute;top:0;left:0;width:100%;height:100%}.vis.timeline .timeaxis .text{position:absolute;color:#4d4d4d;padding:3px;white-space:nowrap}.vis.timeline .timeaxis .text.measure{position:absolute;padding-left:0;padding-right:0;margin-left:0;margin-right:0;visibility:hidden}.vis.timeline .timeaxis .grid.vertical{position:absolute;border-left:1px solid}.vis.timeline .timeaxis .grid.minor{border-color:#e5e5e5}.vis.timeline .timeaxis .grid.major{border-color:#bfbfbf}.vis.timeline .currenttime{background-color:#FF7F6E;width:2px;z-index:1}.vis.timeline .customtime{background-color:#6E94FF;width:2px;cursor:move;z-index:1}.vis.timeline .vispanel.background.horizontal .grid.horizontal{position:absolute;width:100%;height:0;border-bottom:1px solid}.vis.timeline .vispanel.background.horizontal .grid.minor{border-color:#e5e5e5}.vis.timeline .vispanel.background.horizontal .grid.major{border-color:#bfbfbf}.vis.timeline .dataaxis .yAxis.major{width:100%;position:absolute;color:#4d4d4d;white-space:nowrap}.vis.timeline .dataaxis .yAxis.major.measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis.timeline .dataaxis .yAxis.minor{position:absolute;width:100%;color:#bebebe;white-space:nowrap}.vis.timeline .dataaxis .yAxis.minor.measure{padding:0;margin:0;border:0;visibility:hidden;width:auto}.vis.timeline .dataaxis .yAxis.title{position:absolute;color:#4d4d4d;white-space:nowrap;bottom:20px;text-align:center}.vis.timeline .dataaxis .yAxis.title.measure{padding:0;margin:0;visibility:hidden;width:auto}.vis.timeline .dataaxis .yAxis.title.left{bottom:0;-webkit-transform-origin:left top;-moz-transform-origin:left top;-ms-transform-origin:left top;-o-transform-origin:left top;transform-origin:left bottom;-webkit-transform:rotate(-90deg);-moz-transform:rotate(-90deg);-ms-transform:rotate(-90deg);-o-transform:rotate(-90deg);transform:rotate(-90deg)}.vis.timeline .dataaxis .yAxis.title.right{bottom:0;-webkit-transform-origin:right bottom;-moz-transform-origin:right bottom;-ms-transform-origin:right bottom;-o-transform-origin:right bottom;transform-origin:right bottom;-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.vis.timeline .legend{background-color:rgba(247,252,255,.65);padding:5px;border-color:#b3b3b3;border-style:solid;border-width:1px;box-shadow:2px 2px 10px rgba(154,154,154,.55)}.vis.timeline .legendText{white-space:nowrap;display:inline-block}.vis.timeline .graphGroup0{fill:#4f81bd;fill-opacity:0;stroke-width:2px;stroke:#4f81bd}.vis.timeline .graphGroup1{fill:#f79646;fill-opacity:0;stroke-width:2px;stroke:#f79646}.vis.timeline .graphGroup2{fill:#8c51cf;fill-opacity:0;stroke-width:2px;stroke:#8c51cf}.vis.timeline .graphGroup3{fill:#75c841;fill-opacity:0;stroke-width:2px;stroke:#75c841}.vis.timeline .graphGroup4{fill:#ff0100;fill-opacity:0;stroke-width:2px;stroke:#ff0100}.vis.timeline .graphGroup5{fill:#37d8e6;fill-opacity:0;stroke-width:2px;stroke:#37d8e6}.vis.timeline .graphGroup6{fill:#042662;fill-opacity:0;stroke-width:2px;stroke:#042662}.vis.timeline .graphGroup7{fill:#00ff26;fill-opacity:0;stroke-width:2px;stroke:#00ff26}.vis.timeline .graphGroup8{fill:#f0f;fill-opacity:0;stroke-width:2px;stroke:#f0f}.vis.timeline .graphGroup9{fill:#8f3938;fill-opacity:0;stroke-width:2px;stroke:#8f3938}.vis.timeline .fill{fill-opacity:.1;stroke:none}.vis.timeline .bar{fill-opacity:.5;stroke-width:1px}.vis.timeline .point{stroke-width:2px;fill-opacity:1}.vis.timeline .legendBackground{stroke-width:1px;fill-opacity:.9;fill:#fff;stroke:#c2c2c2}.vis.timeline .outline{stroke-width:1px;fill-opacity:1;fill:#fff;stroke:#e5e5e5}.vis.timeline .iconFill{fill-opacity:.3;stroke:none}div.network-manipulationDiv{border-width:0;border-bottom:1px;border-style:solid;border-color:#d6d9d8;background:#fff;background:-moz-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fff),color-stop(48%,#fcfcfc),color-stop(50%,#fafafa),color-stop(100%,#fcfcfc));background:-webkit-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-o-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:-ms-linear-gradient(top,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);background:linear-gradient(to bottom,#fff 0,#fcfcfc 48%,#fafafa 50%,#fcfcfc 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#fcfcfc', GradientType=0);position:absolute;left:0;top:0;width:100%;height:30px}div.network-manipulation-editMode{position:absolute;left:0;top:15px;height:30px}div.network-manipulation-closeDiv{position:absolute;right:0;top:0;width:30px;height:30px;background-position:20px 3px;background-image:url(img/network/cross.png);user-select:none}div.network-manipulation-closeDiv:hover{opacity:.6}div.network-manipulationUI{position:relative;top:-7px;font-family:verdana;font-size:12px;-moz-border-radius:15px;border-radius:15px;display:inline-block;background-position:0 0;height:24px;margin:0 0 0 10px;vertical-align:middle;padding:0 8px;user-select:none}div.network-manipulationUI:hover{box-shadow:1px 1px 8px rgba(0,0,0,.2)}div.network-manipulationUI:active{box-shadow:1px 1px 8px rgba(0,0,0,.5)}div.network-manipulationUI.back{background-image:url(img/network/backIcon.png)}div.network-manipulationUI.none:hover{box-shadow:1px 1px 8px transparent;cursor:default}div.network-manipulationUI.none:active{box-shadow:1px 1px 8px transparent}div.network-manipulationUI.none{padding:0}div.network-manipulationUI.notification{margin:2px;font-weight:700}div.network-manipulationUI.add{background-image:url(img/network/addNodeIcon.png)}div.network-manipulationUI.edit{background-image:url(img/network/editIcon.png)}div.network-manipulationUI.edit.editmode{background-color:#fcfcfc;border-style:solid;border-width:1px;border-color:#ccc}div.network-manipulationUI.connect{background-image:url(img/network/connectIcon.png)}div.network-manipulationUI.delete{background-image:url(img/network/deleteIcon.png)}div.network-manipulationLabel{margin:0 0 0 23px;line-height:25px}div.network-seperatorLine{display:inline-block;width:1px;height:20px;background-color:#bdbdbd;margin:5px 7px 0 15px}div.network-navigation_wrapper{position:absolute;left:0;top:0;width:100%;height:100%}div.network-navigation{width:34px;height:34px;-moz-border-radius:17px;border-radius:17px;position:absolute;display:inline-block;background-position:2px 2px;background-repeat:no-repeat;cursor:pointer;-webkit-touch-callout:none;user-select:none}div.network-navigation:hover{box-shadow:0 0 3px 3px rgba(56,207,21,.3)}div.network-navigation:active{box-shadow:0 0 1px 3px rgba(56,207,21,.95)}div.network-navigation.up{background-image:url(img/network/upArrow.png);bottom:50px;left:55px}div.network-navigation.down{background-image:url(img/network/downArrow.png);bottom:10px;left:55px}div.network-navigation.left{background-image:url(img/network/leftArrow.png);bottom:10px;left:15px}div.network-navigation.right{background-image:url(img/network/rightArrow.png);bottom:10px;left:95px}div.network-navigation.zoomIn{background-image:url(img/network/plus.png);bottom:10px;right:15px}div.network-navigation.zoomOut{background-image:url(img/network/minus.png);bottom:10px;right:55px}div.network-navigation.zoomExtends{background-image:url(img/network/zoomExtends.png);bottom:50px;right:15px}div.network-tooltip{position:absolute;visibility:hidden;padding:5px;white-space:nowrap;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;border:1px solid;box-shadow:3px 3px 10px rgba(128,128,128,.5)} -------------------------------------------------------------------------------- /jsdoc/src/js/AbstractTreeView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class IndexView display the full AST @extends AbstractView 3 | var AbstractTreeView = AbstractView.extend({ 4 | 5 | 6 | expandAll: function() 7 | { 8 | var self = this; 9 | this.$('.tree [data-tree-node]').each(function() 10 | { 11 | self.treeView.expandNode($(this)); 12 | }); 13 | } 14 | 15 | , collapseAll: function() 16 | { 17 | var self = this; 18 | this.$('.tree > ul > .tree-node > [data-tree-node]').each(function() 19 | { 20 | self.treeView.collapseNode($(this)); 21 | }); 22 | } 23 | 24 | 25 | }); 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | //TreeWidget - reusable GUI component 35 | (function(){ 36 | 37 | 38 | 39 | /** 40 | TreeWidget - bootstrap based TreeView. Usage: 41 |
var model = {children: [
 42 | 	{label: '1',  children: [
 43 | 		{label: '1.1', type: 'apple', children: []}
 44 | 	]}
 45 | ,   {label: '2', children: [
 46 | 		{label: '2.1', type: 'orange', children: []}
 47 | 	]}
 48 | ]};
 49 | var widget = new TreeWidget(model);
 50 | widget.render('#mytree');
 51 | widget.onNodeEvent('click', function(nodeModel){
 52 | 	alert(nodeModel.label+' was clicked')
 53 | })
 54 | 
55 | @class TreeWidget 56 | @author Sebastián Gurin 57 | */ 58 | 59 | if(window.TreeWidget) { 60 | return; 61 | } 62 | 63 | // @constructor @param {Object} rootNode 64 | var TreeWidget = function(rootNode) { 65 | //@property {TreeNode} rootNode 66 | this.rootNode = rootNode; 67 | 68 | }; 69 | 70 | /* 71 | @property {Object}TreeWidget.cssOptions configurable css options 72 | @static 73 | */ 74 | TreeWidget.cssOptions = { 75 | hoverChildren: false 76 | , hoverColor: 'red' 77 | }; 78 | 79 | 80 | 81 | /* 82 | @method render 83 | @param {HTMLElement} parent HtmlElement - optional if passed the tree will be created and appended to it 84 | @return {String} the html markup of the tree ready to be append() or html() 85 | */ 86 | TreeWidget.prototype.render = function(parent) 87 | { 88 | this.parentEl = parent; 89 | return this._renderTree(this.rootNode, parent); 90 | }; 91 | TreeWidget.prototype._renderTree = function(tree, parent) 92 | { 93 | var self = this, html = this.renderNode({node: tree, renderNode: this.renderNode, isRoot: true}); 94 | if(parent) 95 | { 96 | jQuery(parent).empty().append(html); 97 | } 98 | //TODO: use less global selectors 99 | $('.tree li:has(ul)').addClass('parent_li').find(' > span').attr('title', 'Collapse this branch'); 100 | $('.tree li.parent_li > span').on('click', function (e) 101 | { 102 | var children = $(this).parent('li.parent_li').find(' > ul > li'); 103 | if (children.is(":visible")) { 104 | self.collapseNode($(this)); 105 | } else { 106 | self.expandNode($(this)); 107 | } 108 | e.stopPropagation(); 109 | }); 110 | return html; 111 | }; 112 | 113 | TreeWidget.prototype.collapseNode = function($node) 114 | { 115 | var children = $node.parent('li.parent_li').find(' > ul > li'); 116 | children.hide('fast'); 117 | // glyphicon glyphicon-minus 118 | $node.attr('title', 'Expand this branch').find(' > i').addClass('glyphicon-plus-sign').removeClass('glyphicon-minus-sign'); 119 | // $node.attr('title', 'Expand this branch').find(' > i').addClass('icon-plus-sign').removeClass('icon-minus-sign'); 120 | }; 121 | TreeWidget.prototype.expandNode = function($node) 122 | { 123 | var children = $node.parent('li.parent_li').find(' > ul > li'); 124 | children.show('fast'); 125 | // $node.attr('title', 'Collapse this branch').find(' > i').addClass('icon-minus-sign').removeClass('icon-plus-sign'); 126 | $node.attr('title', 'Collapse this branch').find(' > i').addClass('glyphicon-minus-sign').removeClass('glyphicon-plus-sign'); 127 | }; 128 | 129 | /*@method onNodeEvent. Usage example: 130 | treeWidget.onNodeEvent =('click', function(node, event){...}); 131 | @method onNodeEvent @param {String} eventType @param {Function} fn 132 | */ 133 | TreeWidget.prototype.onNodeEvent = function(eventType, fn) { 134 | jQuery(this.parentEl).on(eventType, 'li > span', function() 135 | { //event delegation 136 | var nodeId = parseInt($(this).data('tree-node-id')); 137 | fn && fn(this, nodeId); 138 | }); 139 | }; 140 | 141 | 142 | window.TreeWidget = TreeWidget; 143 | 144 | 145 | 146 | 147 | TreeWidget.treeNodeTemplate = 148 | '<% var isRoot = isRoot || false; %>'+ 149 | '<% if(isRoot) { %>'+ 150 | '
'+ 151 | '<% } else { %>'+ 152 | '
  • '+ 153 | ''+ 154 | ''+ 155 | '<%= node.label%>'+ 156 | ''+ 157 | '<% } %>'+ 158 | '<% if(node.children) { %>'+ 159 | '
      '+ 160 | '<% _(node.children).each(function(child){ %>'+ 161 | '<%= renderNode({node:child, isRoot: false, renderNode: renderNode}) %>'+ 162 | '<% }) %>'+ 163 | '
    '+ 164 | '<% } %>'+ 165 | '<%= isRoot ? \'
  • \' : \'\' %>'; 166 | 167 | TreeWidget.prototype.renderNode = _(TreeWidget.treeNodeTemplate).template(); 168 | 169 | // TreeWidget.CSS = 170 | // ''; 235 | 236 | // //install style (only once per DOM) 237 | // jQuery(document.body).append(TreeWidget.CSS); 238 | 239 | 240 | })(); 241 | 242 | 243 | //now an example: 244 | // var model = {children: [ 245 | // {label: '1', children: [ 246 | // {label: '1.1', id: '2234412', children: []} 247 | // ]} 248 | // , {label: '2', children: [ 249 | // {label: '2.1', children: []} 250 | // ]} 251 | // ]}; 252 | // var widget = new TreeWidget(model); 253 | // widget.render('#mytree'); 254 | 255 | 256 | 257 | 258 | /** 259 | @class TreeNode 260 | */ 261 | /** 262 | @property label 263 | @type String 264 | */ 265 | /** 266 | @property tree_node_id 267 | @type String 268 | */ 269 | /** 270 | @property label 271 | @type String 272 | */ 273 | /** 274 | @property parentNode 275 | @type TreeNode 276 | */ -------------------------------------------------------------------------------- /jsdoc/src/js/AbstractView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class AbstractView @extend Backbone.View @module shortjsdoc 3 | 4 | var AbstractView = Backbone.View.extend({ 5 | 6 | tagName: 'div' 7 | 8 | , initialize: function(application) 9 | { 10 | this.application = application; 11 | } 12 | 13 | //@method renderIn renders this view in given parent element @param {jQuery} $parent 14 | , renderIn: function($parent) 15 | { 16 | var template = this.application.templates[this.template]; 17 | if(template) 18 | { 19 | var html = template.apply(this, []); 20 | this.$el.html(html); 21 | $parent.append(this.$el); 22 | } 23 | this.afterRender(); 24 | return this; 25 | } 26 | 27 | 28 | //@method render implemented to comply with Backbone View contract 29 | , render: function() 30 | { 31 | return this.renderIn(jQuery(this.el)); 32 | } 33 | 34 | , afterRender: function() 35 | { 36 | this.renderSource(); 37 | } 38 | 39 | , setTitle: function(t) 40 | { 41 | // var self = this; 42 | this.title = t; 43 | setTimeout(function() 44 | { 45 | document.title = t; 46 | }, 200); 47 | } 48 | 49 | //sources stuff 50 | 51 | , renderSource_: function(jsdoc, $container) 52 | { 53 | if(!jsdoc.commentRange) 54 | { 55 | return ; //this view doesn't have a related jsdoc - don't need this feature. 56 | } 57 | var view = new SourcesView(this.application, jsdoc); 58 | view.fileNameUrl = encodeURIComponent(this.jsdoc.fileName); 59 | // this.jsdoc.fileName.replace(/[\\\/]/g, '_'); 60 | view.renderIn($container); 61 | } 62 | 63 | , renderSource: function() 64 | { 65 | if(!this.jsdoc) 66 | { 67 | return; 68 | } 69 | 70 | this.renderSource_(this.jsdoc, this.$('[data-type="sources"]')); 71 | this.$('pre code').addClass('prettyprint'); 72 | if(typeof prettyPrint !== 'undefined') 73 | { 74 | prettyPrint('pre code'); 75 | } 76 | } 77 | }); 78 | 79 | -------------------------------------------------------------------------------- /jsdoc/src/js/Application.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | // this is the main class for all the application 3 | // utilities for rendering jsdoc data generated by jsdocgenerator1 js-indentator plugin 4 | // using backbone. The user should provide with underscore templates. 5 | // @class AbstractView @extend Backbone.View @module shortjsdoc 6 | // @author: sgurin 7 | 8 | //@class Application 9 | /* 10 | @constructor Application 11 | 12 | @param {Object} data is the data.json object outputed by running 13 | 14 | var maker = new JsDocMaker(); 15 | maker.parseFile(myCodeString); 16 | maker.postProccess(); 17 | var data = maker.data; 18 | */ 19 | var Application = function(data) 20 | { 21 | //@property {String} textFormat can be markdown or html. default: markdown 22 | this.textFormat = 'markdown'; 23 | 24 | //@property {Object} templates The templates dictionary (given by template-output.js) 25 | this.templates = shortjsdoc; 26 | 27 | /*@property {Object} data is the data.json object outputed by running: 28 | 29 | var maker = new JsDocMaker(); 30 | maker.parseFile(myCodeString); 31 | maker.postProccess(); 32 | var data = maker.data; 33 | */ 34 | this.data = data; 35 | 36 | 37 | //@property {JsDocMaker} maker the JsDocMaker instance we will use for loading the parsed data and doing some post processing stage (type binding and so) 38 | this.maker = new JsDocMaker(); 39 | this.maker.data = data; 40 | 41 | this.maker.postProccess(); 42 | this.maker.postProccessBinding(); 43 | this.maker.postProccessInherited(); // <-- important - explicitly ask the framework to calculate inherited methods&properties 44 | 45 | 46 | window.shortjsdocdata = data;//for debugging only 47 | 48 | if(jQuery('#mainContainer').size()===0) 49 | { 50 | jQuery('body').append('
    '); 51 | } 52 | this.$containerEl = jQuery('#mainContainer'); 53 | }; 54 | 55 | _(Application.prototype).extend({ 56 | 57 | //@method start starts the application by instantiating routers and history and navigating to the index. 58 | start: function() 59 | { 60 | this.router = new JsDocRouter(this); 61 | Backbone.history.start(); 62 | var navigateTo = Backbone.history.getHash() || 'index'; 63 | Backbone.history.navigate(navigateTo, {trigger: true}); 64 | } 65 | 66 | //@method showView @param {AbstractView} view 67 | , showView: function(view) 68 | { 69 | this.applicationView = this.applicationView || new ApplicationView(this); 70 | this.currentView = view; 71 | this.$containerEl.empty(); 72 | this.applicationView.renderIn(this.$containerEl); 73 | } 74 | 75 | //@method refreshWithNewModel @param {Object}data 76 | , refreshWithNewModel: function(data) 77 | { 78 | this.data = data; 79 | Backbone.history.navigate('#index', {trigger: true}); 80 | this.showView(this.currentView); 81 | } 82 | 83 | //@method showErrorView @param {String}s 84 | , showErrorView: function(s) 85 | { 86 | this.$containerEl.empty().append('

    '+s+'

    '); 87 | } 88 | 89 | }); 90 | 91 | //@method start an application loading it with given data. @static 92 | //@param data the output of passing jsindentator JsDocMaker. 93 | Application.startApplication = function(data) 94 | { 95 | var app = new Application(data); 96 | app.start(); 97 | }; 98 | -------------------------------------------------------------------------------- /jsdoc/src/js/ApplicationView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class ApplicationView @extends AbstractView 3 | var ApplicationView = AbstractView.extend({ 4 | 5 | className: 'application-view' 6 | 7 | , template: 'application' 8 | 9 | , initialize: function(application) 10 | { 11 | this.application = application; 12 | } 13 | 14 | , renderIn: function($el) 15 | { 16 | AbstractView.prototype.renderIn.apply(this, arguments); 17 | 18 | this.headerView = this.headerView || new HeaderView(this.application); 19 | this.headerView.renderIn(this.$('[data-type="header-container"]')); 20 | 21 | this.mainView = this.application.currentView; 22 | 23 | this.mainView.renderIn(this.$('[data-type="main-view-container"]')); 24 | 25 | document.title = this.title || window.location.href + ''; 26 | } 27 | 28 | }); -------------------------------------------------------------------------------- /jsdoc/src/js/ClassView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class ClassView @extends AbstractView 3 | 4 | var ClassView = AbstractView.extend({ 5 | 6 | className: 'class-view' 7 | 8 | , template: 'class' 9 | 10 | , initialize: function(application, className, options) 11 | { 12 | this.application = application; 13 | this.jsdoc = this.application.data.classes[className]; 14 | if(!this.jsdoc) 15 | { 16 | this.resourceNotFound = true; 17 | return; 18 | } 19 | 20 | this.jsdoc.textHtml = this.getTextHtml(this.jsdoc); 21 | 22 | this.options = options || {}; 23 | this.options.inherited = this.options.inherited ? parseInt(this.options.inherited, 10) : 0; 24 | this.options.text = this.options.text ? parseInt(this.options.text, 10) : 1; 25 | 26 | this.methods = this.jsdoc.methods; 27 | if(this.options.inherited) 28 | { 29 | this.methods = _(_(this.methods).clone()).extend(this.jsdoc.inherited.methods); 30 | } 31 | 32 | // calculate properties, events and attributes inheritance information 33 | this.properties = this.jsdoc.properties; 34 | if(this.options.inherited) 35 | { 36 | this.properties = _(_(this.properties).clone()).extend(this.jsdoc.inherited.properties); 37 | } 38 | this.events = this.jsdoc.events; 39 | if(this.options.inherited) 40 | { 41 | this.events = _(_(this.events).clone()).extend(this.jsdoc.inherited.events); 42 | } 43 | this.attributes = this.jsdoc.attributes; 44 | if(this.options.inherited) 45 | { 46 | this.attributes = _(_(this.attributes).clone()).extend(this.jsdoc.inherited.attributes); 47 | console.log('seba2', this.attributes ) 48 | } 49 | 50 | this.hierarchy = this.computeHierarchy(); 51 | this.knownSubclasses = this.computeKnownSubclasses(); 52 | } 53 | 54 | //@method makePartialText @param {AST} node @return {String} 55 | , makePartialText: function(node) 56 | { 57 | if(!node.text){return ''; } 58 | else 59 | { 60 | var min = Math.min(node.text.length, 100); 61 | return node.text.substring(0, min) + '...'; 62 | } 63 | } 64 | 65 | //@method computeHierarchy @return {Array} 66 | , computeHierarchy: function() 67 | { 68 | var hierarchy = []; 69 | var c = this.jsdoc; 70 | do 71 | { 72 | if(c && c.extends) 73 | { 74 | hierarchy.push(c);// = [c].concat(hierarchy); 75 | if(c.extends.absoluteName===c.absoluteName) 76 | { 77 | break; 78 | } 79 | 80 | } 81 | } 82 | while( (c = c.extends) ); 83 | return hierarchy; 84 | } 85 | 86 | //@method computeKnownSubclasses @return {Array} 87 | , computeKnownSubclasses: function() 88 | { 89 | var self = this; 90 | var knownSubclasses = []; 91 | _(this.application.data.classes).each(function(c) 92 | { 93 | if(c.extends.absoluteName === self.jsdoc.absoluteName) 94 | { 95 | knownSubclasses.push(c); 96 | } 97 | }); 98 | return knownSubclasses; 99 | } 100 | 101 | }); -------------------------------------------------------------------------------- /jsdoc/src/js/DependenciesView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class IndexView display the full AST @extends AbstractView 3 | var DependenciesView = AbstractView.extend({ 4 | 5 | className: 'dependencies' 6 | 7 | , template: 'dependencies' 8 | 9 | , events: { 10 | 'click [data-type="includeExtends"]': 'includeExtends' 11 | , 'click [data-type="includeNativeClasses"]': 'includeNativeClasses' 12 | } 13 | 14 | , initialize: function(application, options) 15 | { 16 | this.application = application; 17 | this.options = options || {}; 18 | this.options.includeExtends = this.options.includeExtends && this.options.includeExtends!=='0'; 19 | this.options.includeNativeClasses = this.options.includeNativeClasses && this.options.includeNativeClasses!=='0'; 20 | 21 | this.ignoreClasses = this.options.includeNativeClasses ? [] : [ 22 | 'javascript.String' 23 | , 'javascript.Object' 24 | , 'javascript.Function' 25 | , 'javascript.Any' 26 | , 'javascript.Number' 27 | , 'javascript.Boolean' 28 | , 'javascript.Array' 29 | ]; 30 | } 31 | 32 | , renderIn: function() 33 | { 34 | var self = this; 35 | AbstractView.prototype.renderIn.apply(this, arguments); 36 | 37 | toast( 38 | 'lib/vis/dist/vis.min.js' 39 | , 'lib/vis/dist/vis.min.css' 40 | , function() 41 | { 42 | self.doTheGraph(); 43 | } 44 | ); 45 | } 46 | 47 | //TODO repeated code 48 | , includeExtends: function() 49 | { 50 | var checked = this.$('[data-type="includeExtends"]').is(':checked'); 51 | var options = this.getOptionsFromHash(); 52 | options.includeExtends = checked ? '1' : '0'; 53 | var url = 'dependencies?' + this.optionsToString(options); 54 | Backbone.history.navigate(url, {trigger: true}); 55 | } 56 | 57 | //TODO repeated code 58 | , includeNativeClasses: function() 59 | { 60 | var checked = this.$('[data-type="includeNativeClasses"]').is(':checked'); 61 | var options = this.getOptionsFromHash(); 62 | options.includeNativeClasses = checked ? '1' : '0'; 63 | var url = 'dependencies?' + this.optionsToString(options); 64 | Backbone.history.navigate(url, {trigger: true}); 65 | } 66 | 67 | , doTheGraph: function() 68 | { 69 | this.$('.loading-message').show(); 70 | var toolConfig = { 71 | ignoreClasses: this.ignoreClasses 72 | , includeExtends: this.options.includeExtends 73 | } 74 | , tool = new this.application.maker.tools.DependencyTool(this.application.maker, toolConfig); 75 | 76 | tool.calculateClassDependencies(); 77 | 78 | // this.application.maker.calculateClassDependencies(); 79 | var self = this, nodes = [], edges = []; 80 | 81 | var counter = 1, nodeIds = {}; 82 | _(this.application.data.classes).each(function(c) 83 | { 84 | var node = {id: counter, label: c.name}; 85 | nodes.push(node); 86 | nodeIds[c.absoluteName] = node; 87 | counter++; 88 | }); 89 | _(this.application.data.classes).each(function(c) 90 | { 91 | _(c.dependencies.classes).each(function(dep) 92 | { 93 | // debugger; 94 | if(nodeIds[c.absoluteName] && nodeIds[dep.absoluteName]) 95 | { 96 | edges.push({ 97 | from: nodeIds[c.absoluteName].id 98 | , to: nodeIds[dep.absoluteName].id 99 | }); 100 | } 101 | }); 102 | }); 103 | 104 | // create a vis network graph 105 | var container = this.$('[data-type="dependency-graph"]').get(0); 106 | var data = { 107 | nodes: nodes, 108 | edges: edges 109 | }; 110 | 111 | var options = { 112 | nodes: { 113 | shape: 'box' 114 | } 115 | , edges: { 116 | style: 'arrow' 117 | } 118 | }; 119 | 120 | var network = new vis.Network(container, data, options); 121 | 122 | this.$('.loading-message').hide(); 123 | } 124 | 125 | }); 126 | 127 | 128 | 129 | 130 | 131 | -------------------------------------------------------------------------------- /jsdoc/src/js/FileView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class ClassView @extends AbstractView 3 | 4 | var FileView = AbstractView.extend({ 5 | 6 | className: 'file-view' 7 | 8 | , template: 'file' 9 | 10 | , events: { 11 | 'click [data-action="donwload"]': 'download' 12 | } 13 | 14 | , initialize: function(application, fileName, options) 15 | { 16 | 17 | this.fileName = decodeURIComponent(fileName); 18 | 19 | this.application = application; 20 | this.jsdoc = this.application.data.files[fileName]; 21 | if(!this.jsdoc) 22 | { 23 | this.resourceNotFound = true; 24 | return; 25 | } 26 | var end = this.application.data.source.indexOf('@filename', this.jsdoc.commentRange[1]); 27 | end = end === -1 ? this.application.data.source.length : end; 28 | this.fileContent = this.application.data.source.substring(this.jsdoc.commentRange[1], end); 29 | } 30 | 31 | , afterRender: function() 32 | { 33 | if(typeof prettyPrint !== 'undefined') 34 | { 35 | prettyPrint(); 36 | } 37 | } 38 | 39 | , download: function() 40 | { 41 | var fileName = this.fileName.split('/'); 42 | fileName = fileName[fileName.length-1]; 43 | var a = document.createElement('a'); 44 | var blob = new Blob([this.fileContent], {'type': 'text/javascript'}); 45 | a.href = window.URL.createObjectURL(blob); 46 | a.download = fileName; 47 | a.click(); 48 | } 49 | }); 50 | -------------------------------------------------------------------------------- /jsdoc/src/js/HeaderView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class HeaderView @extends AbstractView 3 | var HeaderView = AbstractView.extend({ 4 | 5 | className: 'header-view' 6 | 7 | , template: 'header' 8 | 9 | , initialize: function(application) 10 | { 11 | this.application = application; 12 | } 13 | 14 | , renderIn: function() 15 | { 16 | AbstractView.prototype.renderIn.apply(this, arguments); 17 | this.installTypeAhead(); 18 | } 19 | 20 | , installTypeAhead: function() 21 | { 22 | this.classes = this.application.data.classes; 23 | this.modules = this.application.data.modules; 24 | 25 | this.typeahead = $('.main-header .typeahead1').typeahead({ 26 | hint: true, 27 | highlight: true, 28 | minLength: 1 29 | }, { 30 | name: 'jsdoc', 31 | displayKey: 'value', 32 | source: this.substringMatcher(), 33 | templates: { 34 | empty: '
    Sorry, nothing found.
    ' 35 | , suggestion: this.application.templates.typeaheadSuggestion 36 | } 37 | }); 38 | 39 | var self = this; 40 | this.typeahead.on('typeahead:selected', function() 41 | { 42 | self.handleSearchSelection.apply(self, arguments); 43 | }); 44 | 45 | if(jQuery(window).width()<400) 46 | { 47 | jQuery('.tt-dropdown-menu').css({width: jQuery(window).width()+'px'}); 48 | } 49 | 50 | } 51 | 52 | , handleSearchSelection: function(event, object, dataset) 53 | { 54 | var href = this.makeLink(object.node); 55 | Backbone.history.navigate(href, {trigger: true}); 56 | } 57 | 58 | , search: function(q) 59 | { 60 | var self=this,matches = [] 61 | 62 | // regex used to determine if a string contains the substring `q` 63 | , substrRegex = new RegExp(q, 'i'); 64 | 65 | // iterate through the pool of strings and for any string that 66 | // contains the substring `q`, add it to the `matches` array 67 | _(self.classes).each(function (c) 68 | { 69 | if (substrRegex.test(c.name)) 70 | { 71 | matches.push({ value: c.name, node: c }); 72 | } 73 | _(c.methods).each(function (m) 74 | { 75 | if (substrRegex.test(m.name)) 76 | { 77 | matches.push({ value: m.name, node: m }); 78 | } 79 | 80 | }); 81 | }); 82 | 83 | _(self.modules).each(function (m) 84 | { 85 | if (substrRegex.test(m.name)) 86 | { 87 | matches.push({ value: m.name, node: m }); 88 | } 89 | }); 90 | 91 | return matches; 92 | } 93 | 94 | , substringMatcher: function() 95 | { 96 | var self = this; 97 | return function findMatches(q, cb) 98 | { 99 | var matches; 100 | // an array that will be populated with substring matches 101 | matches = self.search(q); 102 | cb(matches); 103 | }; 104 | } 105 | 106 | }); 107 | -------------------------------------------------------------------------------- /jsdoc/src/js/HierarchyTreeView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class HierarchyTreeView display the full AST @extends AbstractView 3 | var HierarchyTreeView = AbstractTreeView.extend({ 4 | 5 | className: 'hierarchy-tree' 6 | 7 | , template: 'hierarchytree' 8 | 9 | , events: { 10 | 'click [data-action="show-tree"]': 'showTree' 11 | , 'click [data-action="expand-all"]': 'expandAll' 12 | , 'click [data-action="collapse-all"]': 'collapseAll' 13 | } 14 | 15 | , renderIn: function() 16 | { 17 | AbstractView.prototype.renderIn.apply(this, arguments); 18 | 19 | var rootNode = this.application.data.classes['javascript.Object']; 20 | if(!rootNode) 21 | { 22 | rootNode = {name:'Object'}; 23 | } 24 | 25 | var a = this.classesExtendsFrom(rootNode); 26 | 27 | this.treeModel = this.buildTreeModel(rootNode); 28 | this.treeModel = {label: 'Something', children: [this.treeModel]}; // add an extra level so root class also appears 29 | 30 | this.treeView = new TreeWidget(this.treeModel); 31 | this.treeView.render('.the-tree'); 32 | this.treeView.onNodeEvent('click', function(nodeModel) 33 | { 34 | alert(nodeModel.label+' was clicked'); 35 | }); 36 | 37 | } 38 | // @method classesExtendsFrom search for classes extending from given type. It taks in consideration native object type and normal types. 39 | // @param {ASTNode} type @return {Array} 40 | , classesExtendsFrom: function(type) 41 | { 42 | var a = []; 43 | _(this.application.data.classes).each(function(c) 44 | { 45 | if(!c.extends || !type){} 46 | else if(c.extends.absoluteName ) 47 | { 48 | if(c.extends.absoluteName === type.absoluteName && c.absoluteName !== c.extends.absoluteName) 49 | { 50 | a.push(c); 51 | } 52 | } 53 | else if(c.extends.name && c.name !== c.extends.name) 54 | { 55 | if(c.extends.name === type.name) 56 | { 57 | a.push(c); 58 | } 59 | } 60 | }); 61 | return a; 62 | } 63 | //@method buildTreeModel @return {children:Array,label:String} @param {ASTNode} node 64 | , buildTreeModel: function(node) 65 | { 66 | if(!node) return []; 67 | var model = { 68 | children: [] 69 | , label: '' + (node.absoluteName || node.name) + '' 70 | } 71 | , self = this 72 | , classesExtendsFrom = self.classesExtendsFrom(node); 73 | 74 | _(classesExtendsFrom).each(function(c) 75 | { 76 | model.children.push(self.buildTreeModel(c)); 77 | }); 78 | 79 | return model; 80 | } 81 | 82 | }); 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /jsdoc/src/js/IndexView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class IndexView @extends AbstractView 3 | var IndexView = AbstractView.extend({ 4 | 5 | className: 'index' 6 | 7 | , template: 'index' 8 | 9 | }); 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /jsdoc/src/js/JsDocRouter.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class JsDocRouter @extends Backbone.Router 3 | var JsDocRouter = Backbone.Router.extend({ 4 | 5 | routes: { 6 | 'class/:class': 'showClass' 7 | , 'class/:class?:options': 'showClass' 8 | 9 | , 'module/:module': 'showModule' 10 | 11 | , 'method/:method': 'showMethod' 12 | , 'constructor/:method': 'showMethod' 13 | 14 | , 'property/:property': 'showProperty' 15 | , 'event/:event': 'showEvent' 16 | , 'attribute/:attribute': 'showAttribute' 17 | 18 | , 'index': 'showIndex' 19 | , 'modules': 'showModules' 20 | , 'classes': 'showClasses' 21 | 22 | , 'parse': 'showParse' 23 | 24 | , 'tree': 'showTree' 25 | , 'hierarchyTree': 'showHierarchyTree' 26 | 27 | , 'file/:file': 'showFile' 28 | , 'file/:file?:options': 'showFile' 29 | 30 | , 'search': 'doSearch' 31 | , 'search/:options': 'doSearch' 32 | 33 | , 'dependencies/:options': 'showDependencies' 34 | , 'dependencies': 'showDependencies' 35 | } 36 | 37 | , initialize: function(application) 38 | { 39 | this.application=application; 40 | } 41 | 42 | //@method showView @param {AbstractView}view @param {String} resourceName 43 | , showView: function(view, resourceName) 44 | { 45 | resourceName = resourceName||'Resource'; 46 | if(view.resourceNotFound) 47 | { 48 | this.application.showErrorView(resourceName+' '+resourceName+' not found!'); 49 | } 50 | else 51 | { 52 | this.application.showView(view); 53 | } 54 | } 55 | 56 | //@method showModule @param {String} moduleName 57 | , showModule: function(moduleName) 58 | { 59 | var view = new ModuleView(this.application, moduleName); 60 | this.showView(view); 61 | } 62 | 63 | //method parseOptions @return {Object} 64 | , parseOptions: function(options) 65 | { 66 | var params = {}; 67 | _(options.split('&')).each(function(p) 68 | { 69 | var a = p.split('='); 70 | if (a.length >= 2) 71 | { 72 | params[a[0]] = a[1]; 73 | } 74 | }); 75 | return params; 76 | } 77 | 78 | //@method showClass @param {String} className 79 | , showClass: function(className, options) 80 | { 81 | options = options || ''; 82 | var params = this.parseOptions(options); 83 | var view = new ClassView(this.application, className, params); 84 | this.showView(view); 85 | } 86 | 87 | //@method showMethod @param {String} method 88 | , showMethod: function(method) 89 | { 90 | var view = new MethodView(this.application, method); 91 | this.showView(view); 92 | } 93 | 94 | 95 | //@method showProperty @param {String} property 96 | , showProperty: function(property) 97 | { 98 | var view = new PropertyView(this.application, property, 'property'); 99 | this.showView(view); 100 | } 101 | //@method showEvent @param {String} event 102 | , showEvent: function(event) 103 | { 104 | var view = new PropertyView(this.application, event, 'event'); 105 | this.showView(view); 106 | } 107 | //@method showAttribute @param {String} attribute 108 | , showAttribute: function(attribute) 109 | { 110 | var view = new PropertyView(this.application, attribute, 'attribute'); 111 | this.showView(view); 112 | } 113 | 114 | 115 | //@method showModules 116 | , showModules: function() 117 | { 118 | var view = new AbstractView(this.application); 119 | view.template = 'modules'; 120 | this.showView(view); 121 | } 122 | 123 | //@method showClasses 124 | , showClasses: function() 125 | { 126 | var view = new AbstractView(this.application); 127 | view.template = 'classes'; 128 | this.showView(view); 129 | } 130 | 131 | //@method search @param {String} options 132 | , doSearch: function(optionsStr) 133 | { 134 | var options = this.parseOptions(optionsStr||''); 135 | var view = new SearchView(this.application, options); 136 | this.showView(view); 137 | } 138 | 139 | //@method showDependencies @param {String} options 140 | , showDependencies: function(optionsStr) 141 | { 142 | var options = this.parseOptions(optionsStr||''); 143 | var view = new DependenciesView(this.application, options); 144 | this.showView(view); 145 | } 146 | 147 | //@method showIndex 148 | , showIndex: function() 149 | { 150 | var view = new IndexView(this.application); 151 | this.application.showView(view); 152 | } 153 | 154 | //@method showTree 155 | , showTree: function() 156 | { 157 | var view = new TreeView(this.application); 158 | this.application.showView(view); 159 | } 160 | 161 | //@method showHierarchyTree 162 | , showHierarchyTree: function() 163 | { 164 | var view = new HierarchyTreeView(this.application); 165 | this.application.showView(view); 166 | } 167 | 168 | //@method showParse 169 | , showParse: function() 170 | { 171 | var view = new ParseView(this.application); 172 | this.application.showView(view); 173 | } 174 | 175 | //@method showFile @param {String} file 176 | , showFile: function(file, options) 177 | { 178 | options = options || ''; 179 | var params = this.parseOptions(options); 180 | var view = new FileView(this.application, file, params); 181 | this.showView(view); 182 | } 183 | 184 | }); 185 | -------------------------------------------------------------------------------- /jsdoc/src/js/MethodView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class MethodView @extends AbstractView 3 | var MethodView = AbstractView.extend({ 4 | 5 | className: 'method-view' 6 | 7 | , template: 'method' 8 | 9 | , initialize: function(application, methodName) 10 | { 11 | this.application = application; 12 | 13 | var className = this.getClassName(methodName); 14 | // var propertySimpleName = a[2]; 15 | var methodSimpleName = this.getSimpleName(methodName); 16 | 17 | // var a = methodName.split('.'); 18 | // var className = a[0] + '.' + a[1]; 19 | var class_ = this.application.data.classes[className]; 20 | // var methodSimpleName = a[2]; 21 | if(!isNaN(parseInt(methodSimpleName, 10))) 22 | { 23 | this.jsdoc = class_.constructors[parseInt(methodSimpleName, 10)]; 24 | this.isConstructor = true; 25 | } 26 | else 27 | { 28 | this.jsdoc = class_.methods[methodSimpleName]; 29 | this.isConstructor = false; 30 | } 31 | if(!this.jsdoc) 32 | { 33 | this.resourceNotFound = true; 34 | return; 35 | } 36 | 37 | this.jsdoc.textHtml = this.getTextHtml(this.jsdoc); 38 | this.ownerClass = this.application.data.classes[this.jsdoc.ownerClass]; 39 | } 40 | 41 | }); 42 | 43 | -------------------------------------------------------------------------------- /jsdoc/src/js/ModuleView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class ModuleView @extends AbstractView 3 | var ModuleView = AbstractView.extend({ 4 | 5 | className: 'module' 6 | 7 | , template: 'module' 8 | 9 | , initialize: function(application, moduleName) 10 | { 11 | this.application = application; 12 | this.jsdoc = this.application.data.modules[moduleName]; 13 | this.classes = _( _(this.application.data.classes).values() ).filter(function(c){ 14 | return c.module.name === moduleName; 15 | }); 16 | 17 | this.jsdoc.textHtml = this.getTextHtml(this.jsdoc); 18 | } 19 | 20 | }); -------------------------------------------------------------------------------- /jsdoc/src/js/ParseView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class ParseView @extends AbstractView 3 | var ParseView = AbstractView.extend({ 4 | 5 | className: 'parse' 6 | 7 | , events: { 8 | 'click [data-action="inputcode_doit"]': 'inputCodeDoit' 9 | } 10 | 11 | , template: 'parse' 12 | 13 | , inputCodeDoit: function() 14 | { 15 | var code = this.$('[data-type="inputcode"]').val(); 16 | var maker = this.application.maker; 17 | 18 | var clean = this.$('[data-action="clean"]:checked').val(); 19 | if(clean) 20 | { 21 | this.application.data = maker.data = {}; 22 | } 23 | maker.parseFile(code, 'textarea'); 24 | maker.postProccess(); 25 | //console.log(JSON.stringify(maker.data)); 26 | maker.postProccessBinding(); 27 | this.application.refreshWithNewModel(maker.data); 28 | } 29 | 30 | }); -------------------------------------------------------------------------------- /jsdoc/src/js/PropertyView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class PropertyView @extends AbstractView 3 | var PropertyView = AbstractView.extend({ 4 | 5 | className: 'property-view' 6 | 7 | , template: 'property' 8 | 9 | , initialize: function(application, propertyName, propertyType) 10 | { 11 | this.application = application; 12 | 13 | var propertyLabelsDic = { 14 | event: 'Event', property: 'Property', attribute: 'Attribute' 15 | }; 16 | 17 | this.propertyLabel = propertyLabelsDic[propertyType]; 18 | 19 | var className = this.getClassName(propertyName); 20 | 21 | var propertySimpleName = this.getSimpleName(propertyName); 22 | 23 | var class_ = this.application.data.classes[className]; 24 | 25 | var propertyPropNamesDic = { 26 | event: 'events', property: 'properties', attribute: 'attributes' 27 | }; 28 | 29 | this.jsdoc = class_[propertyPropNamesDic[propertyType]][propertySimpleName]; 30 | 31 | if(!this.jsdoc) 32 | { 33 | this.resourceNotFound = true; 34 | return; 35 | } 36 | 37 | this.jsdoc.textHtml = this.getTextHtml(this.jsdoc); 38 | } 39 | 40 | 41 | }); 42 | 43 | -------------------------------------------------------------------------------- /jsdoc/src/js/SearchView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class SearchView @extends AbstractView 3 | 4 | var SearchView = AbstractView.extend({ 5 | 6 | className: 'search-view' 7 | 8 | , template: 'search' 9 | 10 | , events: { 11 | 'click [data-action="search"]': 'searchActionHandler' 12 | } 13 | 14 | , initialize: function(application, options) 15 | { 16 | this.application = application; 17 | this.jsdoc = this.application.data; 18 | 19 | var self = this; 20 | // @property {SearchView.Query} query; 21 | this.query = options; 22 | this.search(function(results) 23 | { 24 | // @property {Array} results 25 | self.results = results; 26 | // debugger; 27 | self.render(); 28 | }); 29 | } 30 | 31 | , formToJson: function(form) 32 | { 33 | var s = jQuery(form).serialize(); 34 | var a = s.split('&') 35 | var obj = {}; 36 | _(a).each(function(b) 37 | { 38 | var c = b.split('='); 39 | obj[c[0]] = c[1]; 40 | }); 41 | return obj; 42 | } 43 | 44 | , searchActionHandler: function(e) 45 | { 46 | var options = this.$('[data-type="search-form"]').serialize(); 47 | Backbone.history.navigate('search?'+options, {trigger: true});//, {replace: true}); 48 | // var query = this.formToJson(this.$('[data-type="search-form"]')); 49 | // var results = this.doSearch(query); 50 | e.preventDefault(); 51 | } 52 | 53 | , search: function(cb) 54 | { 55 | if(!this.query.keywords) 56 | { 57 | return; 58 | } 59 | 60 | var self = this, results = {} 61 | , keywordsCompare = self.query.keywords.toLowerCase() 62 | , nodeVisitor = function(node){}; 63 | 64 | var typeVisitor = function(type, ownerNode) 65 | { 66 | var typeName = type.absoluteName ? type.absoluteName : type.name; 67 | 68 | if(!typeName || ! ownerNode) 69 | { 70 | return; 71 | } 72 | 73 | var typeName = typeName.toLowerCase(); 74 | if(typeName && typeName.indexOf(keywordsCompare) !== -1) 75 | { 76 | var label, url, ownerNodeId; 77 | if(ownerNode.annotation==='param') 78 | { 79 | ownerNodeId = ownerNode.parentNode.absoluteName + '.' + ownerNode.name; 80 | label = 'parameter \'' + ownerNode.name + '\' of method \'' + 81 | ownerNode.parentNode.absoluteName + '\''; 82 | url = self.makeLink(ownerNode.parentNode); 83 | } 84 | else 85 | { 86 | ownerNodeId = ownerNode.absoluteName; 87 | label = ownerNode.annotation /*+ ' ' + ownerNode.name + ' of ' + 88 | ownerNode.annotation */ + ' \'' + ownerNode.absoluteName + '\''; 89 | url = self.makeLink(ownerNode); 90 | } 91 | results[ownerNodeId] = { 92 | label: label 93 | , url: url 94 | } 95 | } 96 | }; 97 | 98 | var endCallback = function() 99 | { 100 | var nodeVisitorArray =[]; 101 | _(results).each(function(val) 102 | { 103 | nodeVisitorArray.push(val) 104 | }); 105 | cb(nodeVisitorArray); 106 | } 107 | 108 | this.application.maker.recurseAST(nodeVisitor, typeVisitor, endCallback); 109 | 110 | } 111 | 112 | }); 113 | 114 | // @class SearchView.Query @property {String} keywords 115 | // @property {Boolean} types will list method and properties that reference given type 116 | // @property {String} match can be 'contains', 'exactly', 'regexp' - default: 'contains' -------------------------------------------------------------------------------- /jsdoc/src/js/SourcesView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class SourcesView @extends AbstractView 3 | var SourcesView = AbstractView.extend({ 4 | 5 | className: 'sources' 6 | 7 | , template: 'sources' 8 | 9 | , events: { 10 | 'click [data-type="goto-source"]': 'gotoSource' 11 | } 12 | 13 | , initialize: function(application, jsdoc) 14 | { 15 | this.application = application; 16 | this.jsdoc = jsdoc; 17 | this.allSource = this.application.maker.data.source; 18 | 19 | var rangeRatio = 400; 20 | var rangeMin = Math.max(0, this.jsdoc.commentRange[0] - rangeRatio); 21 | var rangeMax = Math.min(this.allSource.length - 1, this.jsdoc.commentRange[1] + rangeRatio); 22 | this.sourceSubset = this.allSource.substring(rangeMin, rangeMax); 23 | var jsdocSource = this.allSource.substring(this.jsdoc.commentRange[0], this.jsdoc.commentRange[1]); 24 | var previusSource = this.sourceSubset.substring(0, this.sourceSubset.indexOf(jsdocSource)); 25 | var previusSourceLineCount = previusSource.split('\n').length; 26 | 27 | this.jsdocLineNumber = previusSourceLineCount - 1; 28 | 29 | this.lineCount = jsdocSource.split('\n').length; 30 | 31 | //TODO: count the lines of the comment and show all the lines - not only the first one 32 | } 33 | 34 | , afterRender: function() 35 | { 36 | if(typeof prettyPrint !== 'undefined') 37 | { 38 | prettyPrint(); 39 | } 40 | } 41 | 42 | , gotoSource: function() 43 | { 44 | var selector = 'ol.linenums>li' 45 | , $target = jQuery(jQuery(selector).get(this.jsdocLineNumber)); 46 | if($target.size()) 47 | { 48 | jQuery(window).scrollTop($target.position().top); 49 | $target.addClass('selectedJsDocLine'); 50 | } 51 | 52 | for (var i = 0; i < this.lineCount; i++) 53 | { 54 | $target = jQuery(jQuery(selector).get(this.jsdocLineNumber+i)); 55 | $target.addClass('selectedJsDocLine'); 56 | } 57 | } 58 | }); -------------------------------------------------------------------------------- /jsdoc/src/js/TreeView.js: -------------------------------------------------------------------------------- 1 | //@module shortjsdoc.html 2 | //@class IndexView display the full AST @extends AbstractView 3 | var TreeView = AbstractTreeView.extend({ 4 | 5 | className: 'tree' 6 | 7 | , template: 'tree' 8 | 9 | , events: { 10 | 'click [data-action="show-tree"]': 'showTree' 11 | , 'click [data-action="expand-all"]': 'expandAll' 12 | , 'click [data-action="collapse-all"]': 'collapseAll' 13 | } 14 | 15 | , renderIn: function() 16 | { 17 | AbstractView.prototype.renderIn.apply(this, arguments); 18 | 19 | // just show the tree 20 | this.treeModel = this.buildTreeModel(this.application.data); 21 | this.treeView = new TreeWidget(this.treeModel); 22 | this.treeView.render('.the-tree'); 23 | this.treeView.onNodeEvent('click', function(nodeModel) 24 | { 25 | alert(nodeModel.label+' was clicked'); 26 | }); 27 | } 28 | 29 | , buildTreeModel: function() 30 | { 31 | var model = {children: []} 32 | , self = this 33 | , data = this.application.data; 34 | 35 | _(data.modules).each(function(m) 36 | { 37 | model.children.push(self.buildTreeModelForModule(m, data)); 38 | }); 39 | return model; 40 | } 41 | , buildTreeModelForModule: function(m, data) 42 | { 43 | var node = { 44 | children: [] 45 | , label: 'Module ' + this.makeLink(m, true) 46 | , type: 'module' 47 | } 48 | , self = this; 49 | var classes = _(data.classes).filter(function(c){return c.module.name === m.name; }); 50 | _(classes).each(function(c) 51 | { 52 | node.children.push(self.buildTreeModelForClass(c, data)); 53 | }); 54 | return node; 55 | } 56 | , buildTreeModelForClass: function(c, data) 57 | { 58 | var node = { 59 | children: [] 60 | , label: 'Class ' + this.makeLink(c, true) 61 | , type: 'class' 62 | } 63 | , self = this; 64 | _(c.methods).each(function(m) 65 | { 66 | node.children.push(self.buildTreeModelForMethod(m, data)); 67 | }); 68 | _(c.properties).each(function(p) 69 | { 70 | node.children.push(self.buildTreeModelForProperty(p, data, 'Property')); 71 | }); 72 | _(c.events).each(function(e) 73 | { 74 | node.children.push(self.buildTreeModelForProperty(e, data, 'Event')); 75 | }); 76 | return node; 77 | } 78 | 79 | , buildTreeModelForProperty: function(p, data, label) 80 | { 81 | var node = { 82 | children: [] 83 | , label: label + ' ' + this.makeLink(p, true) 84 | , type: 'method' 85 | }; 86 | return node; 87 | } 88 | 89 | , buildTreeModelForMethod: function(m, data) 90 | { 91 | var node = { 92 | children: [] 93 | , label: 'Method ' + this.makeLink(m, true) 94 | , type: 'method' 95 | } 96 | , self = this; 97 | // if(m.returns) 98 | // { 99 | // node.children.push({ 100 | // children: [] 101 | // , label: 'Returns' 102 | // , type: 'returns' 103 | // }); 104 | // } 105 | return node; 106 | } 107 | }); 108 | 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /jsdoc/src/js/TypesUtil.js: -------------------------------------------------------------------------------- 1 | // @module shortjsdoc.html 2 | // this file add methods to Abstract Application for dealing with types and html markup. 3 | // @class AbstractView @extends Backbone.View 4 | _(AbstractView.prototype).extend({ 5 | 6 | //@method printTag 7 | printTag: function(text, classAttribute, tag) { 8 | tag = tag || 'span'; 9 | classAttribute = classAttribute ||''; 10 | if(text) 11 | { 12 | return '<'+tag+ (classAttribute?(' class="'+classAttribute+'"'):'') +'>'+text+''; 13 | } 14 | return ''; 15 | } 16 | 17 | //@method simpleName @param {String}name 18 | , simpleName: function(name) 19 | { 20 | return this.application.maker.simpleName(name); 21 | } 22 | 23 | //@method makeLink @param {boolean} htmlAnchors will output anchor elements html 24 | , makeLink: function(node, htmlAnchors) 25 | { 26 | // if (!node || !node.type) // no type for this node. This isn't undefined ! This means we just simply doesn't have the information. 27 | // { 28 | // return ''; 29 | // } 30 | var className = node.annotation + '-name'; 31 | var s = htmlAnchors ? (''+node.name+''):''; 62 | return s; 63 | } 64 | 65 | , printLiteralObjectType: function(context) 66 | { 67 | 68 | var self = this; 69 | var buf = []; 70 | context.buffer.push(this.printType(context.type, true)); 71 | var has_only_proto = _(context.type.properties).keys().length===1 && context.type.properties.prototype; 72 | if(has_only_proto) //dirty hack to resolve incompatibility between literal types and Object class inherited props 73 | { 74 | return; 75 | } 76 | if(context.type.name==='Object') 77 | { 78 | context.buffer.push('{') 79 | _(context.type.properties).each(function(value, key) 80 | { 81 | buf.push(key + ': ' + self.printSingleTypeAsString(value, true)); 82 | }); 83 | } 84 | context.buffer.push(buf.join(', ')); 85 | if(context.type.name==='Object') 86 | { 87 | context.buffer.push('}'); 88 | } 89 | } 90 | 91 | // @method printType prints a type as html support generic. This is really a html template function 92 | // @param {Object}context @return {String} the type html 93 | , printType: function(context, ignoreLiteralObject) 94 | { 95 | if(!context || !context.type) 96 | { 97 | return ''; 98 | } 99 | 100 | var self = this; 101 | var href = context.type.nativeTypeUrl || '#class/'+context.type.absoluteName; 102 | var htmlText = context.type.name; 103 | var aclass = (context.type.nativeTypeUrl ? ' type external ' : ' type '); 104 | var iconHtml = context.type.nativeTypeUrl ? '' : ''; 105 | 106 | context.buffer.push(''+iconHtml+htmlText+''); 107 | 108 | if(context.type.properties && !ignoreLiteralObject) 109 | { 110 | this.printLiteralObjectType(context); 111 | } 112 | 113 | else if(context.type.params) 114 | { 115 | context.buffer.push('<'); 116 | for (var i = 0; i < (context.type.params||[]).length; i++) 117 | { 118 | var param = context.type.params[i]; 119 | self.printType({ //recurse! 120 | type:param 121 | , buffer: context.buffer 122 | }); 123 | if(i < context.type.params.length - 1) 124 | { 125 | context.buffer.push(','); 126 | } 127 | } 128 | context.buffer.push('>'); 129 | } 130 | } 131 | 132 | //@method printSingleTypeAsString this is the public method for printing a type - supports any type @param {String} type @return {String} @return {String} the type html 133 | , printSingleTypeAsString: function(type, dontRecurse) 134 | { 135 | var buffer = []; 136 | var context = {type: type, typeTemplate: this.printType, buffer: buffer}; 137 | 138 | this.printType(context); 139 | var typeOutput = buffer.join(''); 140 | return typeOutput; 141 | } 142 | 143 | //@method printTypeAsString @param {Array|Type} type @return {String} the type html 144 | , printTypeAsString: function(type) 145 | { 146 | var self = this; 147 | if(_(type).isArray()) 148 | { 149 | var a = []; 150 | _(type).each(function(t) 151 | { 152 | a.push(self.printSingleTypeAsString(t)); 153 | }); 154 | return a.join('or'); 155 | } 156 | else 157 | { 158 | return this.printSingleTypeAsString(type); 159 | } 160 | } 161 | //@method getTextHtml depends on lib/marked/ - all texts should be printed using this method 162 | , getTextHtml: function(node) 163 | { 164 | if(!node || !node.text) 165 | { 166 | return ''; 167 | } 168 | if(node.text_html_app) 169 | { 170 | return node.text_html_app; 171 | } 172 | 173 | var self2 = this //TODO invitigate why I need self2 and self always binds to other thing than this... 174 | , text = node.text 175 | , type = this.application.textFormat || 'markdown' 176 | , html = _(node.children).find(function(c){return c.annotation==='html'; }) 177 | , markdown = _(node.children).find(function(c){return c.annotation==='markdown'; }); 178 | 179 | if(html) 180 | { 181 | type = 'html'; 182 | } 183 | if(markdown) 184 | { 185 | type = 'markdown'; 186 | } 187 | 188 | // perform text marks replacement. 189 | _(node.textMarks).each(function(mark, markId) 190 | { 191 | if(mark.name === 'link') 192 | { 193 | if(type === 'markdown') 194 | { 195 | text = text.replace(markId, '['+mark.linkLabel+']('+mark.linkUrl+')'); 196 | } 197 | else 198 | { 199 | text = text.replace(markId, '< href="mark.linkUrl" class="text-mark-link">'+mark.linkLabel+''); 200 | } 201 | } 202 | else if(mark.binding) 203 | { 204 | text = text.replace(markId, self2.makeLink(mark.binding, true)); 205 | } 206 | }); 207 | 208 | if(type === 'markdown') 209 | { 210 | text = marked(text); 211 | } 212 | 213 | node.text_html_app = text; 214 | return text; 215 | 216 | } 217 | 218 | //@method printMethod 219 | , printMethod: function(m) 220 | { 221 | var isConstructor = m.annotation==='constructor'; 222 | var s = ''; 223 | var methodName = isConstructor ? this.simpleName(m.ownerClass) : m.name; 224 | if(!isConstructor && m.returns) 225 | { 226 | s += this.printTypeAsString(m.returns) + ' '; 227 | } 228 | 229 | s += '' + methodName + ''; 230 | 231 | return s + ''; 232 | } 233 | 234 | , getInherited: function(c, what) 235 | { 236 | var data = {}; 237 | if(what==='method') 238 | { 239 | data = _(c.methods).clone(); 240 | _(data).extend(c.inherited.methods || {}); 241 | } 242 | return data; 243 | } 244 | 245 | , getClassName: function(absoluteName) 246 | { 247 | return absoluteName.substring(0, absoluteName.lastIndexOf('.')); 248 | } 249 | 250 | , getSimpleName: function(absoluteName) 251 | { 252 | return absoluteName.substring(absoluteName.lastIndexOf('.')+1, absoluteName.length); 253 | } 254 | 255 | , getModuleClasses: function(moduleName, data) 256 | { 257 | var a = []; 258 | _(data.classes).each(function(c) 259 | { 260 | if(c.absoluteName.indexOf(moduleName)===0) 261 | { 262 | a.push(c); 263 | } 264 | }); 265 | return a; 266 | } 267 | 268 | 269 | // TODO: move the following to misc utility class 270 | 271 | //@method parseOptions @return {Object} 272 | , parseOptions: function(options, propSep, valueSep) 273 | { 274 | propSep = propSep || '&'; 275 | valueSep = valueSep || '='; 276 | if(!options) 277 | { 278 | return {}; 279 | } 280 | var params = {}; 281 | _(options.split(propSep)).each(function(p) 282 | { 283 | var a = p.split(valueSep); 284 | if (a.length >= 2) 285 | { 286 | params[a[0]] = a[1]; 287 | if(!a[1] || a[1]==='0' || a[1]==='false') 288 | { 289 | params[a[0]] = false; 290 | } 291 | } 292 | }); 293 | return params; 294 | } 295 | 296 | , getOptionsFromHash: function(hash) 297 | { 298 | hash = hash || window.location.hash; 299 | var options = hash.split('?'); 300 | options = options.length<2 ? '' : options[1]; 301 | return this.parseOptions(options); 302 | } 303 | 304 | , setOptionsToHash: function(hash, newOptions) 305 | { 306 | hash = hash || window.location.hash; 307 | var options = hash.split('?'); 308 | options = options.length<2 ? '' : options[1]; 309 | options = this.parseOptions(options); 310 | _(options).extend(newOptions); 311 | return hash.split('?')[0] + '?' + this.optionsToString(options); 312 | } 313 | 314 | , optionsToString: function(options, propSep, valueSep) 315 | { 316 | propSep = propSep || '&'; 317 | valueSep = valueSep || '='; 318 | var a = []; 319 | _(options).each(function(value, key) 320 | { 321 | a.push(key + valueSep + value); 322 | }); 323 | return a.join(propSep); 324 | } 325 | 326 | 327 | 328 | }); -------------------------------------------------------------------------------- /jsdoc/src/styles/class.less: -------------------------------------------------------------------------------- 1 | .class-hierarchy, .known-subclasses { 2 | ul li { 3 | display: inline; 4 | padding-left: 8px; 5 | } 6 | } 7 | 8 | .inherited { 9 | opacity: 0.5; 10 | /* .property-name, .method-name { 11 | color: #A9B9C7; 12 | }*/ 13 | } 14 | 15 | .params, .params ol, .params li{display: inline;padding: 0;} 16 | 17 | 18 | .method-header, .class-header { 19 | h3 { 20 | margin-top: 26px; 21 | } 22 | } 23 | 24 | 25 | .class-header { 26 | background-color: #ededed; 27 | margin:0px; 28 | } 29 | /*[data-type="main-view-container"], [data-type="header-container"]{margin:-15px;}*/ 30 | 31 | .class-view .partial-text { 32 | font-size: 0.93em; 33 | color: #888888; 34 | font-style: italic; 35 | } -------------------------------------------------------------------------------- /jsdoc/src/styles/header.less: -------------------------------------------------------------------------------- 1 | 2 | .main-header { 3 | background-color: #ededed; 4 | padding: 10px; 5 | 6 | .typeahead1 {} 7 | } 8 | .main-search .tt-dropdown-menu { 9 | overflow-y: auto; 10 | opacity: 0.8; 11 | } 12 | 13 | .twitter-typeahead { 14 | top:-15px; 15 | display: block; 16 | width: 200px; 17 | cursor: pointer; 18 | 19 | .suggestion-value { 20 | text-decoration: underline; 21 | } 22 | .suggestion-type { 23 | font-size: 0.8em; 24 | font-style: italic; 25 | } 26 | } 27 | 28 | .tt-dropdown-menu { 29 | width: 600px; 30 | left: -400px !important; 31 | 32 | @media (max-width:600px) { 33 | left: 0px !important; 34 | } 35 | 36 | background-color: #fff; 37 | border: 1px solid #ccc; 38 | border: 1px solid rgba(0, 0, 0, 0.2); 39 | -webkit-border-radius: 8px; 40 | -moz-border-radius: 8px; 41 | border-radius: 8px; 42 | -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); 43 | -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); 44 | box-shadow: 0 5px 10px rgba(0,0,0,.2); 45 | } 46 | 47 | 48 | .tt-hint { 49 | color: #999 50 | } 51 | 52 | 53 | .tt-suggestion { 54 | padding: 3px 10px; 55 | font-size: 14px; 56 | line-height: 18px; 57 | } 58 | 59 | .tt-suggestion.tt-cursor { 60 | color: #fff; 61 | background-color: #0097cf; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /jsdoc/src/styles/index.less: -------------------------------------------------------------------------------- 1 | 2 | 3 | .metadata-name { 4 | font-weight: bold; 5 | } 6 | -------------------------------------------------------------------------------- /jsdoc/src/styles/main-layout.less: -------------------------------------------------------------------------------- 1 | .main-view-container { 2 | li { 3 | /*list-style: none; */ 4 | /*padding-bottom: 8px;*/ 5 | } 6 | ul { 7 | padding-left: 17px; 8 | } 9 | } 10 | 11 | .container { 12 | padding-right: 0px; 13 | padding-left: 4px; 14 | margin-right: auto; 15 | margin-left: auto; 16 | width: 98%; 17 | } 18 | -------------------------------------------------------------------------------- /jsdoc/src/styles/main.less: -------------------------------------------------------------------------------- 1 | @import "header.less"; 2 | @import "sources.less"; 3 | @import "parse.less"; 4 | @import "tree.less"; 5 | @import "class.less"; 6 | @import "types.less"; 7 | @import "main-layout.less"; 8 | @import "index.less"; 9 | @import "module.less"; 10 | 11 | /* dependencies.less*/ 12 | .loading-message { 13 | margin: 40px auto 0 auto; 14 | display: block; 15 | font-weight: bold; font-size: 24px; 16 | } -------------------------------------------------------------------------------- /jsdoc/src/styles/module.less: -------------------------------------------------------------------------------- 1 | 2 | 3 | .module-class-properties-list li {display: inline;} 4 | .module-class-name {font-size: 1.1em; font-weight: bold;} 5 | .modules .module-name { 6 | margin:1.2em 0 1.4em 0; 7 | font-size: 1.3em; 8 | font-weight:bold; 9 | /*display: block;*/ 10 | } 11 | 12 | .modules .modules-classes-list * { 13 | display: inline; 14 | } 15 | -------------------------------------------------------------------------------- /jsdoc/src/styles/parse.less: -------------------------------------------------------------------------------- 1 | .parse { 2 | textarea { 3 | diaplay: block; 4 | width: 100%; 5 | height: 200px; 6 | } 7 | } -------------------------------------------------------------------------------- /jsdoc/src/styles/sources.less: -------------------------------------------------------------------------------- 1 | .selectedJsDocLine { 2 | border: 3px solid pink; 3 | } 4 | 5 | .linenums>li * { 6 | tab-size: 4; 7 | } 8 | -------------------------------------------------------------------------------- /jsdoc/src/styles/styles.css: -------------------------------------------------------------------------------- 1 | .main-header { 2 | background-color: #ededed; 3 | padding: 10px; 4 | } 5 | .main-search .tt-dropdown-menu { 6 | overflow-y: auto; 7 | opacity: 0.8; 8 | } 9 | .twitter-typeahead { 10 | top: -15px; 11 | display: block; 12 | width: 200px; 13 | cursor: pointer; 14 | } 15 | .twitter-typeahead .suggestion-value { 16 | text-decoration: underline; 17 | } 18 | .twitter-typeahead .suggestion-type { 19 | font-size: 0.8em; 20 | font-style: italic; 21 | } 22 | .tt-dropdown-menu { 23 | width: 600px; 24 | left: -400px !important; 25 | background-color: #fff; 26 | border: 1px solid #ccc; 27 | border: 1px solid rgba(0, 0, 0, 0.2); 28 | -webkit-border-radius: 8px; 29 | -moz-border-radius: 8px; 30 | border-radius: 8px; 31 | -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 32 | -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 33 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); 34 | } 35 | @media (max-width: 600px) { 36 | .tt-dropdown-menu { 37 | left: 0px !important; 38 | } 39 | } 40 | .tt-hint { 41 | color: #999999; 42 | } 43 | .tt-suggestion { 44 | padding: 3px 10px; 45 | font-size: 14px; 46 | line-height: 18px; 47 | } 48 | .tt-suggestion.tt-cursor { 49 | color: #fff; 50 | background-color: #0097cf; 51 | } 52 | .selectedJsDocLine { 53 | border: 3px solid pink; 54 | } 55 | .linenums > li * { 56 | tab-size: 4; 57 | } 58 | .parse textarea { 59 | diaplay: block; 60 | width: 100%; 61 | height: 200px; 62 | } 63 | .main-view-container .tree li { 64 | list-style: none; 65 | /*padding: 0;*/ 66 | } 67 | .tree-node-type-module { 68 | padding-bottom: 16px; 69 | } 70 | .tree-node-type-module .module-name { 71 | font-size: 1.1em; 72 | font-weight: bold; 73 | } 74 | /*'.tree {\n'+ 75 | ' min-height:20px;\n'+ 76 | ' padding:19px;\n'+ 77 | ' margin-bottom:20px;\n'+ 78 | ' background-color:#fbfbfb;\n'+ 79 | ' border:1px solid #999;\n'+ 80 | ' -webkit-border-radius:4px;\n'+ 81 | ' -moz-border-radius:4px;\n'+ 82 | ' border-radius:4px;\n'+ 83 | ' -webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);\n'+ 84 | ' -moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);\n'+ 85 | ' box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05)\n'+ 86 | '}\n'+ 87 | '.tree li {\n'+ 88 | ' list-style-type:none;\n'+ 89 | ' margin:0;\n'+ 90 | ' padding:10px 5px 0 5px;\n'+ 91 | ' position:relative\n'+ 92 | '}\n'+ 93 | '.tree li::before, .tree li::after {\n'+ 94 | ' content:\'\';\n'+ 95 | ' left:-20px;\n'+ 96 | ' position:absolute;\n'+ 97 | ' right:auto\n'+ 98 | '}\n'+ 99 | '.tree li::before {\n'+ 100 | ' border-left:1px solid #999;\n'+ 101 | ' bottom:50px;\n'+ 102 | ' height:100%;\n'+ 103 | ' top:0;\n'+ 104 | ' width:1px\n'+ 105 | '}\n'+ 106 | '.tree li::after {\n'+ 107 | ' border-top:1px solid #999;\n'+ 108 | ' height:20px;\n'+ 109 | ' top:25px;\n'+ 110 | ' width:25px\n'+ 111 | '}\n'+ 112 | '.tree li span {\n'+ 113 | ' -moz-border-radius:5px;\n'+ 114 | ' -webkit-border-radius:5px;\n'+ 115 | ' border:1px solid #999;\n'+ 116 | ' border-radius:5px;\n'+ 117 | ' display:inline-block;\n'+ 118 | ' padding:3px 8px;\n'+ 119 | ' text-decoration:none\n'+ 120 | '}\n'+ 121 | '.tree li.parent_li>span {\n'+ 122 | ' cursor:pointer\n'+ 123 | '}\n'+ 124 | '.tree>ul>li::before, .tree>ul>li::after {\n'+ 125 | ' border:0\n'+ 126 | '}\n'+ 127 | '.tree li:last-child::before {\n'+ 128 | ' height:30px\n'+ 129 | '}\n'+ 130 | '.tree li.parent_li>span:hover' + 131 | (TreeWidget.cssOptions.hoverChildren ? ', .tree li.parent_li>span:hover+ul li span ' : '') + 132 | '{\n'+ 133 | ' background:'+TreeWidget.cssOptions.hoverColor+';\n'+ 134 | ' border:1px solid #94a0b4;\n'+ 135 | ' color:#000\n'+ 136 | '}\n'+*/ 137 | .class-hierarchy ul li, 138 | .known-subclasses ul li { 139 | display: inline; 140 | padding-left: 8px; 141 | } 142 | .inherited { 143 | opacity: 0.5; 144 | /* .property-name, .method-name { 145 | color: #A9B9C7; 146 | }*/ 147 | } 148 | .params, 149 | .params ol, 150 | .params li { 151 | display: inline; 152 | padding: 0; 153 | } 154 | .method-header h3, 155 | .class-header h3 { 156 | margin-top: 26px; 157 | } 158 | .class-header { 159 | background-color: #ededed; 160 | margin: 0px; 161 | } 162 | /*[data-type="main-view-container"], [data-type="header-container"]{margin:-15px;}*/ 163 | .class-view .partial-text { 164 | font-size: 0.93em; 165 | color: #888888; 166 | font-style: italic; 167 | } 168 | .external .glyphicon { 169 | /*padding-left: 5px;*/ 170 | font-size: 0.8em; 171 | } 172 | .type { 173 | padding-right: 6px; 174 | } 175 | .type-separator { 176 | padding-right: 6px; 177 | } 178 | .main-view-container li { 179 | /*list-style: none; */ 180 | /*padding-bottom: 8px;*/ 181 | } 182 | .main-view-container ul { 183 | padding-left: 17px; 184 | } 185 | .container { 186 | padding-right: 0px; 187 | padding-left: 4px; 188 | margin-right: auto; 189 | margin-left: auto; 190 | width: 98%; 191 | } 192 | .metadata-name { 193 | font-weight: bold; 194 | } 195 | .module-class-properties-list li { 196 | display: inline; 197 | } 198 | .module-class-name { 199 | font-size: 1.1em; 200 | font-weight: bold; 201 | } 202 | .modules .module-name { 203 | margin: 1.2em 0 1.4em 0; 204 | font-size: 1.3em; 205 | font-weight: bold; 206 | /*display: block;*/ 207 | } 208 | .modules .modules-classes-list * { 209 | display: inline; 210 | } 211 | /* dependencies.less*/ 212 | .loading-message { 213 | margin: 40px auto 0 auto; 214 | display: block; 215 | font-weight: bold; 216 | font-size: 24px; 217 | } 218 | -------------------------------------------------------------------------------- /jsdoc/src/styles/tree.less: -------------------------------------------------------------------------------- 1 | .main-view-container .tree li { 2 | list-style: none; 3 | /*padding: 0;*/ 4 | } 5 | 6 | .tree-node-type-module{ 7 | padding-bottom: 16px; 8 | .module-name{ 9 | font-size: 1.1em; 10 | font-weight: bold; 11 | } 12 | } 13 | 14 | /*'.tree {\n'+ 15 | ' min-height:20px;\n'+ 16 | ' padding:19px;\n'+ 17 | ' margin-bottom:20px;\n'+ 18 | ' background-color:#fbfbfb;\n'+ 19 | ' border:1px solid #999;\n'+ 20 | ' -webkit-border-radius:4px;\n'+ 21 | ' -moz-border-radius:4px;\n'+ 22 | ' border-radius:4px;\n'+ 23 | ' -webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);\n'+ 24 | ' -moz-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05);\n'+ 25 | ' box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.05)\n'+ 26 | '}\n'+ 27 | '.tree li {\n'+ 28 | ' list-style-type:none;\n'+ 29 | ' margin:0;\n'+ 30 | ' padding:10px 5px 0 5px;\n'+ 31 | ' position:relative\n'+ 32 | '}\n'+ 33 | '.tree li::before, .tree li::after {\n'+ 34 | ' content:\'\';\n'+ 35 | ' left:-20px;\n'+ 36 | ' position:absolute;\n'+ 37 | ' right:auto\n'+ 38 | '}\n'+ 39 | '.tree li::before {\n'+ 40 | ' border-left:1px solid #999;\n'+ 41 | ' bottom:50px;\n'+ 42 | ' height:100%;\n'+ 43 | ' top:0;\n'+ 44 | ' width:1px\n'+ 45 | '}\n'+ 46 | '.tree li::after {\n'+ 47 | ' border-top:1px solid #999;\n'+ 48 | ' height:20px;\n'+ 49 | ' top:25px;\n'+ 50 | ' width:25px\n'+ 51 | '}\n'+ 52 | '.tree li span {\n'+ 53 | ' -moz-border-radius:5px;\n'+ 54 | ' -webkit-border-radius:5px;\n'+ 55 | ' border:1px solid #999;\n'+ 56 | ' border-radius:5px;\n'+ 57 | ' display:inline-block;\n'+ 58 | ' padding:3px 8px;\n'+ 59 | ' text-decoration:none\n'+ 60 | '}\n'+ 61 | '.tree li.parent_li>span {\n'+ 62 | ' cursor:pointer\n'+ 63 | '}\n'+ 64 | '.tree>ul>li::before, .tree>ul>li::after {\n'+ 65 | ' border:0\n'+ 66 | '}\n'+ 67 | '.tree li:last-child::before {\n'+ 68 | ' height:30px\n'+ 69 | '}\n'+ 70 | '.tree li.parent_li>span:hover' + 71 | (TreeWidget.cssOptions.hoverChildren ? ', .tree li.parent_li>span:hover+ul li span ' : '') + 72 | '{\n'+ 73 | ' background:'+TreeWidget.cssOptions.hoverColor+';\n'+ 74 | ' border:1px solid #94a0b4;\n'+ 75 | ' color:#000\n'+ 76 | '}\n'+*/ -------------------------------------------------------------------------------- /jsdoc/src/styles/types.less: -------------------------------------------------------------------------------- 1 | 2 | .external .glyphicon { 3 | /*padding-left: 5px;*/ 4 | font-size: 0.8em; 5 | } 6 | 7 | .type { 8 | padding-right: 6px; 9 | } 10 | 11 | .type-separator 12 | { 13 | padding-right: 6px; 14 | } 15 | 16 | 17 | -------------------------------------------------------------------------------- /jsdoc/src/templates/application.html: -------------------------------------------------------------------------------- 1 |
    2 |
    3 |
    4 |
    -------------------------------------------------------------------------------- /jsdoc/src/templates/class.html: -------------------------------------------------------------------------------- 1 | <% 2 | var self = this; 3 | %> 4 | 5 |
    6 |
    7 |

    Class <%= this.makeLink(this.jsdoc, true) %>

    8 |
    9 |
    10 | <% if (this.jsdoc.extends && this.jsdoc.absoluteName != this.jsdoc.extends.absoluteName) { %> 11 |

    Extends <%= this.printTypeAsString(this.jsdoc.extends)%>

    12 | <% } %> 13 |
    14 |
    15 |

    Module <%= this.makeLink(this.jsdoc.module, true) %>

    16 |
    17 |
    18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | <% var template = this.application.templates.classSummary;%> 27 | <%= template.apply(this, arguments) %> 28 | 29 |
    30 | 31 |
    32 | 33 | 34 | 35 | <% if(this.jsdoc.constructors && this.jsdoc.constructors.length) { %> 36 |

    Constructors

    37 |
      38 | <% 39 | _(this.jsdoc.constructors).each(function(method) { %> 40 | <%= self.printMethod(method) %> 41 |
    • 42 | <% if(method.params && method.params.length) { %> 43 | Parameters: 44 |
        45 | <% _(method.params).each(function(param){ %> 46 |
      1. 47 | <%= param.name %> 48 | <%= self.printTypeAsString(param.type) %> 49 |
      2. 50 | <% }); %> 51 |
      52 | <% } %> 53 |
    • 54 | <% }); %> 55 |
    56 | <% } %> 57 | 58 | 59 | 60 | 61 | <% if(this.properties && _(this.properties).keys().length) { %> 62 |

    Properties

    63 |
      64 | <% 65 | var self = this; 66 | _(this.properties).each(function(p) { 67 | var inherited = !JsDocMaker.classOwnsProperty(self.jsdoc, p); 68 | //TODO: perform this in the view or plugin 69 | 70 | var inheritedByName = p.absoluteName.substring(0, p.absoluteName.lastIndexOf('.')); 71 | var inheritedBy = self.application.data.classes[inheritedByName] || {}; 72 | 73 | %> 74 |
    • 75 | <%= p.name %> 76 | <%= self.printTypeAsString(p.type) %> 77 | <%= !inherited ? '' : ('(inherited by ' + self.printTypeAsString(inheritedBy) + ')') %> 78 | <% if (self.options.text) {%> <%= self.makePartialText(p)%><% }%> 79 |
    • 80 | <% }); %> 81 |
    82 | <% } %> 83 | 84 | 85 | <% if(this.attributes && _(this.attributes).keys().length) { %> 86 |

    attributes

    87 |
      88 | <% 89 | var self = this; 90 | _(this.attributes).each(function(p) { 91 | var inherited = !JsDocMaker.classOwnsProperty(self.jsdoc, p); 92 | //TODO: perform this in the view or plugin 93 | 94 | var inheritedByName = p.absoluteName.substring(0, p.absoluteName.lastIndexOf('.')); 95 | var inheritedBy = self.application.data.classes[inheritedByName] || {}; 96 | 97 | %> 98 |
    • 99 | <%= p.name %> 100 | <%= self.printTypeAsString(p.type) %> 101 | <%= !inherited ? '' : ('(inherited by ' + self.printTypeAsString(inheritedBy) + ')') %> 102 | <% if (self.options.text) {%> <%= self.makePartialText(p)%><% }%> 103 |
    • 104 | <% }); %> 105 |
    106 | <% } %> 107 | 108 | 109 | 110 | <% if(this.events && _(this.events).keys().length) {%> 111 |

    Events

    112 |
      113 | <% 114 | var self = this; 115 | _(this.events).each(function(p) { 116 | var inherited = !JsDocMaker.classOwnsProperty(self.jsdoc, p); 117 | //TODO: perform this in the view or plugin 118 | 119 | var inheritedByName = p.absoluteName.substring(0, p.absoluteName.lastIndexOf('.')); 120 | var inheritedBy = self.application.data.classes[inheritedByName] || {}; 121 | 122 | %> 123 |
    • 124 | <%= p.name %> 125 | <%= self.printTypeAsString(p.type) %> 126 | <%= !inherited ? '' : ('(inherited by ' + self.printTypeAsString(inheritedBy) + ')') %> 127 | <% if (self.options.text) {%> <%= self.makePartialText(p)%><% }%> 128 |
    • 129 | <% }); %> 130 |
    131 | <% } %> 132 | 133 | 134 | 135 | 136 | <% if(this.methods && _(this.methods).keys().length) { %> 137 |

    Methods

    138 |
      139 | <% 140 | _(this.methods).each(function(method) { 141 | var inherited = !JsDocMaker.classOwnsProperty(self.jsdoc, method); 142 | var inheritedByName = method.absoluteName.substring(0, method.absoluteName.lastIndexOf('.')); 143 | var inheritedBy = self.application.data.classes[inheritedByName] || {}; 144 | %> 145 | 146 |
    • 147 | <%= self.makeLink(method, true)%> 148 | <% if(method.params && method.params.length) { %> 149 | Parameters: 150 |
        151 | <% _(method.params).each(function(param){ %> 152 |
      1. 153 | <%= param.name %>: 154 | <%= self.printTypeAsString(param.type) %> 155 | <%= !inherited ? '' : ('(inherited by ' + self.printTypeAsString(inheritedBy) + ')') %> 156 |
      2. 157 | <% }); %> 158 |
      159 | <% } %> 160 | 161 | 162 | 163 | <% if(method.returns && (method.returns.type || method.returns.text)) {%> 164 | Returns: <%= self.printTypeAsString(method.returns.type) %> 165 | 166 | <% } %> 167 | 168 | <% if (self.options.text) {%> <%= self.makePartialText(method)%><% }%> 169 |
    • 170 | <% }); %> 171 |
    172 | <% } %> 173 | 174 | 175 | 176 | 177 | 178 |
    179 | 180 |
    181 | 182 | <% if(this.hierarchy && this.hierarchy.length>2) {%> 183 |
    184 |

    Class Hierarchy

    185 |
      186 | <% _(_(this.hierarchy).reverse()).each(function(c){ %> 187 |
    • <%= c.name %>
    • 188 | <% }); %> 189 |
    190 |
    191 | <%}%> 192 | 193 | <% if(this.knownSubclasses && this.knownSubclasses.length) {%> 194 | 195 |
    196 |

    Known Subclasses

    197 |
      198 | <% _(this.knownSubclasses).each(function(c){ %> 199 |
    • <%= c.name %>
    • 200 | <% }); %> 201 |
    202 |
    203 | <%}%> 204 | 205 |

    Search Class Usage

    206 | 207 | <% var summary_text = this.jsdoc.textHtml || self.getTextHtml(this.jsdoc.text) || this.jsdoc.text || ''; %> 208 | 209 | <% if(summary_text) {%> 210 |

    Summary

    211 | 212 |
    213 | <%= summary_text %> 214 |
    215 | <% } %> 216 | 217 |
    218 | 219 |
    220 |
    221 | -------------------------------------------------------------------------------- /jsdoc/src/templates/classSummary.html: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /jsdoc/src/templates/classes.html: -------------------------------------------------------------------------------- 1 | <% var data = this.application.data; %> 2 | 3 |

    Classes

    4 | 5 | 6 |
      7 | <% _(data.classes).each(function(c) { %> 8 |
    • <%= c.name %>
    • 9 | <% }); %> 10 |
    11 | -------------------------------------------------------------------------------- /jsdoc/src/templates/dependencies.html: -------------------------------------------------------------------------------- 1 |

    > 2 | <%= this.options.includeNativeClasses ? 'Include' : 'Don\'t include' %> native classes

    3 | 4 |

    > 5 | <%= this.options.includeExtends ? 'Include' : 'Don\'t include' %> inheritance

    6 | 7 |

    The following is a graph showing dependencies between classes. A class A depends on a class B if any A property or method references the type B or contains an explicit dependency declaration to B using '@depends class B' :

    8 | 9 |
    Calculating, please stand by...
    10 | 11 |
    -------------------------------------------------------------------------------- /jsdoc/src/templates/file.html: -------------------------------------------------------------------------------- 1 |

    File <%= this.jsdoc.fileName%>

    2 | 3 |
    4 | <%= this.fileContent %>
    5 | 
    -------------------------------------------------------------------------------- /jsdoc/src/templates/header.html: -------------------------------------------------------------------------------- 1 | <% var metadata = this.application.data.projectMetadata; %> 2 |
    3 |
    4 | 5 | 6 | 7 | 8 | 9 | 13 | . 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Index 41 | Search 42 | 43 | 44 | 45 | 46 |
    47 |
    -------------------------------------------------------------------------------- /jsdoc/src/templates/hierarchytree.html: -------------------------------------------------------------------------------- 1 | <% var data = this.application.data; %> 2 | 3 | <%= data.projectMetadata && this.application.templates['project-metadata'].apply(this, arguments) %> 4 | 5 |

    Class Hierarchy Tree

    6 | 7 | 8 | 9 | 10 | 11 |
    12 | -------------------------------------------------------------------------------- /jsdoc/src/templates/index.html: -------------------------------------------------------------------------------- 1 | <% var data = this.application.data; %> 2 | 3 | <%= data.projectMetadata && this.application.templates['project-metadata'].apply(this, arguments) %> 4 | 5 |

    Take a look at the Full Abstract Syntax Tree (AST) View

    6 |

    Or to the Full Class Hierarchy tree

    7 | 8 | <%= this.application.templates['modules'].apply(this, arguments) %> 9 | 10 | <%= this.application.templates['classes'].apply(this, arguments) %> 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /jsdoc/src/templates/method.html: -------------------------------------------------------------------------------- 1 | <% var self = this;%> 2 | 3 | 4 | 5 |
    6 |
    7 |

    8 | <% if(this.isConstructor){ %> 9 |

    Constructor

    10 | <% } else {%> 11 |

    Method <%= this.jsdoc.name%>

    12 | <% } %> 13 | 14 |
    15 | 20 | 21 |
    22 |

    Of Module <%= this.makeLink(this.ownerClass.module, true) %>

    23 |
    24 |
    25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 |
    33 |
    34 | 35 | <% if( this.jsdoc.params.length ) { %> 36 |

    Parameters

    37 | <% } %> 38 | 39 |
      40 | <% _(this.jsdoc.params).each(function(param) { %> 41 |
    • 42 | <%= param.name%>: <%= self.printTypeAsString(param.type) %> 43 | <%= self.getTextHtml(param) %> 44 |
    • 45 | 46 | <% }); %> 47 |
    48 | 49 | 50 | 51 | <% if(!this.isConstructor) { %> 52 | <%if (this.jsdoc.returns && (this.jsdoc.returns.type || this.jsdoc.returns.text) ) { %> 53 |

    Returns

    54 | <%= self.printTypeAsString(this.jsdoc.returns.type) %> 55 | 56 | <% if(this.jsdoc.returns.text){ %> 57 | <%= self.getTextHtml(this.jsdoc.returns) %> 58 | <% } %> 59 | 60 | <% }%> 61 | <% }%> 62 | 63 | 64 | 65 | 66 | <% if(this.jsdoc.throws && this.jsdoc.throws.length) { %> 67 | 68 |

    Throws

    69 | 70 |
      71 | <% _(this.jsdoc.throws).each(function(t) { %> 72 |
    • 73 | <%= self.printTypeAsString(t.type) %> 74 | <%= self.getTextHtml(t) %> 75 |
    • 76 | <% }); %> 77 |
    78 | 79 | <% } %> 80 |
    81 | 82 | 83 | 84 |
    85 | <% if (this.jsdoc.text) { %> 86 |
    87 | <%= this.jsdoc.textHtml %> 88 |
    89 | <% } %> 90 | 91 |
    92 |
    93 |
    94 | 95 | 96 | -------------------------------------------------------------------------------- /jsdoc/src/templates/module.html: -------------------------------------------------------------------------------- 1 | <% 2 | var self = this; 3 | %> 4 | 5 |

    Module <%= this.jsdoc.name%>

    6 | 7 | <% if (this.jsdoc.text) { %> 8 |
    9 | <%= this.jsdoc.textHtml %> 10 |
    11 | <% }%> 12 | 13 |

    Classes

    14 | 15 |
      16 | <% _(this.classes).each(function(c) { %> 17 |
    • 18 | <%= c.name %> 19 | 20 |
        21 | <% _(c.methods).each(function(m){ %> 22 |
      • <%= m.name%>(), 23 | <%}) %> 24 | <% _(c.properties).each(function(m){ %> 25 |
      • <%= m.name%>, 26 | <%}) %> 27 |
      28 | <% _(c.attributes).each(function(m){ %> 29 |
    • <%= m.name%>, 30 | <%}) %> 31 |
    32 | 33 | <% }); %> 34 | -------------------------------------------------------------------------------- /jsdoc/src/templates/modules.html: -------------------------------------------------------------------------------- 1 |
    2 | 3 |

    Modules

    4 | 5 | <% var data = this.application.data; 6 | var self = this; %> 7 |
      8 | <% _(data.modules).each(function(moduleBody, moduleName) { %> 9 |
    • <%= moduleName %> 10 |
        11 | <% 12 | /* TODO: make a view */ 13 | var moduleClasses = self.getModuleClasses(moduleName, self.application.data); 14 | _(moduleClasses).each(function(c) { %> 15 |
      • <%= c.name %>,
      • 16 | <% }); %> 17 |
      18 |
    • 19 | <% }); %> 20 |
    21 | 22 |
    -------------------------------------------------------------------------------- /jsdoc/src/templates/parse.html: -------------------------------------------------------------------------------- 1 |

    Parse your code online!

    2 |

    Please paste your commeted code in the following area and it will be loaded automatically.

    3 | 17 | Clean previous data ? 18 | 19 | -------------------------------------------------------------------------------- /jsdoc/src/templates/project-metadata.html: -------------------------------------------------------------------------------- 1 | <% var metaData = this.application.data.projectMetadata; %> 2 | 3 |

    Project <%= metaData.name%> contains #<%= _(this.application.data.modules).keys().length %> modules and #<%= _(this.application.data.classes).keys().length %> classes.

    4 | 5 |
    6 | <% _(metaData).each(function(value, name) { 7 | if(_(['name', 'description', 'author', 'license', 'version']).contains(name)) { %> 8 | 9 | <% } } ); %> 10 |
    11 | -------------------------------------------------------------------------------- /jsdoc/src/templates/property.html: -------------------------------------------------------------------------------- 1 |

    <%= this.propertyLabel %> <%= this.jsdoc.name%>

    2 | 3 |

    Of class 4 | <%= this.simpleName(this.jsdoc.ownerClass) %> 5 |

    6 | 7 | <% if (this.jsdoc.text) { %> 8 |
    9 | <%= this.jsdoc.textHtml %> 10 |
    11 | <% } %> 12 | 13 | 14 |

    Type

    15 | <%= this.printTypeAsString(this.jsdoc.type) %> 16 | 17 | 18 |
    -------------------------------------------------------------------------------- /jsdoc/src/templates/search.html: -------------------------------------------------------------------------------- 1 |

    Query:

    2 | 3 |
    4 |

    Keywords:

    5 |

    value="<%=this.query.keywords%>"> properties referencing given type name

    6 | 7 |
    8 | 9 |

    Results

    10 | 11 |

    <%= this.results ? '' : 'Searching... please wait.'%>

    12 | -------------------------------------------------------------------------------- /jsdoc/src/templates/sources.html: -------------------------------------------------------------------------------- 1 |

    Sources

    2 |

    File <%= this.jsdoc.fileName %>

    3 |
    <%- this.sourceSubset %>
    -------------------------------------------------------------------------------- /jsdoc/src/templates/tree.html: -------------------------------------------------------------------------------- 1 | <% var data = this.application.data; %> 2 | 3 | <%= data.projectMetadata && this.application.templates['project-metadata'].apply(this, arguments) %> 4 | 5 |

    Abstract Syntax Tree

    6 | 7 |

    From modules to classes and properties...

    8 | 9 | 10 | 11 | 12 | 13 |
    14 | -------------------------------------------------------------------------------- /jsdoc/src/templates/typeaheadSuggestion.html: -------------------------------------------------------------------------------- 1 |
    2 | <%= value%> (<%= node.annotation%> 3 | <% if(_(['property', 'method', 'attribute', 'event']).contains(node.annotation)) {%> 4 | of class <%= node.ownerClass%> 5 | <% }%>) 6 | 7 |
    -------------------------------------------------------------------------------- /lib/Adapters/incrementalDOMAdapter.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML.Adapters 2 | //@class IncrementalDOMAdapter @extend Adapter 3 | var adapter = { 4 | //@property {String} Name 5 | name: 'ID' 6 | //@method defineAttribute 7 | //@param {CodeGenerationContext} code_generation_context 8 | //@param {String} object_name Name of the object used to accumulate the result of the code generation process 9 | //@param {String} property_name Name of the property to define. Please notice that this value will come formatted. This means that if it is a string it will already have its quotes. 10 | // Besides notice that it can also be a piece of code 11 | //@return {String} 12 | , defineAttribute: function (code_generation_context, object_name, property_name) 13 | { 14 | 'use strict'; 15 | 16 | return object_name + '['+property_name+']="";'; 17 | } 18 | //@method setPropertysValue 19 | //@param {CodeGenerationContext} code_generation_context 20 | //@param {String} property_definition String generated by the invocation of the method defineProperty 21 | //@param {String} property_accumulated_values Result of the code generation process applied to all the properties value 22 | //@return {String} 23 | , setAttributeValue: function (code_generation_context, property_definition, property_accumulated_values) 24 | { 25 | 'use strict'; 26 | 27 | return property_definition + property_accumulated_values; 28 | } 29 | //@method accumulatePropertysValue 30 | //@param {CodeGenerationContext} code_generation_context 31 | //@param {String} object_name Name of the object used to accumulate the result of the code generation process 32 | //@param {String} property_value Value of the property to set 33 | //@return {String} 34 | , accumulateAttributeValue: function (code_generation_context, object_name, property_value) 35 | { 36 | 'use strict'; 37 | 38 | return object_name + '["'+code_generation_context.keyName+'"]+=' + property_value +';'; 39 | } 40 | }; 41 | 42 | module.exports = adapter; -------------------------------------------------------------------------------- /lib/Adapters/reactAdapter.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML.Adapters 2 | //@class ReactAdapter @extend Adapter 3 | //This class is by NO mean try to be a production ready solution. There are MANY implication on using this code for any purpose rather than simple tests. 4 | //Make sure you understand how this conversion works in order to used for anything. 5 | var adapter = { 6 | //@property {String} Name 7 | name: 'R' 8 | //@property {String} emptyTagCollection Specify the returned string when a block tag element has none children 9 | , emptyTagCollection: '[]' 10 | //@method defineAttribute 11 | //@param {CodeGenerationContext} code_generation_context 12 | //@param {String} object_name Name of the object used to accumulate the result of the code generation process 13 | //@param {String} property_name Name of the property to define. Please notice that this value will come formatted. This means that if it is a string it will already have its quotes. 14 | // Besides notice that it can also be a piece of code 15 | //@return {String} 16 | , defineAttribute: function (code_generation_context, object_name, property_name) 17 | { 18 | 'use strict'; 19 | 20 | //This is a simple hack to avoid having to create a new plugin just for this 21 | if (property_name === '"class"') 22 | { 23 | property_name = '"className"'; 24 | code_generation_context.keyName = 'className'; 25 | } 26 | 27 | return object_name + '['+property_name+']="";'; 28 | } 29 | //@method accumulateFinalAttributesResult Wrap up the final result after all attributes were converted to code 30 | //@param {CodeGenerationContext} attributes_result 31 | //@param {String} code_generation_context 32 | //@return {String} 33 | , accumulateFinalAttributesResult: function (code_generation_context, attributes_result) 34 | { 35 | 'use strict'; 36 | 37 | if (attributes_result) 38 | { 39 | return '(function (){var '+code_generation_context.objectName+' = {}; ' + attributes_result + 'return '+code_generation_context.objectName+';})()'; 40 | } 41 | return 'null'; 42 | } 43 | //@method setPropertysValue 44 | //@param {CodeGenerationContext} code_generation_context 45 | //@param {String} property_definition String generated by the invocation of the method defineProperty 46 | //@param {String} property_accumulated_values Result of the code generation process applied to all the properties value 47 | //@return {String} 48 | , setAttributeValue: function (code_generation_context, property_definition, property_accumulated_values) 49 | { 50 | 'use strict'; 51 | 52 | return property_definition + property_accumulated_values; 53 | } 54 | //@method accumulatePropertysValue 55 | //@param {CodeGenerationContext} code_generation_context 56 | //@param {String} object_name Name of the object used to accumulate the result of the code generation process 57 | //@param {String} property_value Value of the property to set 58 | //@return {String} 59 | , accumulateAttributeValue: function (code_generation_context, object_name, property_value) 60 | { 61 | 'use strict'; 62 | 63 | return object_name + '["'+code_generation_context.keyName+'"]+=' + property_value +';'; 64 | } 65 | //@method defineBlockTag 66 | //@param {CodeGenerationContext} code_generation_context 67 | //@param {String} attributes_result Result of generating the code to all of the tag attributes 68 | //@param {String} children_result Accumulated result for all tag's children 69 | //@return {String} 70 | , defineBlockTag: function (code_generation_context, tag_type, attributes_result, children_result) 71 | { 72 | 'use strict'; 73 | 74 | return 'reactCreateElementWrapper("' + tag_type + '",'+ attributes_result + (children_result !== this.emptyTagCollection ? ',' + children_result : '')+')'; 75 | } 76 | //@method defineSingleTag 77 | //@param {CodeGenerationContext} code_generation_context 78 | //@param {String} attributes_result Result of generating the code to all of the tag attributes 79 | //@return {String} 80 | , defineSingleTag: function (code_generation_context, tag_type, attributes_result) 81 | { 82 | 'use strict'; 83 | 84 | return 'reactCreateElementWrapper("' + tag_type + '",'+ attributes_result+')'; 85 | } 86 | //@method defineTextTag 87 | //@param {CodeGenerationContext} code_generation_context 88 | //@param {String} text Take into account that this variable can contain code to be evaluated! 89 | //@return {String} 90 | , defineTextTag: function (code_generation_context, text) 91 | { 92 | 'use strict'; 93 | 94 | return text; 95 | } 96 | //@method accumulateFinalTagsResult Wrap up the final result get after all tags were converted to code. Please notice that at this point the string code 97 | //passed in generation_result parameter contains the entire resulting code 98 | //@param {CodeGenerationOptions} options 99 | //@param {CodeGenerationResult} geneation_result 100 | //@return {geneation_result} 101 | , accumulateFinalTagsResult: function (options, geneation_result) 102 | { 103 | 'use strict'; 104 | 105 | if (!options.notGenerateContext) 106 | { 107 | var deps = geneation_result.contextName + (geneation_result.externalDependencies.length > 0 ? ',' +geneation_result.externalDependenciesObjectName : '' ); 108 | 109 | geneation_result.value = this._removeBrackets(geneation_result.value); 110 | 111 | geneation_result.value = 112 | 'function ('+deps+') { return React.createClass({ render: function () { '+reactCreateElementWrapper.toString()+' return ' + geneation_result.value + '; }});}'; 113 | } 114 | 115 | return geneation_result; 116 | } 117 | 118 | //@method _removeBrackets Auxiliary method to remove bracket generated by the fist call to the Tags iteration method (iterateOverTagNodes) 119 | //@param {String} code Code to clean 120 | //@return {String} 121 | , _removeBrackets: function (code) 122 | { 123 | 'use strict'; 124 | 125 | if (code.indexOf('[') === 0) 126 | { 127 | code = code.substr(1); 128 | } 129 | if (code.indexOf(']', code.length - 1) !== -1) 130 | { 131 | code = code.substr(0, code.length -1); 132 | } 133 | return code; 134 | } 135 | }; 136 | 137 | function reactCreateElementWrapper (tag_type, attributes, children) 138 | { 139 | var params = children || []; 140 | params.unshift(tag_type, attributes); 141 | 142 | return React.createElement.apply(React.createElement, params); 143 | } 144 | 145 | module.exports = adapter; -------------------------------------------------------------------------------- /lib/Adapters/virtualDOMAdapter.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML.Adapters 2 | //@class Adapter 3 | var adapter = { 4 | //@property {String} Name 5 | name: 'VD' 6 | //@property {String} emptyTagCollection Specify the returned string when a block tag element has none children 7 | , emptyTagCollection: '[]' 8 | //@method defineAttribute 9 | //@param {CodeGenerationContext} code_generation_context 10 | //@param {String} object_name Name of the object used to accumulate the result of the code generation process 11 | //@param {String} property_name Name of the property to define. Please notice that this value will come formatted. This means that if it is a string it will already have its quotes. 12 | // Besides notice that it can also be a piece of code 13 | //@return {String} 14 | , defineAttribute: function (code_generation_context, object_name, property_name) 15 | { 16 | 'use strict'; 17 | 18 | return object_name + '['+property_name+']="";'; 19 | } 20 | //@method accumulateFinalAttributesResult Wrap up the final result get after all attributes were converted to code 21 | //@param {CodeGenerationContext} code_generation_context 22 | //@param {String} attributes_result 23 | //@return {String} 24 | , accumulateFinalAttributesResult: function (code_generation_context, attributes_result) 25 | { 26 | 'use strict'; 27 | 28 | if (attributes_result) 29 | { 30 | return '(function (){var '+code_generation_context.objectName+' = {}; ' + attributes_result + 'return {attributes: '+code_generation_context.objectName+'};})()'; 31 | } 32 | return '{}'; 33 | } 34 | //@method setPropertysValue 35 | //@param {CodeGenerationContext} code_generation_context 36 | //@param {String} property_definition String generated by the invocation of the method defineProperty 37 | //@param {String} property_accumulated_values Result of the code generation process applied to all the properties value 38 | //@return {String} 39 | , setAttributeValue: function (code_generation_context, property_definition, property_accumulated_values) 40 | { 41 | 'use strict'; 42 | 43 | return property_definition + property_accumulated_values; 44 | } 45 | //@method accumulatePropertysValue 46 | //@param {CodeGenerationContext} code_generation_context 47 | //@param {String} object_name Name of the object used to accumulate the result of the code generation process 48 | //@param {String} property_value Value of the property to set 49 | //@return {String} 50 | , accumulateAttributeValue: function (code_generation_context, object_name, property_value) 51 | { 52 | 'use strict'; 53 | 54 | return object_name + '["'+code_generation_context.keyName+'"]+=' + property_value +';'; 55 | } 56 | //@method defineBlockTag 57 | //@param {CodeGenerationContext} code_generation_context 58 | //@param {String} attributes_result Result of generating the code to all of the tag attributes 59 | //@param {String} children_result Accumulated result for all tag's children 60 | //@return {String} 61 | , defineBlockTag: function (code_generation_context, tag_type, attributes_result, children_result) 62 | { 63 | 'use strict'; 64 | 65 | return 'h("' + tag_type + '",'+ attributes_result +',' + children_result + ')'; 66 | } 67 | //@method defineSingleTag 68 | //@param {CodeGenerationContext} code_generation_context 69 | //@param {String} attributes_result Result of generating the code to all of the tag attributes 70 | //@return {String} 71 | , defineSingleTag: function (code_generation_context, tag_type, attributes_result) 72 | { 73 | 'use strict'; 74 | 75 | return 'h("' + tag_type + '",'+ attributes_result +',[])'; 76 | } 77 | //@method defineTextTag 78 | //@param {CodeGenerationContext} code_generation_context 79 | //@param {String} text Take into account that this variable can contain code to be evaluated! 80 | //@return {String} 81 | , defineTextTag: function (code_generation_context, text) 82 | { 83 | 'use strict'; 84 | 85 | return text; 86 | } 87 | //@method accumulateFinalTagsResult Wrap up the final result get after all tags were converted to code. Please notice that at this point the string code 88 | //passed in generation_result parameter contains the entire resulting code 89 | //@param {CodeGenerationOptions} options 90 | //@param {CodeGenerationResult} geneation_result 91 | //@return {geneation_result} 92 | , accumulateFinalTagsResult: function (options, generation_result) 93 | { 94 | 'use strict'; 95 | 96 | if (!options.notGenerateContext) 97 | { 98 | var deps = generation_result.contextName + (generation_result.externalDependencies.length > 0 ? ',' +generation_result.externalDependenciesObjectName : '' ); 99 | generation_result.value = 'function ('+deps+') { return ' + generation_result.value + ';}'; 100 | } 101 | 102 | return generation_result; 103 | } 104 | }; 105 | 106 | //@class VirtualDOMAdapter @extend Adapter 107 | module.exports = adapter; -------------------------------------------------------------------------------- /lib/codeGenerator.Base.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML 2 | 'use strict'; 3 | 4 | var handlebars_parser = require('handlebars-ex') 5 | , HookContainer = require('./hookContainer') 6 | , _ = require('underscore'); 7 | 8 | //@class CodeGenerator Class responsible to call the Handlebars parsers and from that result generate Virtual-DOM code 9 | module.exports = (function () 10 | { 11 | //@class CodeGenerationOptions 12 | var default_parsing_options = { 13 | //@property {ContextContainer} contextName Name of the initial context when running the returned string code. Default value: 'ctx' 14 | contextName: { 15 | value: 'ctx' 16 | } 17 | //@property {String} variableName Name of the variable used to accumulate all virtual dom nodes. 18 | , variableName: 'children' 19 | //@property {Boolean} allowMultiplesFathers 20 | , allowMultiplesFathers: false 21 | //@property {Sring} attributeObjectName 22 | , attributeObjectName: 'obj' 23 | //@property {Sring} externalDependenciesObjectName 24 | , externalDependenciesObjectName: 'external_dependencies' 25 | }; 26 | 27 | //@method codeGenerator 28 | //@constructor 29 | //@return {Void} 30 | function codeGenerator () 31 | { 32 | /*jshint validthis:true */ 33 | this._UNIQUE_ID_COUNTER = 0; 34 | } 35 | 36 | //@method generateCode Public method to generate code 37 | //@param {String} string_hx HTML/HandlebarX code to parse 38 | //@param {CodeGenerationOptions} options 39 | //@return {CodeGenerationResult} 40 | codeGenerator.prototype.generateCode = function (string_hx, options) 41 | { 42 | this.options = _.defaults(options || {}, default_parsing_options); 43 | 44 | if (!this.options.adapter) 45 | { 46 | throw new Error('Invalid codeGenerator options. Please make sure an adapter is set'); 47 | } 48 | 49 | var result = this._parse(string_hx) 50 | , adapter = this.options.adapter; 51 | 52 | if (result.value.indexOf('[') === 0) 53 | { 54 | result.value = result.value.substr(1); 55 | } 56 | if (result.value.indexOf(']', result.value.length - 1) !== -1) 57 | { 58 | result.value = result.value.substr(0, result.value.length -1); 59 | } 60 | 61 | return adapter.accumulateFinalTagsResult.call(adapter, this.options, result); 62 | }; 63 | 64 | //@method _parse Internal method that parse the given string and generates the corresponding a virtual-dom string 65 | //@param {String} string HTML/Handlebar code to parse 66 | //@return {CodeGenerationResult} 67 | codeGenerator.prototype._parse = function (string) 68 | { 69 | var nodes_ast 70 | //@class CodeGenerationResult 71 | , communication_result = { 72 | //@property {String} contextName 73 | contextName: this.options.contextName.value 74 | //@property {String} value Final string result 75 | , value: '' 76 | //@property {Arra} externalDependencies General purpose array to be used by plugins to add any external dependency 77 | , externalDependencies: [] 78 | //@property {String} externalDependenciesObjectName Name of the object that will carry all external dependencies 79 | , externalDependenciesObjectName: this.options.externalDependenciesObjectName 80 | } 81 | //@class CodeGenerationContext This class holds all the information and data used during the code generation process 82 | , code_generation_context = { 83 | //@property {NodeASTNode} astNode Current node being processed 84 | astNode: {} 85 | //property {ContextContainer} currentContextName 86 | , currentContextName: this.options.contextName 87 | //@property {Array} contextStack Stack where all context names are saved. Used in functions like handlebars EACH that change the current context name. 88 | , contextStack: [] 89 | //@property {String} variableName Name of the variable that accumulate all virtual-dom elements 90 | , variableName: this.options.variableName 91 | //@param {Boolean} isInsideContext Indicate if this function is invoked being inside a new execution context. 92 | // This means, in case it is true, that the result must be concatenated with the current variable name. 93 | , isInsideContext: false 94 | //@property {String} externalDependenciesObjectName Name of the object that will carry all external dependencies 95 | , externalDependenciesObjectName: this.options.externalDependenciesObjectName 96 | //@property {Adapter} adapter 97 | , adapter: this.options.adapter 98 | }; 99 | //@class CodeGenerator 100 | 101 | string = codeGenerator.beforeTagCodeGeneration.execute(string, code_generation_context); 102 | 103 | nodes_ast = handlebars_parser.parse(string); 104 | 105 | if (nodes_ast.length > 1 && !this.options.allowMultiplesFathers) 106 | { 107 | throw new Error('Invalid handlebars template. Please make sure there is only one parent node!'); 108 | } 109 | 110 | communication_result.value = this.iterateOverTagNodes(nodes_ast, code_generation_context, false); 111 | 112 | communication_result = codeGenerator.afterTagCodeGeneration.execute(communication_result, code_generation_context); 113 | 114 | return communication_result; 115 | }; 116 | 117 | //@method getNodeHandle Auxiliary method that given a node, returns the method (of this class) that will handle/parse it 118 | // Please notice that the searched function must fulfill the criteria based on the name of the type of the ast node 119 | //@param {NodeASTNode} ast_node Node used to look a handle for 120 | //@return {Function} 121 | codeGenerator.prototype.getNodeHandle = function (ast_node) 122 | { 123 | var fn; 124 | 125 | if (ast_node.type === 'handlebars' && (ast_node.subType === 'GENERICSINGLE' || ast_node.subType === 'ATTRGENERICSINGLE')) 126 | { 127 | fn = _.isFunction(this['single' + ast_node.value]) ? this['single' + ast_node.value] : 128 | _.isFunction(this['singleInstance' + ast_node.value]) ? this.runtimeGenericSingleHandle : 129 | null; 130 | } 131 | else if (ast_node.type === 'handlebars' && ast_node.subType === 'GENERICBLOCK') 132 | { 133 | fn = _.isFunction(this['block' + ast_node.openTag]) ? this['block' + ast_node.openTag] : 134 | _.isFunction(this['blockInstance' + ast_node.openTag]) ? this.runtimeGenericBlockHandle : 135 | null; 136 | } 137 | else if (ast_node.type === 'handlebars') 138 | { 139 | fn = this['handlebars' + ast_node.subType]; 140 | } 141 | else 142 | { 143 | fn = this[ast_node.type]; 144 | } 145 | 146 | if (!fn) 147 | { 148 | console.log(ast_node); 149 | } 150 | 151 | return fn; 152 | }; 153 | 154 | 155 | 156 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 157 | // PLUGINS DEFINITION // 158 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 159 | 160 | //@property {HookContainer} beforeAttributeHandlerRetrieved Static plugin property invoked before the attributes handlebars handler is detected/retrieved. 161 | //Aim: Edit the selected attribute AST Node before being used to detect the handler 162 | //Its invocation has the following signature: Function where the last value is the optional return one. 163 | codeGenerator.beforeAttributeHandlerRetrieved = new HookContainer(); 164 | 165 | //@property {HookContainer} beforeAttributeHandlerExecuted Static plugin property invoked before the attributes handlebars handler is executed. 166 | //Aim: Edit the selected attribute AST node before being used by the selected handle and wrap the selected handler function 167 | //Its invocation has the following signature: Function, AttributeASTNode> where the last value is the optional return one. 168 | codeGenerator.beforeAttributeHandlerExecuted = new HookContainer(); 169 | //@property {HookContainer} afterAttributeHandlerExecuted Static plugin property invoked after the attributes handlebars handler is executed. 170 | //Aim: Access the accumulated attribute generated code up to the moment, access the result of the function handler and add another step to edit the selected attribute AST node 171 | //Its invocation has the following signature: Function, AttributeASTNode> where the last value is the optional return one. 172 | codeGenerator.afterAttributeHandlerExecuted = new HookContainer(); 173 | 174 | //@property {HookContainer} beforeAttributeCodeGeneration Static plugin property invoked when at the beginning of the attributes code generation process for each tag node. 175 | //Aim: Access the entire Tag node that contains the attributes sub-tree, and to initialize plugin's state related with the attributes code generation 176 | //Its invocation has the following signature: Function where the last value is the optional return one. 177 | codeGenerator.beforeAttributeCodeGeneration = new HookContainer(); 178 | //@property {HookContainer} afterAttributeCodeGeneration Static plugin property invoked when at the end of the attributes code generation process for each tag node. 179 | //Aim: Access/Edit the entire result of attributes code generation, also to clean up any plugin's state 180 | //Its invocation has the following signature: Function where the last value is the optional return one. 181 | codeGenerator.afterAttributeCodeGeneration = new HookContainer(); 182 | 183 | //@property {HookContainer} beforeTagCodeGeneration Static plugin property invoked at the beginning of the entire code generation process. 184 | //Aim: Access/Edit the entire string template and initalize any plugin state 185 | //Its invocation has the following signature: Function where the last value is the optional return one. 186 | codeGenerator.beforeTagCodeGeneration = new HookContainer(); 187 | //@property {HookContainer} afterTagCodeGeneration Static plugin property invoked at the end of the entire code generation process. 188 | //Aim: Access/Edit the entire code generation process result 189 | //Its invocation has the following signature: Function where the last value is the optional return one. 190 | codeGenerator.afterTagCodeGeneration = new HookContainer(); 191 | 192 | //@property {HookContainer} afterTagEachContextCreation Static plugin property invoked after handlebars 'EACH' tags context is created. 193 | //Aim: Access the current AST node 194 | //Its invocation has the following signature: Function where the last value is the optional return one. It is not recommend to return anything in this plugin. 195 | codeGenerator.afterTagEachContextCreation = new HookContainer(); 196 | //@property {HookContainer} beforeTagEachContextCreation Static plugin property invoked before handlebars 'EACH' tags context is created. 197 | //Aim: Augment the EACH context 198 | //Its invocation has the following signature: Function where the last value is the optional return one. 199 | codeGenerator.beforeTagEachContextCreation = new HookContainer(); 200 | 201 | return codeGenerator; 202 | })(); -------------------------------------------------------------------------------- /lib/codeGenerator.CustomHelpers.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML 2 | var _ = require('underscore'); 3 | 4 | 5 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 6 | // TAGS // 7 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 8 | 9 | //@class CodeGenerator 10 | module.exports = { 11 | 12 | //@method _joinExternalFunctionParameters Internal method to join parameters used by external functions 13 | //@param {Array} parameters 14 | //@param {CodeGenerationContext} code_generation_context 15 | //@return {String} 16 | _joinExternalFunctionParameters: function (parameters, code_generation_context) 17 | { 18 | 'use strict'; 19 | 20 | var self = this; 21 | 22 | //TODO TAKE INTO ACCOUNT THAT PARAMETERS CAN BE REFERENCE VALUES (@index) 23 | return _.reduce(parameters, function (acc, param) 24 | { 25 | switch (param.subType) { 26 | case 'SIMPLEVALUE': 27 | acc += ',' + param.value; 28 | break; 29 | case 'LOOKUPSINGLE': 30 | acc += ',' + self._getLookUpContextName(code_generation_context, param); 31 | break; 32 | case 'SINGLEEVALUATION': 33 | if ((+param.value).toString() === param.value) 34 | { 35 | //This is the case of numbers 36 | acc += ',' + param.value; 37 | } 38 | else 39 | { 40 | acc += ',' + code_generation_context.currentContextName.value + '.' + param.value; 41 | } 42 | break; 43 | default: 44 | acc += ',' + param.value; 45 | } 46 | return acc; 47 | }, ''); 48 | }, 49 | 50 | //@method runtimeGenericSingleHandle This method converts all passed in function that represent extra helpers to string in a safe way 51 | //@param {CodeGenerationContext} code_generation_context 52 | //@return {Function} 53 | runtimeGenericSingleHandle: function (code_generation_context) 54 | { 55 | 'use strict'; 56 | 57 | var fn = this['singleInstance' + code_generation_context.astNode.value].toString() 58 | , result = '(function(){var fn = '+fn+'; return fn.call(this'+ this._joinExternalFunctionParameters(code_generation_context.astNode.parameters, code_generation_context)+'); })()'; 59 | 60 | if (code_generation_context.isSettingAttributes) 61 | { 62 | if (code_generation_context.isSettingValue) 63 | { 64 | return code_generation_context.objectName + '["'+code_generation_context.keyName+'"]+=' + result +';'; 65 | } 66 | else 67 | { 68 | return code_generation_context.objectName + '['+result+']="";'; 69 | } 70 | } 71 | else 72 | { 73 | return code_generation_context.isInsideContext ? code_generation_context.variableName + '=' + code_generation_context.variableName + '.concat(['+result+']);' : result; 74 | } 75 | }, 76 | 77 | //@method runtimeGenericBlockHandle This method converts all passed in function that represent extra helpers to string in a safe way 78 | //@param {CodeGenerationContext} code_generation_context 79 | //@return {Function} 80 | runtimeGenericBlockHandle: function (code_generation_context) 81 | { 82 | 'use strict'; 83 | 84 | var fn = this['blockInstance' + code_generation_context.astNode.openTag].toString() 85 | , result = '(function(){var fn = '+fn+'; return fn.call(this'+ this._joinExternalFunctionParameters(code_generation_context.astNode.parameters, code_generation_context)+'); })()'; 86 | 87 | return code_generation_context.isInsideContext ? code_generation_context.variableName + '=' + code_generation_context.variableName + '.concat(['+result+']);' : result; 88 | } 89 | }; -------------------------------------------------------------------------------- /lib/codeGenerator.Tags.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML 2 | var _ = require('underscore') 3 | , codeGeneratorBase = require('./codeGenerator.Base'); 4 | 5 | //@class CodeGenerator 6 | module.exports = { 7 | 8 | //@method iterateOverTagNodes Given a list of ast nodes, iterate over them and returns a string that represent its union. 9 | //@param {Array} nodes List of nodes to iterate 10 | //@param {CodeGenerationContext} code_generation_context Current code generation context 11 | //@param {Boolean} parent_require_new_context Indicate if the parent, the function that calls this function, requires that the result be in another 12 | // execution context or not. 13 | //@return {String} Portion of code that group all the nodes passed in 14 | iterateOverTagNodes: function (nodes, code_generation_context, parent_require_new_context) 15 | { 16 | 'use strict'; 17 | 18 | var self = this 19 | , handle_function 20 | , result = '' 21 | , variableName = code_generation_context.variableName 22 | 23 | , there_is_NO_handlebars = _.all(nodes, function (node) 24 | { 25 | return node.type !== 'handlebars'; 26 | }); 27 | 28 | code_generation_context.isInsideContext = parent_require_new_context || !there_is_NO_handlebars; 29 | 30 | if (nodes.length) 31 | { 32 | if (code_generation_context.isInsideContext) 33 | { 34 | result = '(function () {'; 35 | result += 'var '+variableName+ '=[];'; 36 | result += _.map(nodes, function (ast_node) 37 | { 38 | code_generation_context.astNode = ast_node; 39 | handle_function = self.getNodeHandle(ast_node); 40 | return handle_function.call(self, code_generation_context, true); 41 | }, '').join(''); 42 | 43 | result += 'return '+variableName+'; })()'; 44 | } 45 | else 46 | { 47 | result = '[' + _.map(nodes, function (ast_node) 48 | { 49 | code_generation_context.astNode = ast_node; 50 | code_generation_context.isInsideContext = false; 51 | handle_function = self.getNodeHandle(ast_node); 52 | return handle_function.call(self, code_generation_context, false); 53 | }, '').join(',') + ']'; 54 | } 55 | } 56 | else 57 | { 58 | result = _.isUndefined(code_generation_context.adapter.emptyTagCollection) ? '[]' : code_generation_context.adapter.emptyTagCollection; 59 | } 60 | 61 | return result; 62 | }, 63 | 64 | 65 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 66 | // HTML // 67 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 68 | 69 | 70 | //@method htmlBlockNode Handle standard HTML blocks 71 | //@param {CodeGenerationContext} code_generation_context 72 | //@return {String} 73 | htmlBlockNode: function (code_generation_context) 74 | { 75 | 'use strict'; 76 | 77 | var code_generation_context_clone = _.clone(code_generation_context) 78 | , attributes_result = this.parseAttributes(code_generation_context) 79 | , children_result = this.iterateOverTagNodes(code_generation_context.astNode.children, code_generation_context, true) 80 | , adapter = code_generation_context.adapter 81 | , virtual_dom = adapter.defineBlockTag.call(adapter, code_generation_context_clone, code_generation_context_clone.astNode.openTag, attributes_result, children_result); 82 | 83 | if (code_generation_context_clone.isInsideContext) 84 | { 85 | return this._concatenateTagValues(code_generation_context.variableName, virtual_dom, code_generation_context); 86 | } 87 | return virtual_dom; 88 | }, 89 | 90 | //@method htmlSingleNode Handle standard one liner HTML 91 | //@param {CodeGenerationContext} code_generation_context 92 | //@return {String} 93 | htmlSingleNode: function (code_generation_context) 94 | { 95 | 'use strict'; 96 | 97 | var code_generation_context_clone = _.clone(code_generation_context) 98 | , attributes_result = this.parseAttributes(code_generation_context) 99 | , adapter = code_generation_context.adapter 100 | , virtual_dom = adapter.defineSingleTag.call(adapter, code_generation_context_clone, code_generation_context_clone.astNode.tag, attributes_result); 101 | 102 | if (code_generation_context_clone.isInsideContext) 103 | { 104 | return this._concatenateTagValues(code_generation_context.variableName, virtual_dom, code_generation_context); 105 | } 106 | return virtual_dom; 107 | }, 108 | 109 | //@method text Handle plain text inside the HTML document 110 | //@param {CodeGenerationContext} code_generation_context 111 | //@return {String} 112 | text: function (code_generation_context) 113 | { 114 | 'use strict'; 115 | 116 | var adapter = code_generation_context.adapter 117 | , virtual_dom = adapter.defineTextTag.call(adapter, code_generation_context, '\'' + code_generation_context.astNode.value.replace(/'/g, "\\'")+ '\''); 118 | 119 | if (code_generation_context.isInsideContext) 120 | { 121 | return this._concatenateTagValues(code_generation_context.variableName, virtual_dom, code_generation_context); 122 | } 123 | return virtual_dom; 124 | }, 125 | 126 | //@method htmlComment Handle standard HTML comments 127 | //@param {CodeGenerationContext} code_generation_context 128 | //@return {String} 129 | htmlComment: function (code_generation_context) 130 | { 131 | 'use strict'; 132 | 133 | //TODO MAKE A BETTER MANAGEMENT OF HTML COMMENT NODES!! 134 | return ''; 135 | }, 136 | 137 | 138 | 139 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 140 | // UTILS TAGS // 141 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 142 | 143 | //@method _concatenateValues Concatenate/Composite a bunch of results into the accumulator variable. Used when the conversion is done inside a new context. 144 | //@param {String} accumulator_variable_name Name of the variable than has all the results 145 | //@param {String} children_result Result to be appended 146 | //@param {CodeGenerationContext} code_generation_context 147 | //@param {Boolean} are_children_array Indicate if the children_result param is an array or not. (If false children_result will be wrapper with '[' ']' characters) 148 | //@return {String} 149 | _concatenateTagValues: function (accumulator_variable_name, children_result, code_generation_context, are_children_array) 150 | { 151 | 'use strict'; 152 | 153 | var adapter = code_generation_context.adapter; 154 | 155 | if (_.isFunction(adapter.concatenateTagValues)) 156 | { 157 | return adapter.concatenateTagValues.call(adapter, accumulator_variable_name, children_result, code_generation_context); 158 | } 159 | 160 | if (!are_children_array) 161 | { 162 | children_result = '['+children_result+']'; 163 | } 164 | 165 | return accumulator_variable_name + '='+ accumulator_variable_name + '.concat('+children_result+');'; 166 | }, 167 | 168 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 169 | // HANDLEBARS // 170 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 171 | 172 | 173 | //@method handlebarsSINGLECOMMENTS Handle the parsing of handlebar line comments 174 | //@param {CodeGenerationContext} code_generation_context 175 | //@return {String} 176 | handlebarsSINGLECOMMENTS: function (code_generation_context) 177 | { 178 | 'use strict'; 179 | 180 | //TODO Provide some support for handlebars comments 181 | return ''; 182 | }, 183 | 184 | //@method handlebarsSAFEEVALUATION Handle the parsing of safe evaluation handlebar nodes 185 | //@param {CodeGenerationContext} code_generation_context 186 | //@return {String} 187 | handlebarsSAFEEVALUATION: function (code_generation_context) 188 | { 189 | 'use strict'; 190 | 191 | var adapter = code_generation_context.adapter 192 | , virtual_dom = adapter.defineTextTag.call(adapter, code_generation_context, '_.escape('+ code_generation_context.currentContextName.value + '.'+ code_generation_context.astNode.value +')'); 193 | 194 | if (code_generation_context.isInsideContext) 195 | { 196 | return this._concatenateTagValues(code_generation_context.variableName, virtual_dom, code_generation_context); 197 | } 198 | return virtual_dom; 199 | }, 200 | 201 | //@method handlebarsUNSAFEEVALUATION Handle the parsing of unsafe evaluation handlebar nodes 202 | //@param {CodeGenerationContext} code_generation_context 203 | //@return {String} 204 | handlebarsUNSAFEEVALUATION: function (code_generation_context) 205 | { 206 | 'use strict'; 207 | 208 | var adapter = code_generation_context.adapter 209 | , virtual_dom = adapter.defineTextTag.call(adapter, code_generation_context, '""+' + code_generation_context.currentContextName.value + '.'+ code_generation_context.astNode.value ); 210 | 211 | if (code_generation_context.isInsideContext) 212 | { 213 | return this._concatenateTagValues(code_generation_context.variableName, virtual_dom, code_generation_context); 214 | } 215 | return virtual_dom; 216 | }, 217 | 218 | //@method handlebarsLOOKUPSINGLE Handle the parsing of single lookup variable evaluation 219 | //@param {CodeGenerationContext} code_generation_context 220 | //@return {String} 221 | handlebarsLOOKUPSINGLE: function (code_generation_context) 222 | { 223 | 'use strict'; 224 | 225 | var adapter = code_generation_context.adapter 226 | , expression = '_.escape('+ this._getLookUpContextName(code_generation_context, code_generation_context.astNode) + ')' 227 | , virtual_dom = adapter.defineTextTag.call(adapter, code_generation_context, expression); 228 | 229 | if (code_generation_context.isInsideContext) 230 | { 231 | return this._concatenateTagValues(code_generation_context.variableName, virtual_dom, code_generation_context); 232 | } 233 | return virtual_dom; 234 | }, 235 | 236 | //@method handlebarsSAFEREFERENCEEVALUATION Handle the parsing of safe reference evaluation handlebar nodes 237 | //@param {CodeGenerationContext} code_generation_context 238 | //@return {String} 239 | handlebarsSAFEREFERENCEEVALUATION: function (code_generation_context) 240 | { 241 | 'use strict'; 242 | 243 | var property_name = code_generation_context.astNode.value.trim().substr(1); 244 | 245 | if (code_generation_context.currentContextName[property_name]) 246 | { 247 | var adapter = code_generation_context.adapter 248 | , expression = '_.escape('+ code_generation_context.currentContextName.contextName + '.' + property_name+')' 249 | , virtual_dom = adapter.defineTextTag.call(adapter, code_generation_context, expression); 250 | 251 | if (code_generation_context.isInsideContext) 252 | { 253 | return this._concatenateTagValues(code_generation_context.variableName, virtual_dom, code_generation_context); 254 | } 255 | return virtual_dom; 256 | } 257 | 258 | // console.log(code_generation_context.astNode, 'Invalid safe reference evaluation'); 259 | throw new Error('Invalid safe reference evaluation.'); 260 | }, 261 | 262 | //@method handlebarsEACH Handle the parsing of each handlebar nodes 263 | //@param {CodeGenerationContext} code_generation_context 264 | //@return {String} 265 | handlebarsEACH: function (code_generation_context) 266 | { 267 | 'use strict'; 268 | 269 | code_generation_context.astNode = codeGeneratorBase.afterTagEachContextCreation.execute( code_generation_context.astNode, code_generation_context); 270 | 271 | var ast_node = code_generation_context.astNode 272 | , iterator_variable_name = this._generateUniqueId('eachIterator') 273 | , iterator_index = iterator_variable_name+'Index' 274 | , accumulator_variable_name = this._generateUniqueId('eachAccumulator') 275 | , each_context_name = this._generateUniqueId('contextName') 276 | , iterator_name = this._handlebarsEvaluateCondition(code_generation_context, ast_node.iterator) 277 | , result = '' 278 | //@class HandlebarsEACHContext 279 | , each_context = { 280 | //@property {String} value 281 | value: iterator_variable_name 282 | //@property {String} first This string, when compiled will be converted to Boolean 283 | , first: iterator_index + ' === 0' 284 | //@property {String} last This string, when compiled will be converted to Boolean 285 | , last: iterator_index + ' === ('+iterator_name+'.length - 1)' 286 | //@property {String} index This string, when compiled will be converted to Number 287 | , index: iterator_index 288 | //@property {String} contextName 289 | , contextName: each_context_name 290 | 291 | //This SHOULD NOT BE IN THE CORE, THIS OPTIONS MUST BE ADDED BY ONE EXTENSION! 292 | //I added here just to make it fast and easy :P 293 | , indexPlusOne: iterator_index + '+1' 294 | }; 295 | //@class CodeGenerator 296 | 297 | each_context = codeGeneratorBase.beforeTagEachContextCreation.execute(each_context, code_generation_context); 298 | 299 | //reduce/EACH header 300 | result = code_generation_context.variableName + '=' + code_generation_context.variableName + '.concat(' + 301 | '_.reduce( '+ iterator_name +', function ('+ 302 | accumulator_variable_name+',' + iterator_variable_name+','+iterator_index+') {'; 303 | //new context definition 304 | result += this._serializeContext(each_context, each_context_name, each_context.value); 305 | 306 | //adapt context default value. It is needed to add the context name to the serialized context value 307 | each_context.value = each_context_name + '.' + each_context.value; 308 | code_generation_context.contextStack.push(code_generation_context.currentContextName); 309 | code_generation_context.currentContextName = each_context; 310 | 311 | // result += accumulator_variable_name +'='+ accumulator_variable_name +'.concat('+ this.iterateOverTagNodes(ast_node.eachBody, code_generation_context, true)+ ');'; 312 | result += this._concatenateTagValues(accumulator_variable_name, this.iterateOverTagNodes(ast_node.eachBody, code_generation_context, true), code_generation_context, true); 313 | result += 'return ' + accumulator_variable_name; 314 | result += '}, []));'; 315 | 316 | code_generation_context.currentContextName = code_generation_context.contextStack.pop(); 317 | 318 | //TODO Give support for ELSE statement in EACH iterators!!! 319 | 320 | // if (ast_node.elseBody.length) 321 | // { 322 | // result += '} else {' 323 | // result += this.iterateOverTagNodes(ast_node.elseBody, code_generation_context, true); 324 | // } 325 | return result; 326 | }, 327 | 328 | //@method handlebarsIF Handle the parsing of IF handlebar nodes 329 | // Notice that the second param 'not_consider_context' is indeed being passed in to this function, it is just the it does not make sense to used, 330 | // as we always need to run any handlebars conversion in the context of a function, '(function () {}()' 331 | //@param {CodeGenerationContext} code_generation_context 332 | //@return {String} 333 | handlebarsIF: function (code_generation_context) 334 | { 335 | 'use strict'; 336 | 337 | var ast_node = code_generation_context.astNode 338 | , result = 'if ('+ this._handlebarsEvaluateCondition(code_generation_context, ast_node.condition) +') {'; 339 | 340 | result += this._concatenateTagValues(code_generation_context.variableName, this.iterateOverTagNodes(ast_node.ifBody, code_generation_context, true), code_generation_context, true); 341 | 342 | if (ast_node.elseBody.length) 343 | { 344 | result += '} else {'; 345 | result += code_generation_context.variableName + '=' + code_generation_context.variableName + '.concat('+ 346 | this.iterateOverTagNodes(ast_node.elseBody, code_generation_context, true) +');'; 347 | } 348 | result += '}'; 349 | return result; 350 | }, 351 | 352 | //@method handlebarsUNLESS Handle the parsing of UNLESS handlebar nodes 353 | //@param {CodeGenerationContext} code_generation_context 354 | //@return {String} 355 | handlebarsUNLESS: function (code_generation_context) 356 | { 357 | 'use strict'; 358 | 359 | var ast_node = code_generation_context.astNode 360 | , result = 'if (!'+this._handlebarsEvaluateCondition(code_generation_context, ast_node.condition) +') {'; 361 | 362 | result += this.iterateOverTagNodes(ast_node.unlessBody, code_generation_context, true); 363 | 364 | if (ast_node.elseBody.length) 365 | { 366 | result += '} else {'; 367 | result += this.iterateOverTagNodes(ast_node.elseBody, code_generation_context, true); 368 | } 369 | result += '}'; 370 | return result; 371 | } 372 | }; 373 | -------------------------------------------------------------------------------- /lib/codeGenerator.Utils.js: -------------------------------------------------------------------------------- 1 | 2 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 3 | // UTILS // 4 | ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 5 | 6 | //@module blueHTML 7 | //@class CodeGenerator 8 | module.exports = { 9 | 10 | //@method _generateUniqueId Internal method used to create unique identifiers. Copy of underscore.uniqueId. It is copy here in order to 11 | // control it's internal state. 12 | //@param {String?} prefix Optional prefix 13 | //@return {String} 14 | _generateUniqueId: function (prefix) 15 | { 16 | 'use strict'; 17 | 18 | var id = ++this._UNIQUE_ID_COUNTER + ''; 19 | return prefix ? prefix + id : id; 20 | }, 21 | 22 | //@method _serializeContext Internal method used to serialize a context object. This method is used by each handlebar block object that defines a new context. For example EACH 23 | // Notice that the presence of any property called contextName will NOT be included in the final result 24 | //@param {Object} context Any plain javascript object with one 'value' property 25 | //@param {String} variable_name Name of the object in the returned string 26 | //@param {String} value_name Name of the value property in the returned string 27 | //@return {String} 28 | _serializeContext: function (context, variable_name, value_name) 29 | { 30 | 'use strict'; 31 | 32 | var result = 'var ' + variable_name + '= {' 33 | , prefix = ''; 34 | 35 | for (var key in context) 36 | { 37 | if (context.hasOwnProperty(key) && key !== 'contextName') 38 | { 39 | if (key === 'value') 40 | { 41 | result += prefix + value_name + ':' + context[key]; 42 | } 43 | else 44 | { 45 | result += prefix + key + ':' + context[key]; 46 | } 47 | 48 | prefix = ','; 49 | } 50 | } 51 | 52 | result += '};'; 53 | return result; 54 | }, 55 | 56 | //@method _getLookUpContextName Internal method to find the context name in the case of look Ups 57 | //@param {CodeGenerationContext} code_generation_context 58 | //@param {NodeASTNode} node 59 | //@return {String} 60 | _getLookUpContextName: function (code_generation_context, node) 61 | { 62 | 'use strict'; 63 | 64 | //We remove one as the length returns the amount of items in the array and we need the index 65 | var number_of_elements_to_exclude = code_generation_context.contextStack.length - 1 66 | //We remove 2 because; 1 for the name of the variable inside the value array and 1 because the current context name is not the parsing context stack 67 | , inverted_index = node.value.length - 2 68 | , context_index = (number_of_elements_to_exclude - inverted_index) < 0 ? 0 : number_of_elements_to_exclude - inverted_index 69 | , selected_context_name = code_generation_context.contextStack[context_index] ? code_generation_context.contextStack[context_index].value : code_generation_context.currentContextName.value; 70 | 71 | return selected_context_name + '.' + node.value[node.value.length - 1]; 72 | }, 73 | 74 | //@method _handlebarsEvaluateCondition Evaluates the condition of IFs, UNLESSs and EACHs. As these values can be single evaluation or lookups 75 | //@param {CodeGenerationContext} code_generation_context 76 | //@param {ConditionNode} condition 77 | //@return {String} 78 | _handlebarsEvaluateCondition: function (code_generation_context, condition) 79 | { 80 | 'use strict'; 81 | 82 | if (condition.subType === 'SINGLEEVALUATION' || condition.subType === 'ATTRSINGLEEVALUATION') 83 | { 84 | return code_generation_context.currentContextName.value + '.' + condition.value; 85 | } 86 | else if (condition.subType === 'REFERENCEEVALUATION' || condition.subType === 'ATTRREFERENCEEVALUATION') 87 | { 88 | var property_name = condition.value.trim().substr(1); 89 | if (code_generation_context.currentContextName[property_name]) 90 | { 91 | return code_generation_context.currentContextName.contextName + '.' + property_name; 92 | } 93 | console.log(condition, 'Invalid reference evaluation'); 94 | throw new Error('Invalid reference evaluation.'); 95 | } 96 | else if (condition.subType === 'LOOKUPSINGLE' || condition.subType === 'ATTRLOOKUPSINGLE') 97 | { 98 | return this._getLookUpContextName(code_generation_context, condition); 99 | } 100 | else 101 | { 102 | console.log(condition, 'Non supported evaluation!'); 103 | throw new Error('Non supported evaluation!'); 104 | } 105 | } 106 | }; -------------------------------------------------------------------------------- /lib/codeGenerator.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML 2 | var base = require('./codeGenerator.Base') 3 | , utils = require('./codeGenerator.Utils') 4 | , tags = require('./codeGenerator.Tags') 5 | , attributes = require('./codeGenerator.Attributes') 6 | , customHelpers = require('./codeGenerator.CustomHelpers') 7 | , _ = require('underscore'); 8 | 9 | //@class CodeGenerator 10 | base.prototype = _.extend( 11 | base.prototype 12 | , utils 13 | , tags 14 | , attributes 15 | , customHelpers 16 | , { 17 | //@method addCustomHandler Add a new handlebars handler 18 | //@param {Function } 19 | //@return {Void} 20 | addCustomHandler: function (handlebars_handlers) 21 | { 22 | 'use strict'; 23 | 24 | _.extend(base.prototype, handlebars_handlers || {}); 25 | } 26 | //@method installPlugin Install a plugin inside the code generator 27 | //@param {Plugin} plugin_container 28 | //@return {Void} 29 | , installPlugin: function (plugin_container) 30 | { 31 | 'use strict'; 32 | 33 | /*jshint -W030 */ 34 | plugin_container && plugin_container.install && plugin_container.install.call(plugin_container, base); 35 | } 36 | } 37 | ); 38 | 39 | module.exports = base; 40 | 41 | 42 | //@class Plugin 43 | //@method install Public method invoked by blueHTML when adding a new plugin. 44 | //@param {CodeGenerator} codeGenerator 45 | //@return {Void} 46 | -------------------------------------------------------------------------------- /lib/hookContainer.js: -------------------------------------------------------------------------------- 1 | //@module blueHTML 2 | 3 | 'use strict'; 4 | 5 | //@class HookContainer 6 | module.exports = (function () 7 | { 8 | //@method HookContainer 9 | //@constructor 10 | //@return {Void} 11 | function HookContainer () 12 | { 13 | this.hooks = []; 14 | } 15 | 16 | //@method add Adds a hook into the current hook container 17 | //@param {Hook} hook 18 | //@return {Void} 19 | HookContainer.prototype.add = function (hook) 20 | { 21 | this.hooks.push(hook); 22 | }; 23 | 24 | //@method execute Execute all register hooks 25 | //@param {Any} xx This method allows an arbitrary number of parameters. Only the first only will be accumulated among all hooks and returned 26 | //@return {Any} First parameter passed in 27 | HookContainer.prototype.execute = function () 28 | { 29 | var args = Array.prototype.slice.call(arguments, 0); 30 | 31 | for (var i = 0; i < this.hooks.length; i++) 32 | { 33 | args[0] = this.hooks[i].execute.apply(this.hooks[i], args) || args[0]; 34 | } 35 | 36 | return args[0]; 37 | }; 38 | 39 | return HookContainer; 40 | })(); 41 | 42 | //@class Hook 43 | //@method execute Execute the plugin itself 44 | //@param {Any} This method allows a variable numbers of parameters. This will depend on the invocation of the HookContainer 45 | //@return {Any} The returned value, if any, will be accumulated during the execution of all plugins 46 | // 47 | //@property {String} name 48 | //@property {Number} priority 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bluehtml", 3 | "version": "0.1.0", 4 | "description": "Handlebars to Virtual DOM parser", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "jasmine" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git://github.com/mictian/blueHTML.git" 12 | }, 13 | "keywords": [ 14 | "handlebars", 15 | "virtual-dom", 16 | "virtualdom", 17 | "parser", 18 | "convert" 19 | ], 20 | "author": "Mictian", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/mictian/blueHTML/issues" 24 | }, 25 | "homepage": "https://github.com/mictian/blueHTML", 26 | "dependencies": { 27 | "handlebars-ex": "0.0.2", 28 | "underscore": "^1.8.3", 29 | "virtual-dom": "^2.0.1" 30 | }, 31 | "devDependencies": { 32 | "jasmine": "^2.3.1", 33 | "rimraf": "^2.4.3", 34 | "short-jsdoc": "^0.2.1" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /spec/combinationHandlebarsHTMLSpec.js: -------------------------------------------------------------------------------- 1 | var parser = require('../index') 2 | , h = require('virtual-dom/h') 3 | , _ = require('underscore') 4 | , deafult_parsing_options = { 5 | notGenerateContext: true 6 | } 7 | //GLOBAL CONTEXT! 8 | , ctx = {}; 9 | 10 | function parse (template_str, return_string, options) 11 | { 12 | var vd_str = parser.generateVirtualDOM(template_str, _.extend({}, deafult_parsing_options, options)); 13 | 14 | return return_string ? vd_str : eval(vd_str); 15 | } 16 | 17 | xdescribe('Combination Handlebars & HTML', function () 18 | { 19 | xit ('Should recognize a simple address template', function () 20 | { 21 | var result = parser.parse( 22 | ' \ 23 |

    \ 24 | {{city}} \ 25 |

    \ 26 | {{#if showState}} \ 27 |

    \ 28 | {{state}} \ 29 |

    \ 30 | {{/if}} \ 31 |

    \ 32 | {{zip}} \ 33 |

    \ 34 |
    ') 35 | , expeted = 12; 36 | 37 | expect(result).toEqual(expeted); 38 | }); 39 | 40 | xdescribe('Reference Values', function () 41 | { 42 | describe('Inside an invalid context', function () 43 | { 44 | xit('Should fails setting a reference values as an attribute', function () 45 | { 46 | var result = parse('
    ') 47 | , expeted = h("div",(function (){var obj = {}; obj["data-type"]="";obj["data-type"]+="controller";return {attributes: obj};})(),[]); 48 | 49 | expect(result).toEqual(expeted); 50 | }); 51 | }); 52 | 53 | describe('Inside a Valid context', function () 54 | { 55 | it('Should create a property which name is the the refence values when used in attributes definitions', function () 56 | { 57 | var result = parse('{{#each list}}
    {{/each}}', true) 58 | , expeted = 12// h("div",(function (){var obj = {}; obj["data-type"]="";obj["data-type"]+="controller";return {attributes: obj};})(),[]); 59 | 60 | expect(result).toEqual(expeted); 61 | }); 62 | }); 63 | 64 | }); 65 | 66 | //REFENCE VALUES 67 | //Inside an invalid context (without context at all) 68 | //Safe evaluation as a single statement 69 | //Safe evaluation as a single statement in an attribute 70 | //Safe evaluation in a generic block as parameter 71 | //UnSafe evaluation as a single statement 72 | //UnSafe evaluation as a single statement in an attribute 73 | //UnSafe evaluation in a generic single as parameter 74 | //Inside a valid context 75 | //Safe evaluation as a single statement 76 | //Safe evaluation as a single statement in an attribute 77 | //Safe evaluation in a generic block as parameter 78 | //UnSafe evaluation as a single statement 79 | //UnSafe evaluation as a single statement in an attribute 80 | //UnSafe evaluation in a generic single as parameter 81 | //Inside multiples valid contexts 82 | //Safe evaluation as a single statement 83 | //Safe evaluation as a single statement in an attribute 84 | //Safe evaluation in a generic block as parameter 85 | //UnSafe evaluation as a single statement 86 | //UnSafe evaluation as a single statement in an attribute 87 | //UnSafe evaluation in a generic single as parameter 88 | 89 | //GENERICS 90 | //For Nodes 91 | //SAFE GENERIC BLOCKS 92 | //UNSAFE GENERIC BLOCKS 93 | //SAFE GENERIC SINGLE (Already tested!) 94 | //UNSAFE GENERIC SINGLE 95 | //For Attributes 96 | //SAFE GENERIC BLOCKS 97 | //UNSAFE GENERIC BLOCKS 98 | //SAFE GENERIC SINGLE (Already tested!) 99 | //UNSAFE GENERIC SINGLE 100 | 101 | //HTML COMMENTS 102 | //HANDLEBARS COMMENTS 103 | 104 | 105 | it('Should recognize reference values as a block statement inside an each block', function () 106 | { 107 | expect(12).toBe('FAIL'); 108 | }); 109 | 110 | it('Should recognize reference values as properties in a generic BLOCK node inside an each block', function () 111 | { 112 | expect(12).toBe('FAIL'); 113 | }); 114 | 115 | it('Should recognize reference values as properties in a generic SINGLE node inside an each block', function () 116 | { 117 | expect(12).toBe('FAIL'); 118 | }); 119 | 120 | it('Should recognize lookup values inside an each block', function () 121 | { 122 | //The idea here is test with multiples nested each block and at diff levels with crossed reference values @value 123 | expect(12).toBe('FAIL'); 124 | }); 125 | }); -------------------------------------------------------------------------------- /spec/simpleHTMLAttributesSpec.js: -------------------------------------------------------------------------------- 1 | var parser = require('../index') 2 | , h = require('virtual-dom/h') 3 | , _ = require('underscore') 4 | , deafult_parsing_options = { 5 | notGenerateContext: true 6 | } 7 | //GLOBAL CONTEXT! 8 | , ctx = {}; 9 | 10 | function parse (template_str, return_string, options) 11 | { 12 | var vd_str = parser.generateVirtualDOM(template_str, _.extend({}, deafult_parsing_options, options)); 13 | 14 | return return_string ? vd_str : eval(vd_str); 15 | } 16 | 17 | describe('Simple HTML Attributes', function () 18 | { 19 | describe('key value nodes', function () 20 | { 21 | it('Should recognize key-value with one value using double quotes', function () 22 | { 23 | var result = parse('
    ') 24 | , expeted = h("div",(function (){var obj = {}; obj["data-type"]="";obj["data-type"]+="controller";return {attributes: obj};})(),[]); 25 | 26 | expect(result).toEqual(expeted); 27 | }); 28 | 29 | it('Should recognize key-value with none value using double quotes', function () 30 | { 31 | var result = parse('
    ') 32 | , expeted = h("div",(function (){var obj = {}; obj["data-type"]="";obj["data-type"]+="";return {attributes: obj};})(),[]); 33 | 34 | expect(result).toEqual(expeted); 35 | }); 36 | 37 | it('Should recognize key-value with two value using double quotes', function () 38 | { 39 | var result = parse('
    ') 40 | , expeted = h("div",(function (){var obj = {}; obj["class"]="";obj["class"]+="blue";obj["class"]+=" ";obj["class"]+="red";return {attributes: obj};})(),[]); 41 | 42 | expect(result).toEqual(expeted); 43 | }); 44 | 45 | it('Should recognize key-value with one value using single quotes', function () 46 | { 47 | var result = parse('
    ') 48 | , expeted = h("div",(function (){var obj = {}; obj["data-type"]="";obj["data-type"]+="controller";return {attributes: obj};})(),[]); 49 | 50 | expect(result).toEqual(expeted); 51 | }); 52 | 53 | it('Should recognize key-value with none value using single quotes', function () 54 | { 55 | var result = parse('
    ') 56 | , expeted = h("div",(function (){var obj = {}; obj["data-type"]="";obj["data-type"]+="";return {attributes: obj};})(),[]); 57 | 58 | expect(result).toEqual(expeted); 59 | }); 60 | 61 | it('Should recognize key-value with two value using single quotes', function () 62 | { 63 | var result = parse('
    ') 64 | , expeted = h("div",(function (){var obj = {}; obj["class"]="";obj["class"]+="blue";obj["class"]+=" ";obj["class"]+="red"; 65 | return {attributes: obj};})(),[]); 66 | 67 | expect(result).toEqual(expeted); 68 | }); 69 | }); 70 | 71 | describe('single keys nodes', function () 72 | { 73 | it('Should recognize single key', function () 74 | { 75 | var result = parse('
    ') 76 | , expeted = h("div",(function (){var obj = {}; obj["checked"]="";return {attributes: obj};})(),[]); 77 | 78 | expect(result).toEqual(expeted); 79 | }); 80 | 81 | it('Should recognize two single keys', function () 82 | { 83 | var result = parse('
    ') 84 | , expeted = h("div",(function (){var obj = {}; obj["checked"]="";obj["disabled"]="";return {attributes: obj};})(),[]); 85 | 86 | expect(result).toEqual(expeted); 87 | }); 88 | 89 | it('Should recognize two single keys (one with single quotes)', function () 90 | { 91 | var result = parse('
    ') 92 | , expeted = h("div",(function (){var obj = {}; obj["checked"]="";obj["disabled"]="";return {attributes: obj};})(),[]); 93 | 94 | expect(result).toEqual(expeted); 95 | }); 96 | 97 | it('Should recognize two single keys (one with double quotes)', function () 98 | { 99 | var result = parse('
    ') 100 | , expeted = h("div",(function (){var obj = {}; obj["checked"]="";obj["disabled"]="";return {attributes: obj};})(),[]); 101 | 102 | expect(result).toEqual(expeted); 103 | }); 104 | 105 | it('Should recognize two single keys (one with double quotes and the other with single quotes)', function () 106 | { 107 | var result = parse('
    ') 108 | , expeted = h("div",(function (){var obj = {}; obj["checked"]="";obj["disabled"]="";return {attributes: obj};})(),[]); 109 | 110 | expect(result).toEqual(expeted); 111 | }); 112 | 113 | it('Should recognize single keys nodes mixed', function () 114 | { 115 | var result = parse('
    ') 116 | , expeted = h("div",(function (){var obj = {}; obj["checked"]="";obj["ok-value"]="";obj["testing"]="";obj["disabled"]=""; 117 | return {attributes: obj};})(),[]); 118 | 119 | expect(result).toEqual(expeted); 120 | }); 121 | }); 122 | }); -------------------------------------------------------------------------------- /spec/simpleHTMLTagsSpec.js: -------------------------------------------------------------------------------- 1 | var parser = require('../index') 2 | , h = require('virtual-dom/h') 3 | , _ = require('underscore') 4 | , deafult_parsing_options = { 5 | notGenerateContext: true 6 | } 7 | //GLOBAL CONTEXT! 8 | , ctx = {}; 9 | 10 | parser.parse = function (template_str, return_string, options) 11 | { 12 | var vd_str = parser.generateVirtualDOM(template_str, _.extend({}, deafult_parsing_options, options)); 13 | 14 | return return_string ? vd_str : eval(vd_str); 15 | } 16 | 17 | describe('Simple HTLM', function () 18 | { 19 | describe('block tags', function () 20 | { 21 | it('Should recognize simple block elements (div)', function () 22 | { 23 | var result = parser.parse('
    ') 24 | , expeted = h("div",{},[]); 25 | 26 | expect(result).toEqual(expeted); 27 | }); 28 | 29 | it('Should recognize simples block elements (div) together', function () 30 | { 31 | //IMPORTANT: Notice that here the comparison is made using string as the evaluation will only take into account the first 32 | //div. For this reason is that more than one root tag is discouraged 33 | var result = parser.parse('
    ', true, {allowMultiplesFathers: true}) 34 | , expeted = 'h("div",{},[]),h("div",{},[])'; 35 | 36 | expect(result).toEqual(expeted); 37 | }); 38 | 39 | it('Should recognize simple block elements (span)', function () 40 | { 41 | var result = parser.parse('') 42 | , expeted = h("span",{},[]); 43 | 44 | expect(result).toEqual(expeted); 45 | }); 46 | 47 | it('Should recognize nested simple block elements', function () 48 | { 49 | var result = parser.parse('
    ') 50 | , expeted = h("div",{},(function () {children= [];children=children.concat([h("div",{},[])]);return children; })()); 51 | 52 | expect(result).toEqual(expeted); 53 | }); 54 | 55 | it('Should recognize nested simple block elements, divs and block inputs', function () 56 | { 57 | var result = parser.parse('
    ') 58 | , expeted = h("div",{},(function () {children= [];children=children.concat([h("input",{},[])]);return children; })()); 59 | 60 | expect(result).toEqual(expeted); 61 | }); 62 | 63 | it('Should recognize nested simple block elements omitting spaces', function () 64 | { 65 | var result = parser.parse('
    \n
    \n
    ') 66 | , expeted = h("div",{},(function () {children= [];children=children.concat([h("div",{},[])]);return children; })()); 67 | 68 | expect(result).toEqual(expeted); 69 | }); 70 | }); 71 | 72 | describe('single tags', function () 73 | { 74 | it('Should recognize simple single elements (input)', function () 75 | { 76 | var result = parser.parse('') 77 | , expeted = h("input",{},[]); 78 | 79 | expect(result).toEqual(expeted); 80 | }); 81 | 82 | it('Should recognize simple single elements (hr)', function () 83 | { 84 | var result = parser.parse('
    ') 85 | , expeted = h("hr",{},[]); 86 | 87 | expect(result).toEqual(expeted); 88 | }); 89 | 90 | it('Should recognize a simple single elements (hr) in-line with a block element', function () 91 | { 92 | var result = parser.parse('
    ', true, {allowMultiplesFathers: true}) 93 | , expeted = 'h("hr",{},[]),h("input",{},[])'; 94 | 95 | expect(result).toEqual(expeted); 96 | }); 97 | 98 | it('Should recognize simple text', function () 99 | { 100 | var result = parser.parse('This is a text tag') 101 | , expeted = "This is a text tag"; 102 | 103 | expect(result).toEqual(expeted); 104 | }); 105 | 106 | it('Should recognize simple text nested in block tags', function () 107 | { 108 | var result = parser.parse('
    This is a text tag
    ') 109 | , expeted = h("div",{},(function () {children= [];children=children.concat(["This is a text tag"]);return children; })()); 110 | 111 | expect(result).toEqual(expeted); 112 | }); 113 | 114 | it('Should recognize simple text nested in block tags with a single tag in-line', function () 115 | { 116 | var result = parser.parse('
    This is a text tag
    ') 117 | , expeted = h("div",{},(function () {children= [];children=children.concat(["This is a text tag"]);children=children.concat([h("hr",{},[])]);return children; })()); 118 | 119 | expect(result).toEqual(expeted); 120 | }); 121 | 122 | 123 | xdescribe ('HTML comments', function () 124 | { 125 | it('Should recognize html comments', function () 126 | { 127 | var result = parser.parse('') 128 | , expeted = [{"type":"htmlComment","value":" This is a comment "}]; 129 | 130 | expect(result).toEqual(expeted); 131 | }); 132 | 133 | it('Should recognize two html comments', function () 134 | { 135 | var result = parser.parse('') 136 | , expeted = [ {"type":"htmlComment","value":" This is a comment "}, 137 | {"type":"htmlComment","value":" This is a comment also "}]; 138 | 139 | expect(result).toEqual(expeted); 140 | }); 141 | 142 | it('Should recognize nested html comments in block tags', function () 143 | { 144 | var result = parser.parse(' ') 145 | , expeted = [{"type":"htmlBlockNode","openTag":"span","closeTag":"span","attributes":[],"children":[{"type":"htmlComment","value":" This is a comment "}]}]; 146 | 147 | expect(result).toEqual(expeted); 148 | }); 149 | }); 150 | }); 151 | }); -------------------------------------------------------------------------------- /spec/support/jasmine.json: -------------------------------------------------------------------------------- 1 | { 2 | "spec_dir": "spec", 3 | "spec_files": [ 4 | "**/*[sS]pec.js" 5 | ], 6 | "helpers": [ 7 | "helpers/**/*.js" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /status.txt: -------------------------------------------------------------------------------- 1 | 2 | ADD SUPPORT FOR 3 | * GENERIC BLOCKS 4 | * ELSE in EACH block 5 | * Generic tag type: <{{type}}> 6 | * COMMENTS. In attributes and tags 7 | * Handle {{this}} 8 | * Fixing the entire template where there is not single tag father. 9 | 10 | 11 | TO CHECK 12 | * Valdiate list of supported cases in both, node and attributes 13 | * Spaces in block are not supported? 14 | * Parameters in generic statements (single and blocks) which should be extracted from the context. These could be: 15 | REFRENCE VALUES 16 | LOOKUP VALUES 17 | SINGLE VALUES 18 | * Reference values used in: 19 | IF conditions 20 | UNLESS conditions 21 | EVALUATION iterator 22 | UNSAFEEVALUATION 23 | AFEEVALUATION 24 | GENERIC single 25 | GENERIC block 26 | 27 | OPTIMIZATIONS 28 | * IN VALUES: 29 | If all its string are simples, add those values in one single set. 30 | If the last value is a space ommit it 31 | 32 | --------------------------------------------------------------------------------