@qubit-ltd/jsdoc-theme 1.3.6 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # qubit-jsdoc-theme
2
2
 
3
- [![Stars](https://img.shields.io/github/stars/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme) [![Fork](https://img.shields.io/github/forks/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/fork) ![Version](https://img.shields.io/badge/version-1.2.0-005bff) [![Issues Open](https://img.shields.io/github/issues/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/issues) [![Contributors](https://img.shields.io/github/contributors/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/graphs/contributors) [![license](https://img.shields.io/github/license/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/blob/master/LICENSE)
3
+ [![Stars](https://img.shields.io/github/stars/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme) [![Fork](https://img.shields.io/github/forks/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/fork) ![Version](https://img.shields.io/badge/version-1.5.0-005bff) [![Issues Open](https://img.shields.io/github/issues/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/issues) [![Contributors](https://img.shields.io/github/contributors/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/graphs/contributors) [![license](https://img.shields.io/github/license/Haixing-Hu/qubit-jsdoc-theme)](https://github.com/Haixing-Hu/qubit-jsdoc-theme/blob/master/LICENSE)
4
4
  <br>
5
5
 
6
6
  **Based on [clean-jsdoc-theme](https://github.com/ankitskvmdam/clean-jsdoc-theme) v4.3.0**
@@ -10,9 +10,12 @@
10
10
  ## Enhanced Features (New in qubit-jsdoc-theme)
11
11
 
12
12
  - **🆕 Smart Properties Table:** Automatically generates a dedicated "Properties" section for classes, displaying all class properties in a clean table format with type information and descriptions derived from individual field JSDoc comments.
13
+ - **🆕 Static/Instance Property Separation:** Intelligently separates static and instance properties into distinct sections, with automatic scope detection and fallback logic for accurate classification.
14
+ - **🆕 Getter/Setter Pair Merging:** Automatically detects and merges getter/setter pairs into single table entries, displaying combined descriptions and access type indicators.
13
15
  - **🆕 Intelligent Constructor Detection:** Only displays the "Constructor" section when a class has explicit constructor documentation, avoiding empty constructor sections for classes without custom constructors.
14
16
  - **🆕 Field-Level JSDoc Support:** Properties table is populated directly from `@type` annotations on individual class fields, eliminating the need for redundant `@property` tags in class-level JSDoc.
15
17
  - **🆕 Clean Member Organization:** Properties are displayed in their own dedicated section, while the "Members" section can be configured to show only methods, avoiding duplication.
18
+ - **🆕 Enhanced Mixin Support:** Automatically displays methods inherited from mixin classes when using `@mixes` JSDoc tags, providing complete documentation of mixed-in functionality with proper inheritance attribution.
16
19
  - **🆕 Internationalization (i18n):** Full support for multiple languages with comprehensive translation of all UI elements, section headings, table headers, and navigation tooltips.
17
20
  - **🆕 Homepage Navigation:** Added a "Back to Homepage" button in the top navigation bar for easy navigation between class documentation and the main documentation index.
18
21
  - **🆕 Enhanced Tooltips:** All navigation buttons include internationalized tooltips that adapt to the selected language.
@@ -32,8 +35,10 @@
32
35
  The enhanced features of `qubit-jsdoc-theme` include:
33
36
 
34
37
  1. **Smart Properties Table**: Automatically generated from field-level `@type` annotations
35
- 2. **Intelligent Constructor Detection**: Only shows constructor section when explicitly documented
36
- 3. **Clean Organization**: Properties and methods are clearly separated
38
+ 2. **Static/Instance Property Separation**: Properties are automatically categorized and displayed in separate sections
39
+ 3. **Getter/Setter Pair Merging**: Related accessor methods are intelligently combined in the properties table
40
+ 4. **Intelligent Constructor Detection**: Only shows constructor section when explicitly documented
41
+ 5. **Clean Organization**: Properties and methods are clearly separated with enhanced categorization
37
42
 
38
43
  For the base theme features and styling, you can reference the original [clean-jsdoc-theme demo](https://ankdev.me/clean-jsdoc-theme/v4).
39
44
 
@@ -96,6 +101,13 @@ Here's how to document your JavaScript classes to take advantage of the enhanced
96
101
  * @author John Doe
97
102
  */
98
103
  class User {
104
+ /**
105
+ * Total number of users created
106
+ * @type {number}
107
+ * @static
108
+ */
109
+ static userCount = 0;
110
+
99
111
  /**
100
112
  * User's unique identifier
101
113
  * @type {string}
@@ -120,6 +132,24 @@ class User {
120
132
  */
121
133
  isActive;
122
134
 
135
+ /**
136
+ * Get user's full display information
137
+ * @type {string}
138
+ */
139
+ get displayInfo() {
140
+ return `${this.name} (${this.email})`;
141
+ }
142
+
143
+ /**
144
+ * Set user's full display information
145
+ * @type {string}
146
+ */
147
+ set displayInfo(value) {
148
+ const parts = value.split(' (');
149
+ this.name = parts[0];
150
+ this.email = parts[1]?.replace(')', '') || '';
151
+ }
152
+
123
153
  /**
124
154
  * Creates a new user instance
125
155
  * @param {string} name - The user's name
@@ -129,6 +159,7 @@ class User {
129
159
  this.name = name;
130
160
  this.email = email;
131
161
  this.isActive = true;
162
+ User.userCount++;
132
163
  }
133
164
 
134
165
  /**
@@ -143,9 +174,10 @@ class User {
143
174
  ```
144
175
 
145
176
  This will generate documentation with:
146
- - A dedicated "Properties" section showing all class properties in a table
147
- - A "Constructor" section (only if constructor has documentation)
148
- - A "Members" section for methods (properties are excluded to avoid duplication)
177
+ - **Static Properties section**: Showing `userCount` and other static properties
178
+ - **Instance Properties section**: Showing `id`, `name`, `email`, `isActive` and merged `displayInfo` (getter/setter)
179
+ - **Constructor section**: Only displayed when constructor has documentation
180
+ - **Members section**: For methods like `activate()` (properties are excluded to avoid duplication)
149
181
 
150
182
  ## Example JSDoc Config
151
183
 
@@ -705,11 +737,51 @@ Don't forget to add the following in your jsdoc config file, otherwise toc will
705
737
 
706
738
  ## Changelog
707
739
 
740
+ ### v1.5.0 (2025-01-XX)
741
+
742
+ **Advanced Property Management & Enhanced Documentation Features**
743
+
744
+ #### 🔧 New Features
745
+ - **Static/Instance Property Separation**: Automatically separates static and instance properties into distinct sections with intelligent scope detection
746
+ - **Getter/Setter Pair Merging**: Smart detection and merging of getter/setter pairs into unified table entries with combined descriptions
747
+ - **Enhanced Scope Detection**: Improved logic for detecting property scope using JSDoc's built-in detection with fallback heuristics
748
+ - **Access Type Indicators**: Clear visual indicators for property access types (property, getter, setter, getter/setter)
749
+
750
+ #### 🛠️ Technical Improvements
751
+ - **Advanced Template Logic**: Enhanced `container.tmpl` with sophisticated property categorization and merging algorithms
752
+ - **Improved Properties Template**: Updated `properties.tmpl` to support separate rendering of static and instance properties
753
+ - **Fallback Scope Detection**: Added longname pattern analysis for accurate scope detection when JSDoc's built-in detection fails
754
+ - **Bilingual Section Headers**: Support for both English and Chinese section headers in property tables
755
+
756
+ #### 📖 Documentation Updates
757
+ - **Enhanced Usage Examples**: Updated examples to demonstrate static properties and getter/setter documentation
758
+ - **Feature Documentation**: Comprehensive documentation for new property management features
759
+
760
+ ### v1.4.0 (2025-01-XX)
761
+
762
+ **Enhanced Mixin Documentation Support**
763
+
764
+ #### 🔧 New Features
765
+ - **Complete Mixin Method Documentation**: Automatically displays methods inherited from mixin classes when using `@mixes` JSDoc tags
766
+ - **Proper Inheritance Attribution**: Methods from mixin classes are displayed with clear "Inherited from [MixinClass]" labels
767
+ - **Full Method Documentation**: Includes complete parameter descriptions, return values, and method documentation from mixin classes
768
+ - **Seamless Integration**: Works transparently with existing `@mixes` tags without requiring code changes
769
+
770
+ #### 🛠️ Technical Improvements
771
+ - **Enhanced Template Logic**: Updated `container.tmpl` to collect and display methods from mixed-in classes
772
+ - **Dynamic Method Collection**: Automatically searches for methods in classes specified by `@mixes` tags
773
+ - **Inheritance Flag Support**: Properly marks mixin methods as inherited for correct documentation formatting
774
+
775
+ #### 📖 Documentation Updates
776
+ - **Updated Examples**: Enhanced usage examples to demonstrate mixin documentation features
777
+ - **Feature Documentation**: Added comprehensive documentation for the new mixin method display functionality
778
+
708
779
  ### v1.2.0 (2025-01-XX)
709
780
 
710
781
  **Major Update - Internationalization & Navigation Enhancements**
711
782
 
712
783
  #### 🌍 New Features
784
+ - **Enhanced Mixin Documentation**: Automatic detection and display of methods inherited from mixin classes when using `@mixes` JSDoc tags, with proper "Inherited from" attribution
713
785
  - **Full Internationalization (i18n)**: Complete support for multiple languages with comprehensive translation system
714
786
  - **Homepage Navigation Button**: Added "Back to Homepage" button in top navigation bar for easy navigation
715
787
  - **Internationalized Tooltips**: All navigation buttons now include language-aware tooltips
package/i18n/en.json CHANGED
@@ -36,6 +36,7 @@
36
36
  "requires": "Requires",
37
37
  "interfaces": "Interfaces",
38
38
  "mixins": "Mixins",
39
+ "externals": "Externals",
39
40
  "type_definitions": "Type Definitions",
40
41
  "optional": "optional",
41
42
  "nullable": "nullable",
package/i18n/zh.json CHANGED
@@ -36,6 +36,7 @@
36
36
  "requires": "依赖",
37
37
  "interfaces": "接口",
38
38
  "mixins": "混入",
39
+ "externals": "外部",
39
40
  "type_definitions": "类型定义",
40
41
  "optional": "可选",
41
42
  "nullable": "可为空",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qubit-ltd/jsdoc-theme",
3
- "version": "1.3.6",
3
+ "version": "1.5.0",
4
4
  "description": "A customized JSDoc theme based on clean-jsdoc-theme, enhanced with properties table and constructor detection features for Qubit projects.",
5
5
  "main": "publish.js",
6
6
  "author": "Haixing Hu (starfish.hu@gmail.com)",
package/publish.js CHANGED
@@ -555,7 +555,7 @@ function buildSidebar(members) {
555
555
 
556
556
  const sections = {
557
557
  [SECTION_TYPE.Modules]: buildSidebarMembers({
558
- itemHeading: "Modules",
558
+ itemHeading: i18n.t("module", "Modules"),
559
559
  items: members.modules,
560
560
  itemsSeen: seen,
561
561
  linktoFn: linkto,
@@ -571,7 +571,7 @@ function buildSidebar(members) {
571
571
  }),
572
572
 
573
573
  [SECTION_TYPE.Externals]: buildSidebarMembers({
574
- itemHeading: "Externals",
574
+ itemHeading: i18n.t("externals", "Externals"),
575
575
  items: members.externals,
576
576
  itemsSeen: seen,
577
577
  linktoFn: linktoExternal,
@@ -579,7 +579,7 @@ function buildSidebar(members) {
579
579
  }),
580
580
 
581
581
  [SECTION_TYPE.Events]: buildSidebarMembers({
582
- itemHeading: "Events",
582
+ itemHeading: i18n.t("events", "Events"),
583
583
  items: members.events,
584
584
  itemsSeen: seen,
585
585
  linktoFn: linkto,
@@ -587,7 +587,7 @@ function buildSidebar(members) {
587
587
  }),
588
588
 
589
589
  [SECTION_TYPE.Namespaces]: buildSidebarMembers({
590
- itemHeading: "Namespaces",
590
+ itemHeading: i18n.t("namespaces", "Namespaces"),
591
591
  items: members.namespaces,
592
592
  itemsSeen: seen,
593
593
  linktoFn: linkto,
@@ -595,7 +595,7 @@ function buildSidebar(members) {
595
595
  }),
596
596
 
597
597
  [SECTION_TYPE.Mixins]: buildSidebarMembers({
598
- itemHeading: "Mixins",
598
+ itemHeading: i18n.t("mixins", "Mixins"),
599
599
  items: members.mixins,
600
600
  itemsSeen: seen,
601
601
  linktoFn: linkto,
@@ -603,7 +603,7 @@ function buildSidebar(members) {
603
603
  }),
604
604
 
605
605
  [SECTION_TYPE.Tutorials]: buildSidebarMembers({
606
- itemHeading: "Tutorials",
606
+ itemHeading: i18n.t("tutorials", "Tutorials"),
607
607
  items: members.tutorials,
608
608
  itemsSeen: seenTutorials,
609
609
  linktoFn: linktoTutorial,
@@ -611,7 +611,7 @@ function buildSidebar(members) {
611
611
  }),
612
612
 
613
613
  [SECTION_TYPE.Interfaces]: buildSidebarMembers({
614
- itemHeading: "Interfaces",
614
+ itemHeading: i18n.t("interfaces", "Interfaces"),
615
615
  items: members.interfaces,
616
616
  itemsSeen: seen,
617
617
  linktoFn: linkto,
@@ -152,18 +152,103 @@
152
152
  }
153
153
 
154
154
  if (allMembers && allMembers.length && allMembers.forEach) {
155
- // Create a temporary properties array
156
- var propertiesData = {
157
- properties: allMembers.map(function(member) {
158
- return {
159
- name: member.name,
155
+ // Separate static and instance properties, merge getter/setter pairs
156
+ var staticProperties = {};
157
+ var instanceProperties = {};
158
+
159
+ allMembers.forEach(function(member) {
160
+ // Use JSDoc's built-in scope detection with fallback logic
161
+ // JSDoc sometimes misidentifies scope in mixin classes, so we add some heuristics
162
+ var isStatic = member.scope === 'static';
163
+
164
+ // Fallback: check longname pattern for static members (uses '.' separator)
165
+ // and instance members (uses '#' separator)
166
+ if (member.longname) {
167
+ var hasStaticSeparator = member.longname.indexOf('.') > member.longname.lastIndexOf('#');
168
+ var hasInstanceSeparator = member.longname.indexOf('#') > member.longname.lastIndexOf('.');
169
+
170
+ if (hasStaticSeparator && !hasInstanceSeparator) {
171
+ isStatic = true;
172
+ } else if (hasInstanceSeparator && !hasStaticSeparator) {
173
+ isStatic = false;
174
+ }
175
+ }
176
+
177
+ var targetObj = isStatic ? staticProperties : instanceProperties;
178
+ var propName = member.name;
179
+
180
+ if (!targetObj[propName]) {
181
+ targetObj[propName] = {
182
+ name: propName,
160
183
  type: member.type,
161
184
  description: member.description || '',
162
185
  nullable: member.nullable,
163
186
  optional: member.optional,
164
- defaultvalue: member.defaultvalue
187
+ defaultvalue: member.defaultvalue,
188
+ isStatic: isStatic,
189
+ hasGetter: false,
190
+ hasSetter: false,
191
+ getterDescription: '',
192
+ setterDescription: ''
165
193
  };
166
- })
194
+ }
195
+
196
+ // Check if this is a getter or setter based on description or other indicators
197
+ var desc = (member.description || '').toLowerCase();
198
+ if (desc.indexOf('获取') === 0 || desc.indexOf('get') === 0) {
199
+ targetObj[propName].hasGetter = true;
200
+ targetObj[propName].getterDescription = member.description || '';
201
+ } else if (desc.indexOf('设置') === 0 || desc.indexOf('set') === 0) {
202
+ targetObj[propName].hasSetter = true;
203
+ targetObj[propName].setterDescription = member.description || '';
204
+ } else {
205
+ // Regular property, use the description as is
206
+ if (!targetObj[propName].description) {
207
+ targetObj[propName].description = member.description || '';
208
+ }
209
+ }
210
+ });
211
+
212
+ // Convert objects to arrays
213
+ var staticPropsArray = Object.keys(staticProperties).map(function(key) {
214
+ var prop = staticProperties[key];
215
+ // Combine getter/setter descriptions
216
+ if (prop.hasGetter && prop.hasSetter) {
217
+ prop.description = prop.getterDescription + ' / ' + prop.setterDescription;
218
+ prop.accessType = 'getter/setter';
219
+ } else if (prop.hasGetter) {
220
+ prop.description = prop.getterDescription;
221
+ prop.accessType = 'getter';
222
+ } else if (prop.hasSetter) {
223
+ prop.description = prop.setterDescription;
224
+ prop.accessType = 'setter';
225
+ } else {
226
+ prop.accessType = 'property';
227
+ }
228
+ return prop;
229
+ });
230
+
231
+ var instancePropsArray = Object.keys(instanceProperties).map(function(key) {
232
+ var prop = instanceProperties[key];
233
+ if (prop.hasGetter && prop.hasSetter) {
234
+ prop.description = prop.getterDescription + ' / ' + prop.setterDescription;
235
+ prop.accessType = 'getter/setter';
236
+ } else if (prop.hasGetter) {
237
+ prop.description = prop.getterDescription;
238
+ prop.accessType = 'getter';
239
+ } else if (prop.hasSetter) {
240
+ prop.description = prop.setterDescription;
241
+ prop.accessType = 'setter';
242
+ } else {
243
+ prop.accessType = 'property';
244
+ }
245
+ return prop;
246
+ });
247
+
248
+ // Create properties data with both static and instance properties
249
+ var propertiesData = {
250
+ staticProperties: staticPropsArray,
251
+ instanceProperties: instancePropsArray
167
252
  };
168
253
  ?>
169
254
  <h2 id="properties" class="subsection-title has-anchor"><?js= t('properties') ?></h2>
@@ -199,6 +284,24 @@
199
284
 
200
285
  <?js
201
286
  var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname, ...shouldExcludeInherited});
287
+
288
+ // Add mixin methods if this class has @mixes tags
289
+ if (doc.mixes && doc.mixes.length) {
290
+ doc.mixes.forEach(function(mixinName) {
291
+ var mixinMethods = self.find({kind: 'function', memberof: mixinName});
292
+ if (mixinMethods && mixinMethods.length) {
293
+ // Add inherited flag and source info to mixin methods
294
+ mixinMethods.forEach(function(mixinMethod) {
295
+ mixinMethod.inherited = true;
296
+ mixinMethod.inherits = mixinName;
297
+ mixinMethod.mixinSource = mixinName;
298
+ });
299
+ // Merge mixin methods with current class methods
300
+ methods = methods.concat(mixinMethods);
301
+ }
302
+ });
303
+ }
304
+
202
305
  if (methods && methods.length && methods.forEach) {
203
306
  ?>
204
307
  <h2 id="methods" class="subsection-title has-anchor"><?js= t('methods') ?></h2>
package/tmpl/method.tmpl CHANGED
@@ -7,13 +7,19 @@ var self = this;
7
7
  // Check if this is a class with an explicit constructor
8
8
  var hasExplicitConstructor = false;
9
9
  if (data.kind === 'class') {
10
- // Only consider constructor-specific documentation, not class-level documentation
11
- hasExplicitConstructor = data.params && data.params.length > 0 ||
12
- (data.description && data.description !== data.classdesc) ||
13
- data.examples && data.examples.length > 0 ||
14
- data.see && data.see.length > 0 ||
15
- data.since;
16
- // Note: We exclude @author as it's typically class-level, not constructor-specific
10
+ // Only show constructor if:
11
+ // 1. Has constructor parameters OR
12
+ // 2. Has constructor-specific description (different from class description) OR
13
+ // 3. Has constructor-specific examples/see/since AND also has params or different description
14
+
15
+ var hasConstructorParams = data.params && data.params.length > 0;
16
+ var hasConstructorSpecificDescription = data.description &&
17
+ data.description !== data.classdesc &&
18
+ data.description.trim() !== '';
19
+
20
+ // For MixIn classes and similar patterns, avoid showing constructor
21
+ // unless there are clear constructor-specific elements
22
+ hasExplicitConstructor = hasConstructorParams || hasConstructorSpecificDescription;
17
23
  }
18
24
  ?>
19
25
  <?js if (data.kind !== 'module' && !data.hideconstructor) { ?>
@@ -1,109 +1,132 @@
1
1
  <?js
2
2
  var data = obj;
3
- var props = data.subprops || data.properties;
4
-
5
- /* sort subprops under their parent props (like opts.classname) */
6
- var parentProp = null;
7
- props.forEach(function(prop, i) {
8
- if (!prop) { return; }
9
- if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) {
10
- prop.name = prop.name.substr(parentProp.name.length+1);
11
- parentProp.subprops = parentProp.subprops || [];
12
- parentProp.subprops.push(prop);
13
- props[i] = null;
14
- }
15
- else {
16
- parentProp = prop;
17
- }
18
- });
3
+ var self = this;
4
+
5
+ // Handle both old format (single properties array) and new format (static/instance separation)
6
+ var staticProps = data.staticProperties || [];
7
+ var instanceProps = data.instanceProperties || data.properties || [];
8
+
9
+ // Function to render a properties table
10
+ function renderPropertiesTable(props, title) {
11
+ if (!props || props.length === 0) return '';
12
+
13
+ /* sort subprops under their parent props (like opts.classname) */
14
+ var parentProp = null;
15
+ props.forEach(function(prop, i) {
16
+ if (!prop) { return; }
17
+ if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) {
18
+ prop.name = prop.name.substr(parentProp.name.length+1);
19
+ parentProp.subprops = parentProp.subprops || [];
20
+ parentProp.subprops.push(prop);
21
+ props[i] = null;
22
+ }
23
+ else {
24
+ parentProp = prop;
25
+ }
26
+ });
27
+
28
+ /* determine if we need extra columns, "attributes" and "default" */
29
+ props.hasAttributes = false;
30
+ props.hasDefault = false;
31
+ props.hasName = false;
32
+
33
+ props.forEach(function(prop) {
34
+ if (!prop) { return; }
35
+
36
+ if (prop.optional || prop.nullable) {
37
+ props.hasAttributes = true;
38
+ }
19
39
 
20
- /* determine if we need extra columns, "attributes" and "default" */
21
- props.hasAttributes = false;
22
- props.hasDefault = false;
23
- props.hasName = false;
40
+ if (prop.name) {
41
+ props.hasName = true;
42
+ }
24
43
 
25
- props.forEach(function(prop) {
26
- if (!prop) { return; }
44
+ if (typeof prop.defaultvalue !== 'undefined' && !data.isEnum) {
45
+ props.hasDefault = true;
46
+ }
47
+ });
27
48
 
28
- if (prop.optional || prop.nullable) {
29
- props.hasAttributes = true;
49
+ var html = '';
50
+ if (title) {
51
+ html += '<h3 class="subsection-title">' + title + '</h3>';
30
52
  }
31
53
 
32
- if (prop.name) {
33
- props.hasName = true;
54
+ html += '<div class="allow-overflow">';
55
+ html += '<table class="props">';
56
+ html += '<thead><tr>';
57
+
58
+ if (props.hasName) {
59
+ html += '<th>' + t('name') + '</th>';
34
60
  }
61
+ html += '<th>' + t('type') + '</th>';
35
62
 
36
- if (typeof prop.defaultvalue !== 'undefined' && !data.isEnum) {
37
- props.hasDefault = true;
63
+ if (props.hasAttributes) {
64
+ html += '<th>' + t('attributes') + '</th>';
38
65
  }
39
- });
40
- ?>
41
- <div class="allow-overflow">
42
- <table class="props">
43
- <thead>
44
- <tr>
45
- <?js if (props.hasName) {?>
46
- <th><?js= t('name') ?></th>
47
- <?js } ?>
48
-
49
- <th><?js= t('type') ?></th>
50
-
51
- <?js if (props.hasAttributes) {?>
52
- <th><?js= t('attributes') ?></th>
53
- <?js } ?>
54
-
55
- <?js if (props.hasDefault) {?>
56
- <th><?js= t('default') ?></th>
57
- <?js } ?>
58
-
59
- <th class="last"><?js= t('description') ?></th>
60
- </tr>
61
- </thead>
62
-
63
- <tbody>
64
- <?js
65
- var self = this;
66
+
67
+ if (props.hasDefault) {
68
+ html += '<th>' + t('default') + '</th>';
69
+ }
70
+
71
+ html += '<th class="last">' + t('description') + '</th>';
72
+ html += '</tr></thead><tbody>';
73
+
66
74
  props.forEach(function(prop) {
67
75
  if (!prop) { return; }
68
- ?>
69
-
70
- <tr>
71
- <?js if (props.hasName) {?>
72
- <td class="name"><code><?js= prop.name ?></code></td>
73
- <?js } ?>
74
-
75
- <td class="type">
76
- <?js if (prop.type && prop.type.names) {?>
77
- <?js= self.partial('type.tmpl', prop.type.names) ?>
78
- <?js } ?>
79
- </td>
80
-
81
- <?js if (props.hasAttributes) {?>
82
- <td class="attributes">
83
- <?js if (prop.optional) { ?>
84
- &lt;optional><br>
85
- <?js } ?>
86
-
87
- <?js if (prop.nullable) { ?>
88
- &lt;nullable><br>
89
- <?js } ?>
90
- </td>
91
- <?js } ?>
92
-
93
- <?js if (props.hasDefault) {?>
94
- <td class="default">
95
- <?js if (typeof prop.defaultvalue !== 'undefined') { ?>
96
- <?js= self.htmlsafe(prop.defaultvalue) ?>
97
- <?js } ?>
98
- </td>
99
- <?js } ?>
100
-
101
- <td class="description last"><?js= prop.description ?><?js if (prop.subprops) { ?>
102
- <h6>Properties</h6><?js= self.partial('properties.tmpl', prop) ?>
103
- <?js } ?></td>
104
- </tr>
105
-
106
- <?js }); ?>
107
- </tbody>
108
- </table>
109
- </div>
76
+
77
+ html += '<tr>';
78
+
79
+ if (props.hasName) {
80
+ var nameDisplay = prop.name;
81
+ if (prop.accessType && prop.accessType !== 'property') {
82
+ nameDisplay += ' <em>(' + prop.accessType + ')</em>';
83
+ }
84
+ html += '<td class="name"><code>' + nameDisplay + '</code></td>';
85
+ }
86
+
87
+ html += '<td class="type">';
88
+ if (prop.type && prop.type.names) {
89
+ html += self.partial('type.tmpl', prop.type.names);
90
+ }
91
+ html += '</td>';
92
+
93
+ if (props.hasAttributes) {
94
+ html += '<td class="attributes">';
95
+ if (prop.optional) {
96
+ html += '&lt;optional><br>';
97
+ }
98
+ if (prop.nullable) {
99
+ html += '&lt;nullable><br>';
100
+ }
101
+ html += '</td>';
102
+ }
103
+
104
+ if (props.hasDefault) {
105
+ html += '<td class="default">';
106
+ if (typeof prop.defaultvalue !== 'undefined') {
107
+ html += self.htmlsafe(prop.defaultvalue);
108
+ }
109
+ html += '</td>';
110
+ }
111
+
112
+ html += '<td class="description last">' + (prop.description || '');
113
+ if (prop.subprops) {
114
+ html += '<h6>Properties</h6>' + self.partial('properties.tmpl', prop);
115
+ }
116
+ html += '</td>';
117
+
118
+ html += '</tr>';
119
+ });
120
+
121
+ html += '</tbody></table></div>';
122
+ return html;
123
+ }
124
+ ?>
125
+
126
+ <?js if (staticProps.length > 0) { ?>
127
+ <?js= renderPropertiesTable(staticProps, '静态属性') ?>
128
+ <?js } ?>
129
+
130
+ <?js if (instanceProps.length > 0) { ?>
131
+ <?js= renderPropertiesTable(instanceProps, staticProps.length > 0 ? '实例属性' : null) ?>
132
+ <?js } ?>