Browse Source

yuidoc: updated generators and templates to fix IE sidebar issue

Signed-off-by: Mihai Tudor Panu <mihai.tudor.panu@intel.com>
Mihai Tudor Panu 9 years ago
parent
commit
0c46dd28be

+ 6
- 9
doxy/node/docgen.js View File

@@ -43,20 +43,17 @@ opts
43 43
 
44 44
 // use promise-style programming rather than spaghetti callbacks
45 45
 Promise.promisifyAll(fs);
46
-
47
-
48
-// TODO: create directory structure if doesn't exist
49
-var formats = opts.formats.split(',');
50
-formats.forEach(function(format){
51
-  mkdirp('jsdoc/' + format + '/' + opts.module);
52
-});
46
+Promise.promisifyAll(mkdirp);
53 47
 
54 48
 
55 49
 // main
56 50
 xml2js.parse().then(function(specjs) {
51
+  var formats = opts.formats.split(',');
57 52
   Promise.all(_.map(formats, function(format) {
58 53
     var generateDocs = require(__dirname + '/generators/' + format + '/generator');
59
-    var outFile = opts.outdir + '/' + format + '/' + specjs.MODULE + '/doc.js';
60
-    return fs.writeFileAsync(outFile, generateDocs(specjs));
54
+    var dir = opts.outdir + '/' + format + '/' + specjs.MODULE;
55
+    return mkdirp.mkdirpAsync(dir).then(function() {
56
+      return fs.writeFileAsync(dir + '/doc.js', generateDocs(specjs));
57
+    });
61 58
   }));
62 59
 });

+ 1
- 0
doxy/node/generators/jsdoc/generator.js View File

