source: Dev/branches/rest-dojo-ui/client/dojox/lang/docs.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 5.6 KB
Line 
1dojo.provide("dojox.lang.docs");
2
3// Extracts information from the API docs to apply a schema representation to dojo classes.
4// This can be utilized for runtime metadata retrieval and type checking
5(function(){
6        function error(error){
7                console.log("Warning, the API docs must be available at ../util/docscripts/api.json "+
8                "or ../util/docscripts/api/*.json "+
9                "in order for dojox.lang.docs to supply schema information, but it could not be loaded: " + error);
10        }
11
12        var declaredClasses = {};
13        var requiredModules = [];
14        var _docs = dojox.lang.docs._loadedDocs = {};
15
16        var schemifyClass = function(clazz, name){
17                // initial implementation records classes until they are ready
18                declaredClasses[name] = clazz;
19        };
20        var getType = function(typeDef){
21                var type = typeDef.type || '';
22                var typeObj, optional = false, array = false, dontModify;
23                type = type.replace(/\?/, function(){
24                        optional = true;
25                        return '';
26                });
27                type = type.replace(/\[\]/, function(){
28                        array = true;
29                        return '';
30                });
31                if(type.match(/HTML/)){
32                        // HTML String and other "types" of strings are really just strings
33                        type = "string";
34                }else if(type == 'String' || type == 'Number' ||
35                                type == 'Boolean' || type == 'Object' ||
36                                type == 'Array' || type == 'Integer' || type == "Function"){
37                        type = type.toLowerCase();
38                }else if(type == "bool"){
39                        type = "boolean";
40                }else if(type){
41                        typeObj = dojo.getObject(type) || {};
42                        dontModify = true;
43                }else{
44                        typeObj = {};
45                }
46                typeObj = typeObj || {type:type};
47                if(array){
48                        typeObj = {items:typeObj, type:"array"};
49                        dontModify = false;
50                }
51                if(!dontModify){
52                        if(optional){
53                                typeObj.optional = true;
54                        }
55                        if(/const/.test(typeDef.tags)){
56                                typeObj.readonly = true;
57                        }
58                }
59                return typeObj;
60        };
61        var actualSchemifyClass = function(clazz, name){
62                var docForClass = _docs[name];
63                if(docForClass){
64                        clazz.description = docForClass.description;
65                        clazz.properties = {};
66                        clazz.methods = {};
67
68                        if(docForClass.properties){
69                                var props = docForClass.properties;
70                                for(var i=0, l=props.length; i<l; i++){
71                                        if(props[i].scope == "prototype"){
72                                                var propDef = clazz.properties[props[i].name] = getType(props[i]);
73                                                propDef.description = props[i].summary;
74                                        }
75                                }
76                        }
77
78                        // translate the methods to JSON Schema
79                        if(docForClass.methods){
80                                var methods = docForClass.methods;
81                                for(i=0, l=methods.length; i<l; i++){
82                                        name = methods[i].name;
83                                        if(name && methods[i].scope == "prototype"){
84                                                var methodDef = clazz.methods[name] = {};
85                                                methodDef.description = methods[i].summary;
86                                                var parameters = methods[i].parameters;
87                                                if(parameters){
88                                                        methodDef.parameters = [];
89                                                        for(var j=0, k=parameters.length; j<k; j++){
90                                                                var param = parameters[j];
91                                                                var paramDef = methodDef.parameters[j] = getType(param);
92                                                                paramDef.name = param.name;
93                                                                paramDef.optional = "optional" == param.usage;
94                                                        }
95                                                }
96                                                var ret = methods[i]['return-types'];
97                                                if(ret && ret[0]){
98                                                        var returns = getType(ret[0]);
99                                                        if(returns.type){
100                                                                methodDef.returns = returns;
101                                                        }
102                                                }
103                                        }
104                                }
105                        }
106
107                        var superclass = docForClass.superclass;
108                        if(superclass){
109                                clazz["extends"] = dojo.getObject(superclass);
110                        }
111                }
112        };
113        var requireDocs = function(moduleName){
114                requiredModules.push(moduleName);
115        };
116
117        // hook into all declared classes
118        var defaultDeclare = dojo.declare;
119        dojo.declare = function(name){
120                var clazz = defaultDeclare.apply(this, arguments);
121                schemifyClass(clazz, name);
122                return clazz;
123        };
124        dojo.mixin(dojo.declare, defaultDeclare);
125        var initialized;
126
127        // hook into dojo.require
128        var defaultRequire = dojo.require;
129        dojo.require = function(moduleName){
130                requireDocs(moduleName);
131                var module = defaultRequire.apply(this, arguments);
132                return module;
133        };
134
135        dojox.lang.docs.init = function(/*Boolean*/async){
136                // summary:
137                //              Loads the documentation and applies it to the previously defined classes
138                //              and any future defined classes
139                //
140                // async:
141                //               If true, the documentation will be loaded asynchronously
142                function loadFullDocs(){
143                        dojo.require = defaultRequire;
144                        requiredModules = null;
145                        try{
146                                dojo.xhrGet({
147                                        sync:!async,
148                                        url: dojo.baseUrl + '../util/docscripts/api.json',
149                                        handleAs: 'text'
150                                }).addCallbacks(function(obj){
151                                        _docs = (new Function("return " + obj))();
152                                        obj = null;
153                                        schemifyClass = actualSchemifyClass;
154
155                                        for(var i in declaredClasses){
156                                                schemifyClass(declaredClasses[i], i);
157                                        }
158                                        declaredClasses = null;
159                                }, error);
160                        }catch(e){
161                                error(e);
162                        }
163                }
164               
165                if(initialized){
166                        return null;
167                }
168                initialized = true;
169
170                var getSplitDocs = function(moduleName, sync){
171                        return dojo.xhrGet({
172                                sync: sync||!async,
173                                url: dojo.baseUrl + '../util/docscripts/api/' + moduleName + '.json',
174                                handleAs: 'text'
175                        }).addCallback(function(obj){
176                                obj = (new Function("return " + obj))();
177                                for(var clazz in obj){
178                                        if(!_docs[clazz]){
179                                                _docs[clazz] = obj[clazz];
180                                        }
181                                }
182                        });
183                };
184                try{
185                        var firstMod = requiredModules.shift();
186                        getSplitDocs(firstMod, true).addCallbacks(function(){
187                                requireDocs = function(moduleName){
188                                        if(!_docs[moduleName]){
189                                                try{
190                                                        getSplitDocs(moduleName);
191                                                }catch(e){
192                                                        _docs[moduleName] = {};
193                                                }
194                                        }
195                                };
196                                //console.log(requiredModules);
197                                dojo.forEach(requiredModules, function(mod){
198                                        requireDocs(mod);
199                                });
200                                requiredModules = null;
201
202                                schemifyClass = actualSchemifyClass;
203
204                                for(i in declaredClasses){
205                                        schemifyClass(declaredClasses[i], i);
206                                }
207                                declaredClasses = null;
208                        },loadFullDocs);
209                }catch(e){
210                        loadFullDocs();
211                }
212                return null;
213        }
214})();
Note: See TracBrowser for help on using the repository browser.