@@ -58,6 +58,7 @@ function GENERATE_MODULE(module) {
58 58
 
59 59
 // generate method spec with parent module/class
60 60
 function GENERATE_METHOD(name, spec, parent) {
61
+  name = name.replace(/!+$/, '');
61 62
   return GENERATE_DOC(spec.description + '\n'
62 63
     + '@method ' + name + '\n'
63 64
     + '@instance\n'

+ 37
- 15
doxy/node/generators/ternjs/generator.js View File

@@ -28,44 +28,66 @@ var _ = require('lodash');
28 28
 
29 29
 // generate json for ternjs input
30 30
 function generateDocs(specjs) {
31
-  var docs = GENERATE_MODULE(specjs.MODULE);
32 31
   GENERATE_TYPE = (function(enums) {
33 32
     return function(type) {
34 33
       return (_.contains(enums, type) ? ('Enum ' + type) : type);
35 34
     }
36 35
   })(_.keys(specjs.ENUMS_BY_GROUP));
36
+  var docs = { '!name': specjs.MODULE + 'library' };
37
+  _.extend(docs, GENERATE_MODULE(specjs.MODULE));
37 38
   _.each(specjs.ENUMS, function(enumSpec, enumName) {
38 39
     _.extend(docs[specjs.MODULE], GENERATE_ENUM(enumName, enumSpec));
39 40
   });
40 41
   _.each(specjs.METHODS, function(methodSpec, methodName) {
41 42
     _.extend(docs[specjs.MODULE], GENERATE_METHOD(methodName, methodSpec));
42 43
   });
43
-  _.each(specjs.CLASSES, function(classSpec, parentClass) {
44
-    var constructor =  classSpec.methods[parentClass];
45
-    _.extend(docs[specjs.MODULE], GENERATE_METHOD(parentClass, constructor ? constructor : { params: {}, return: {}, description: '' } ));
46
-    _.each(classSpec.enums, function(enumSpec, enumName) {
47
-      _.extend(docs[specjs.MODULE][parentClass], GENERATE_ENUM(enumName, enumSpec));
48
-    });
49
-    docs[specjs.MODULE][parentClass].prototype = {};
50
-    _.each(_.omit(classSpec.methods, parentClass), function(methodSpec, methodName) {
51
-      _.extend(docs[specjs.MODULE][parentClass].prototype, GENERATE_METHOD(methodName, methodSpec));
52
-    });
53
-    _.each(classSpec.variables, function(variableSpec, variableName) {
54
-      _.extend(docs[specjs.MODULE][parentClass].prototype, GENERATE_VARIABLE(variableName, variableSpec));
44
+  
45
+  if (_.isEmpty(specjs.CLASSGROUPS)) {
46
+    _.extend(docs[specjs.MODULE], GENERATE_CLASSES(specjs.CLASSES));
47
+  } else {
48
+    var grouped = _.flatten(_.pluck(_.values(specjs.CLASSGROUPS), 'classes'));
49
+    var ungrouped = _.difference(_.keys(specjs.CLASSES), grouped);
50
+    _.extend(docs[specjs.MODULE], GENERATE_CLASSES(_.pick(specjs.CLASSES, ungrouped)));
51
+    _.each(specjs.CLASSGROUPS, function(groupSpec, groupName) {
52
+      _.extend(docs, GENERATE_MODULE(groupName));
53
+      _.extend(docs[groupName], GENERATE_CLASSES(_.pick(specjs.CLASSES, groupSpec.classes), groupName));
55 54
     });
56
-  });
55
+  }
57 56
   return JSON.stringify(docs, null, 2);
58 57
 }
59 58
 
60 59
 
61 60
 // generate module spec
62 61
 function GENERATE_MODULE(module) {
63
-  var docs = { '!name': module + 'library' };
62
+  var docs = {};
64 63
   docs[module] = {};
65 64
   return docs;
66 65
 }
67 66
 
68 67
 
68
+// generate the spec for the given list of classes
69
+function GENERATE_CLASSES(classes) {
70
+  var docs = {};
71
+  _.each(classes, function(classSpec, parentClass) {
72
+    var constructor =  classSpec.methods[parentClass];
73
+    _.extend(docs, GENERATE_METHOD(parentClass, constructor ? constructor : { params: {}, return: {}, description: '' } ));
74
+    if (_.has(docs, parentClass)) {
75
+      _.each(classSpec.enums, function(enumSpec, enumName) {
76
+        _.extend(docs[parentClass], GENERATE_ENUM(enumName, enumSpec));
77
+      });
78
+      docs[parentClass].prototype = {};
79
+      _.each(_.omit(classSpec.methods, parentClass), function(methodSpec, methodName) {
80
+        _.extend(docs[parentClass].prototype, GENERATE_METHOD(methodName, methodSpec));
81
+      });
82
+      _.each(classSpec.variables, function(variableSpec, variableName) {
83
+        _.extend(docs[parentClass].prototype, GENERATE_VARIABLE(variableName, variableSpec));
84
+      });
85
+    }
86
+  });
87
+  return docs;
88
+}
89
+
90
+
69 91
 // generate method spec
70 92
 function GENERATE_METHOD(name, spec) {
71 93
   var doc = {};

+ 10
- 4
doxy/node/generators/yuidoc/generator.js View File

@@ -46,7 +46,7 @@ function generateDocs(specjs) {
46 46
     docs += GENERATE_MODULE('common', '');
47 47
     var grouped = _.flatten(_.pluck(_.values(specjs.CLASSGROUPS), 'classes'));
48 48
     var ungrouped = _.difference(_.keys(specjs.CLASSES), grouped);
49
-    docs += GENERATE_CLASSES(_.pick(specjs.CLASSES, ungrouped), 'common');
49
+    docs += GENERATE_CLASSES(_.pick(specjs.CLASSES, ungrouped), 'common'); 
50 50
     _.each(specjs.CLASSGROUPS, function(groupSpec, groupName) {
51 51
       docs += GENERATE_CLASSES(_.pick(specjs.CLASSES, groupSpec.classes), groupName);
52 52
     });
@@ -76,7 +76,7 @@ function GENERATE_MODULE(name, description) {
76 76
 function GENERATE_CLASSES(classes, parent) {
77 77
   return _.reduce(classes, function(memo, classSpec, className) {
78 78
     return memo
79
-      + GENERATE_CLASS(className, classSpec.description, parent)
79
+      + GENERATE_CLASS(className, classSpec.description, parent, classSpec.parent)
80 80
       + _.reduce(classSpec.methods, function(memo, methodSpec, methodName) {
81 81
         return memo += GENERATE_METHOD(methodName, methodSpec, className);
82 82
       }, '') 
@@ -91,15 +91,21 @@ function GENERATE_CLASSES(classes, parent) {
91 91
 
92 92
 
93 93
 // generate class spec
94
-function GENERATE_CLASS(name, description, parent) {
94
+function GENERATE_CLASS(name, description, namespace, parent) {
95 95
   return GENERATE_DOC(description + '\n' 
96 96
     + '@class ' + name + '\n'
97
-    + (parent ? ('@module ' + parent + '\n') : ''));
97
+    + (namespace ? ('@module ' + namespace + '\n') : '')
98
+    /*
99
+    TODO: leave out until figure out what swig does with inheritance
100
+    + (parent ? ('@extends ' + parent + '\n') : '')
101
+    */
102
+  );
98 103
 }
99 104
 
100 105
 
101 106
 // generate method spec with parent module/class
102 107
 function GENERATE_METHOD(name, spec, parent) {
108
+  name = name.replace(/!+$/, '');
103 109
   return GENERATE_DOC(spec.description + '\n'
104 110
     + '@method ' + name + '\n'
105 111
     + (parent ? ('@for ' + parent + '\n') : '@for common\n')

+ 4
- 6
doxy/node/generators/yuidoc/helper.js View File

@@ -77,17 +77,15 @@ function listByGroup(modules, classes, field, projectRoot) {
77 77
   var groups = Object.keys(modulesByGroup).sort();
78 78
   var html = '';
79 79
   var pfx = projectRoot + 'modules/';
80
-  var first = true;
81 80
   for (i = 0; i < groups.length; i++) {
82 81
     var group = groups[i];
83
-    html += (first ? '' : '</span>');
84 82
     html += '<div class="upmGroup"><div class="right-arrow"></div>' + group + '</div><span class="upmModules" style="display:none">';
85 83
     var moduleNames = modulesByGroup[group];
86 84
     for (j = 0; j < moduleNames.length; j++) {
87 85
       var moduleName = moduleNames[j];
88 86
       html += '<a href="' + pfx + moduleName + '.html">' + moduleName + '</a>';
89 87
     }
90
-    first = false;
88
+    html += '</span>';
91 89
   }
92 90
   return html;
93 91
 }
@@ -117,7 +115,7 @@ var insertStyles = "Y.one(document.head).append('<style> \
117 115
     font-size: 0;                                        \
118 116
     margin-right: 5px;                                   \
119 117
     vertical-align: 5px;                                 \
120
-    display: inline;                                     \
118
+    float: left                                          \
121 119
   }                                                      \
122 120
   div.down-arrow {                                       \
123 121
     width: 0;                                            \
@@ -127,7 +125,7 @@ var insertStyles = "Y.one(document.head).append('<style> \
127 125
     border-top: 5px solid #356de4;                       \
128 126
     font-size: 0;                                        \
129 127
     margin-right: 5px;                                   \
130
-    display: inline;                                     \
128
+    float: left                                          \
131 129
   }                                                      \
132 130
   div.upmGroup {                                         \
133 131
     font-weight: bold;                                   \
@@ -137,7 +135,7 @@ var insertStyles = "Y.one(document.head).append('<style> \
137 135
 
138 136
 var scripts = "YUI().use('node', 'event', function (Y) {"
139 137
   + onClickHandler  
140
-  + insertStyles
138
+//  + insertStyles
141 139
   + "});";
142 140
 
143 141
 

+ 25
- 0
doxy/node/generators/yuidoc/tmpl/assets/css/main.css View File

@@ -787,3 +787,28 @@ kbd .cmd { font-family: Monaco, Helvetica; }
787 787
     font-weight: bold;
788 788
 }
789 789
 
790
+div.right-arrow {                                      
791
+    width: 0;                                            
792
+    height: 0;                                           
793
+    border-bottom: 5px solid transparent;                
794
+    border-top: 5px solid transparent;                   
795
+    border-left: 5px solid #356de4;                      
796
+    font-size: 0;                                        
797
+    margin-right: 5px;                                                            
798
+    float: left                                          
799
+  }                                                      
800
+
801
+div.down-arrow {                                       
802
+    width: 0;                                            
803
+    height: 0;                                           
804
+    border-left: 5px solid transparent;                  
805
+    border-right: 5px solid transparent;                 
806
+    border-top: 5px solid #356de4;                       
807
+    font-size: 0;                                        
808
+    margin-right: 5px;                                                                 
809
+    float: left                                          
810
+}                                                      
811
+
812
+div.upmGroup {                                         
813
+    font-weight: bold;                                   
814
+}                                                      

+ 96
- 9
doxy/node/xml2js.js View File

@@ -69,6 +69,8 @@ var xml2js = {
69 69
   // CLASSES: {
70 70
   //   <class name>: {
71 71
   //     description: <class description>,
72
+  //     parent: <parent class name>,
73
+  //     group: <group name>,
72 74
   //     methods: { ... },
73 75
   //     variables: {
74 76
   //       <variable name>: {
@@ -83,7 +85,9 @@ var xml2js = {
83 85
   // CLASSGROUPS: {
84 86
   //   <group name>: {
85 87
   //     description: <group description>,
86
-  //     classes: [ <class name>, ... ]
88
+  //     classes: [ <class name>, ... ],
89
+  //     enums: { ... },
90
+  //     enums_by_group: { ... }
87 91
   //   }, ...
88 92
   // }
89 93
   MODULE: '',
@@ -98,7 +102,8 @@ var xml2js = {
98 102
   TYPEMAPS: {
99 103
     '^(const)?\\s*(unsigned|signed)?\\s*(int|short|long|float|double|size_t|u?int\\d{1,2}_t)?$': 'Number',
100 104
     '^bool$': 'Boolean',
101
-    '^(const)?\\s*(unsigned|signed)?\\s*(char|char\\s*\\*|std::string)$': 'String'  // TODO: verify that swig does this mapping
105
+    '^(const)?\\s*(unsigned|signed)?\\s*(char|char\\s*\\*|std::string)$': 'String',  // TODO: verify that swig does this mapping
106
+    '^void\\s*\\(\\s*\\*\\s*\\)\\s*\\(\\s*void\\s*\\*\\)\\s*$': 'Function'
102 107
   },
103 108
 
104 109
 
@@ -157,13 +162,14 @@ var xml2js = {
157 162
           try {
158 163
             var spec_c = xmlparser.parse(xml)[0];
159 164
             var className = getName(spec_c);
160
-            xml2js.CLASSES[className] = {
165
+            _.extend(xml2js.CLASSES[className], {
161 166
               description: getDescription(spec_c),
167
+              parent: getParent(spec_c, className),
162 168
               enums: getEnums(spec_c, false, className),
163 169
               enums_by_group: getEnums(spec_c, true, className),
164 170
               variables: getVariables(spec_c, className),
165 171
               methods: getMethods(spec_c, className)
166
-            };
172
+            });
167 173
           } catch(e) {
168 174
             console.log(e.toString() + ': class ' + className + ' was not parsed correctly.');
169 175
           }
@@ -177,15 +183,48 @@ var xml2js = {
177 183
           return fs.readFileAsync(xml2js.opts.inputdir + '/' + fn, 'utf8').then(function(xml) {
178 184
             var spec_c = xmlparser.parse(xml)[0];
179 185
             if (_.isEmpty(getSubmodules(spec_c))) {
180
-              xml2js.CLASSGROUPS[getName(spec_c)] = {
186
+              var group = getName(spec_c);
187
+              var classes = getSubclassNames(spec_c);
188
+              xml2js.CLASSGROUPS[group] = {
181 189
                 description: getDescription(spec_c),
182
-                classes: getSubclassNames(spec_c)
183
-              }
190
+                classes: classes
191
+              };
192
+              _.each(classes, function(c) {
193
+                if (_.has(xml2js.CLASSES, c)) {
194
+                  xml2js.CLASSES[c].group = group;
195
+                } else {
196
+                  console.log('Warning: Group ' + group + ' has unknown class ' + c);
197
+                }
198
+              });
184 199
             }
185 200
           });
186 201
         }));
187 202
       });
188 203
       return Promise.all(parseClasses.concat(parseGroups));
204
+    }).then(function() {
205
+      if (!_.isEmpty(xml2js.CLASSGROUPS)) {
206
+        // try to categorize ungrouped classes, if any
207
+        var grouped = _.flatten(_.pluck(_.values(xml2js.CLASSGROUPS), 'classes'));
208
+        var ungrouped = _.difference(_.keys(xml2js.CLASSES), grouped);
209
+        _.each(ungrouped, function(c) {
210
+          _.each(findUsage(c), function(group) {
211
+            xml2js.CLASSGROUPS[group].classes.push(c);
212
+          });
213
+        });
214
+        grouped = _.flatten(_.pluck(_.values(xml2js.CLASSGROUPS), 'classes'));
215
+        ungrouped = _.difference(_.keys(xml2js.CLASSES), grouped);
216
+        // try to categorize ungrouped enums, if any
217
+        _.each(xml2js.ENUMS_BY_GROUP, function(enumGroupSpec, enumGroupName) {
218
+          _.each(findUsage(enumGroupName, true), function(c) {
219
+            xml2js.CLASSES[c].enums_by_group[enumGroupName] = enumGroupSpec;            
220
+            _.each(enumGroupSpec.members, function(enumName) {
221
+              xml2js.CLASSES[c].enums[enumName] = xml2js.ENUMS[enumName];
222
+              delete xml2js.ENUMS[enumName];
223
+            });
224
+            delete xml2js.ENUMS_BY_GROUP[enumGroupName];
225
+          });
226
+        });
227
+      }
189 228
     }).then(function() {
190 229
       if (xml2js.opts.custom && fs.existsSync(xml2js.opts.custom)) {
191 230
         return fs.readFileAsync(xml2js.opts.custom, 'utf8').then(function(custom) {
@@ -199,9 +238,9 @@ var xml2js = {
199 238
         console.log(xml2js.opts.custom ? ('Error: No such customization file exists: ' + xml2js.opts.custom) : 'No customizations given.');
200 239
       }
201 240
     }).then(function() {
241
+      generateCustomPointerClasses();       
202 242
       validateMethods();
203 243
       validateVars();
204
-      generateCustomPointerClasses();
205 244
       return _.pick(xml2js, 'MODULE', 'ENUMS', 'ENUMS_BY_GROUP', 'METHODS', 'CLASSES', 'CLASSGROUPS');
206 245
     });
207 246
   }
@@ -391,7 +430,30 @@ function generateCustomPointerClasses() {
391 430
 }
392 431
 
393 432
 
394
-// override autogenerated methods with custom configuration
433
+// search for usage of a type
434
+function findUsage(type, classOnly) {
435
+  var filterClasses = function(fn) { return _.without(_.map(xml2js.CLASSES, fn), undefined); };
436
+  var usesType = function(classSpec, className) {
437
+    var methodsOfType = (_.find(classSpec.methods, function(methodSpec, methodName) {
438
+      return ((!_.isEmpty(methodSpec.return) && methodSpec.return.type == type) || 
439
+              (_.contains(_.pluck(methodSpec.params, 'type'), type)));
440
+    }) != undefined);
441
+    var variablesOfType = _.contains(_.pluck(classSpec.variable, 'type'), type);
442
+    return ((methodsOfType || variablesOfType) ? className : undefined);
443
+  };
444
+  var extendsType = function(classSpec, className) {
445
+    return ((classSpec.parent == type) ? className : undefined);
446
+  };
447
+  var classes = _.union(filterClasses(usesType), filterClasses(extendsType));
448
+  if (classOnly) {
449
+    return classes;
450
+  } else {
451
+    return _.without(_.uniq(_.pluck(_.pick(xml2js.CLASSES, classes), 'group')), undefined);
452
+  }
453
+}
454
+
455
+
456
+// override autogenerated methods with custom configuration 
395 457
 function customizeMethods(custom) {
396 458
   _.each(custom, function(classMethods, className) {
397 459
     _.extend(xml2js.CLASSES[className].methods, _.pick(classMethods, function(methodSpec, methodName) {
@@ -527,6 +589,19 @@ function getSubmodules(spec_c) {
527 589
 }
528 590
 
529 591
 
592
+// get parent class, if any
593
+function getParent(spec_c, className) {
594
+  var parent = getChild(spec_c, 'basecompoundref');
595
+  if (parent) {
596
+    parent = getText(parent);
597
+    if (!_.has(xml2js.CLASSES, parent)) {
598
+      console.log('WARNING: Class ' + className + ' has unknown parent class ' + parent);
599
+    }
600
+  }
601
+  return parent;
602
+}
603
+
604
+
530 605
 function hasParams(paramsSpec) {
531 606
   return !(_.isEmpty(paramsSpec) ||
532 607
            ((_.size(paramsSpec) == 1) && getText(getChild(paramsSpec[0], 'type')) == 'void'));
@@ -559,6 +634,7 @@ function getMethods(spec_c, parent) {
559 634
           if (!_.isEmpty(returnSpec)) {
560 635
             retval = getReturn(returnSpec, getReturnDetails(description), methodName, parent);
561 636
           }
637
+          methodName = getUniqueMethodName(methodName, spec_js, parent);
562 638
           spec_js[methodName] = {
563 639
             description: methodDescription,
564 640
             params: params,
@@ -575,6 +651,17 @@ function getMethods(spec_c, parent) {
575 651
 }
576 652
 
577 653
 
654
+// get a unique string to represent the name of an overloaded method
655
+function getUniqueMethodName(methodName, module, parent) {
656
+  if (methodName in module) {
657
+    do {
658
+      methodName += '!';
659
+    } while (methodName in module);
660
+  }
661
+  return methodName;
662
+}
663
+
664
+
578 665
 // get variable specifications for a class
579 666
 function getVariables(spec_c, parent) {
580 667
   var spec_js = {};