bixbite 0.1.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.
Files changed (194) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +49 -0
  3. data/VERSION +1 -0
  4. data/bin/bixbite +73 -0
  5. data/lib/bixbite.rb +13 -0
  6. data/lib/bixbite/command.rb +14 -0
  7. data/lib/bixbite/create.rb +76 -0
  8. data/template/Rakefile +25 -0
  9. data/template/assets/bixbite/Rakefile.rb +297 -0
  10. data/template/assets/naturaldocs/NaturalDocs/Config/Languages.txt +286 -0
  11. data/template/assets/naturaldocs/NaturalDocs/Config/Topics.txt +382 -0
  12. data/template/assets/naturaldocs/NaturalDocs/Help/customizinglanguages.html +52 -0
  13. data/template/assets/naturaldocs/NaturalDocs/Help/customizingtopics.html +74 -0
  14. data/template/assets/naturaldocs/NaturalDocs/Help/documenting.html +58 -0
  15. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/reference.html +146 -0
  16. data/template/assets/naturaldocs/NaturalDocs/Help/documenting/walkthrough.html +180 -0
  17. data/template/assets/naturaldocs/NaturalDocs/Help/example/Default.css +528 -0
  18. data/template/assets/naturaldocs/NaturalDocs/Help/example/NaturalDocs.js +204 -0
  19. data/template/assets/naturaldocs/NaturalDocs/Help/examples.css +90 -0
  20. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/background.png +0 -0
  21. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/leftside.png +0 -0
  22. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/logo.png +0 -0
  23. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbody.png +0 -0
  24. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbodybg.png +0 -0
  25. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overleftmargin.png +0 -0
  26. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenu.png +0 -0
  27. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenubg.png +0 -0
  28. data/template/assets/naturaldocs/NaturalDocs/Help/images/header/rightside.png +0 -0
  29. data/template/assets/naturaldocs/NaturalDocs/Help/images/logo.gif +0 -0
  30. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/about.png +0 -0
  31. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/background.png +0 -0
  32. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomleft.png +0 -0
  33. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomright.png +0 -0
  34. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/community.png +0 -0
  35. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/customizing.png +0 -0
  36. data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/using.png +0 -0
  37. data/template/assets/naturaldocs/NaturalDocs/Help/index.html +9 -0
  38. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/BrowserStyles.js +77 -0
  39. data/template/assets/naturaldocs/NaturalDocs/Help/javascript/PNGHandling.js +72 -0
  40. data/template/assets/naturaldocs/NaturalDocs/Help/keywords.html +38 -0
  41. data/template/assets/naturaldocs/NaturalDocs/Help/languages.html +32 -0
  42. data/template/assets/naturaldocs/NaturalDocs/Help/menu.html +79 -0
  43. data/template/assets/naturaldocs/NaturalDocs/Help/output.html +84 -0
  44. data/template/assets/naturaldocs/NaturalDocs/Help/running.html +40 -0
  45. data/template/assets/naturaldocs/NaturalDocs/Help/styles.css +290 -0
  46. data/template/assets/naturaldocs/NaturalDocs/Help/styles.html +52 -0
  47. data/template/assets/naturaldocs/NaturalDocs/Help/troubleshooting.html +18 -0
  48. data/template/assets/naturaldocs/NaturalDocs/Info/CSSGuide.txt +947 -0
  49. data/template/assets/naturaldocs/NaturalDocs/Info/File Parsing.txt +83 -0
  50. data/template/assets/naturaldocs/NaturalDocs/Info/HTMLTestCases.pm +269 -0
  51. data/template/assets/naturaldocs/NaturalDocs/Info/Languages.txt +107 -0
  52. data/template/assets/naturaldocs/NaturalDocs/Info/NDMarkup.txt +91 -0
  53. data/template/assets/naturaldocs/NaturalDocs/Info/Symbol Management.txt +59 -0
  54. data/template/assets/naturaldocs/NaturalDocs/Info/images/Logo.png +0 -0
  55. data/template/assets/naturaldocs/NaturalDocs/JavaScript/NaturalDocs.js +836 -0
  56. data/template/assets/naturaldocs/NaturalDocs/License-GPL.txt +341 -0
  57. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/BinaryFile.pm +294 -0
  58. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder.pm +280 -0
  59. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/Base.pm +348 -0
  60. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/FramedHTML.pm +345 -0
  61. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTML.pm +398 -0
  62. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTMLBase.pm +3693 -0
  63. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy.pm +860 -0
  64. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/Class.pm +412 -0
  65. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/File.pm +157 -0
  66. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ConfigFile.pm +497 -0
  67. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Constants.pm +165 -0
  68. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/DefineMembers.pm +100 -0
  69. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Error.pm +305 -0
  70. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/File.pm +540 -0
  71. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable.pm +383 -0
  72. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/Reference.pm +44 -0
  73. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/String.pm +110 -0
  74. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages.pm +1475 -0
  75. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/ActionScript.pm +1473 -0
  76. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Ada.pm +38 -0
  77. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced.pm +828 -0
  78. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/Scope.pm +95 -0
  79. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/ScopeChange.pm +70 -0
  80. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Base.pm +832 -0
  81. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/CSharp.pm +1484 -0
  82. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/PLSQL.pm +319 -0
  83. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Pascal.pm +143 -0
  84. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Perl.pm +1370 -0
  85. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype.pm +92 -0
  86. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype/Parameter.pm +87 -0
  87. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Simple.pm +503 -0
  88. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Tcl.pm +219 -0
  89. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu.pm +3406 -0
  90. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu/Entry.pm +201 -0
  91. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/NDMarkup.pm +76 -0
  92. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser.pm +1331 -0
  93. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/JavaDoc.pm +464 -0
  94. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/Native.pm +1060 -0
  95. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/ParsedTopic.pm +253 -0
  96. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project.pm +1402 -0
  97. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/ImageFile.pm +160 -0
  98. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/SourceFile.pm +113 -0
  99. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ReferenceString.pm +334 -0
  100. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings.pm +1418 -0
  101. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings/BuildTarget.pm +66 -0
  102. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB.pm +678 -0
  103. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Extension.pm +84 -0
  104. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/File.pm +129 -0
  105. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Item.pm +201 -0
  106. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/ItemDefinition.pm +45 -0
  107. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/WatchedFileDefinitions.pm +159 -0
  108. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/StatusMessage.pm +102 -0
  109. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolString.pm +212 -0
  110. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable.pm +1984 -0
  111. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/File.pm +186 -0
  112. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/IndexElement.pm +522 -0
  113. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Reference.pm +273 -0
  114. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm +97 -0
  115. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Symbol.pm +428 -0
  116. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm +96 -0
  117. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics.pm +1319 -0
  118. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics/Type.pm +151 -0
  119. data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Version.pm +384 -0
  120. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs +400 -0
  121. data/template/assets/naturaldocs/NaturalDocs/NaturalDocs.bat +17 -0
  122. data/template/assets/naturaldocs/NaturalDocs/Styles/Default.css +767 -0
  123. data/template/assets/naturaldocs/NaturalDocs/Styles/Roman.css +765 -0
  124. data/template/assets/naturaldocs/NaturalDocs/Styles/Small.css +763 -0
  125. data/template/assets/utilities/pngout +0 -0
  126. data/template/deploy/public_html/.htaccess +0 -0
  127. data/template/documentation/js/.htaccess +0 -0
  128. data/template/src/html/.htaccess +76 -0
  129. data/template/src/html/css/cmn/global.css +96 -0
  130. data/template/src/html/css/cmn/ie.css +15 -0
  131. data/template/src/html/css/cmn/ie6.css +15 -0
  132. data/template/src/html/images/cmn/.htaccess +0 -0
  133. data/template/src/html/images/tmp/.htaccess +0 -0
  134. data/template/src/html/includes/debug.inc +5 -0
  135. data/template/src/html/includes/footer.inc +52 -0
  136. data/template/src/html/includes/header.inc +61 -0
  137. data/template/src/html/includes/html.inc +3 -0
  138. data/template/src/html/includes/namespace.inc +19 -0
  139. data/template/src/html/includes/page.inc +151 -0
  140. data/template/src/html/index.html +35 -0
  141. data/template/src/html/js/cmn/bootstrap.js +74 -0
  142. data/template/src/html/js/cmn/global.js +142 -0
  143. data/template/src/html/js/cmn/lib/LAB.js +348 -0
  144. data/template/src/html/min/.htaccess +4 -0
  145. data/template/src/html/min/MinifyCLI.php +19 -0
  146. data/template/src/html/min/README.txt +132 -0
  147. data/template/src/html/min/builder/_index.js +242 -0
  148. data/template/src/html/min/builder/bm.js +36 -0
  149. data/template/src/html/min/builder/index.php +182 -0
  150. data/template/src/html/min/builder/ocCheck.php +36 -0
  151. data/template/src/html/min/builder/rewriteTest.js +1 -0
  152. data/template/src/html/min/config.php +187 -0
  153. data/template/src/html/min/groupsConfig.php +34 -0
  154. data/template/src/html/min/index.php +66 -0
  155. data/template/src/html/min/lib/FirePHP.php +1370 -0
  156. data/template/src/html/min/lib/HTTP/ConditionalGet.php +348 -0
  157. data/template/src/html/min/lib/HTTP/Encoder.php +326 -0
  158. data/template/src/html/min/lib/JSMin.php +314 -0
  159. data/template/src/html/min/lib/JSMinPlus.php +1872 -0
  160. data/template/src/html/min/lib/Minify.php +532 -0
  161. data/template/src/html/min/lib/Minify/Build.php +103 -0
  162. data/template/src/html/min/lib/Minify/CSS.php +83 -0
  163. data/template/src/html/min/lib/Minify/CSS/Compressor.php +250 -0
  164. data/template/src/html/min/lib/Minify/CSS/UriRewriter.php +270 -0
  165. data/template/src/html/min/lib/Minify/Cache/APC.php +130 -0
  166. data/template/src/html/min/lib/Minify/Cache/File.php +125 -0
  167. data/template/src/html/min/lib/Minify/Cache/Memcache.php +137 -0
  168. data/template/src/html/min/lib/Minify/ClosureCompiler.php +85 -0
  169. data/template/src/html/min/lib/Minify/CommentPreserver.php +90 -0
  170. data/template/src/html/min/lib/Minify/Controller/Base.php +202 -0
  171. data/template/src/html/min/lib/Minify/Controller/Files.php +78 -0
  172. data/template/src/html/min/lib/Minify/Controller/Groups.php +94 -0
  173. data/template/src/html/min/lib/Minify/Controller/MinApp.php +132 -0
  174. data/template/src/html/min/lib/Minify/Controller/Page.php +82 -0
  175. data/template/src/html/min/lib/Minify/Controller/Version1.php +118 -0
  176. data/template/src/html/min/lib/Minify/HTML.php +245 -0
  177. data/template/src/html/min/lib/Minify/ImportProcessor.php +157 -0
  178. data/template/src/html/min/lib/Minify/Lines.php +131 -0
  179. data/template/src/html/min/lib/Minify/Logger.php +45 -0
  180. data/template/src/html/min/lib/Minify/Packer.php +37 -0
  181. data/template/src/html/min/lib/Minify/Source.php +187 -0
  182. data/template/src/html/min/lib/Minify/YUICompressor.php +139 -0
  183. data/template/src/html/min/lib/Solar/Dir.php +199 -0
  184. data/template/src/html/min/lib/closure-compiler.jar +0 -0
  185. data/template/src/html/min/lib/yuicompressor-2.4.2.jar +0 -0
  186. data/template/src/html/min/utils.php +90 -0
  187. data/template/src/templates/css/template.css +7 -0
  188. data/template/src/templates/js/template.js +72 -0
  189. data/template/src/templates/template.html +18 -0
  190. data/template/src/yaml/config.yml +46 -0
  191. data/template/src/yaml/deploy.yml +35 -0
  192. data/test/bixbite_test.rb +7 -0
  193. data/test/test_helper.rb +10 -0
  194. metadata +278 -0
@@ -0,0 +1,201 @@
1
+ ###############################################################################
2
+ #
3
+ # Package: NaturalDocs::Menu::Entry
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # A class representing an entry in the menu.
8
+ #
9
+ ###############################################################################
10
+
11
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
12
+ # Natural Docs is licensed under the GPL
13
+
14
+ use strict;
15
+ use integer;
16
+
17
+ package NaturalDocs::Menu::Entry;
18
+
19
+
20
+ ###############################################################################
21
+ # Group: Implementation
22
+
23
+ #
24
+ # Constants: Members
25
+ #
26
+ # The object is implemented as a blessed arrayref with the indexes below.
27
+ #
28
+ # TYPE - The <MenuEntryType>
29
+ # TITLE - The title of the entry.
30
+ # TARGET - The target of the entry. If the type is <MENU_FILE>, it will be the source <FileName>. If the type is
31
+ # <MENU_LINK>, it will be the URL. If the type is <MENU_GROUP>, it will be an arrayref of
32
+ # <NaturalDocs::Menu::Entry> objects representing the group's content. If the type is <MENU_INDEX>, it will be
33
+ # a <TopicType>.
34
+ # FLAGS - Any <Menu Entry Flags> that apply.
35
+ #
36
+ use constant TYPE => 0;
37
+ use constant TITLE => 1;
38
+ use constant TARGET => 2;
39
+ use constant FLAGS => 3;
40
+ # DEPENDENCY: New() depends on the order of these constants.
41
+
42
+
43
+ ###############################################################################
44
+ # Group: Functions
45
+
46
+ #
47
+ # Function: New
48
+ #
49
+ # Creates and returns a new object.
50
+ #
51
+ # Parameters:
52
+ #
53
+ # type - The <MenuEntryType>.
54
+ # title - The title of the entry.
55
+ # target - The target of the entry, if applicable. If the type is <MENU_FILE>, use the source <FileName>. If the type is
56
+ # <MENU_LINK>, use the URL. If the type is <MENU_INDEX>, use the <TopicType>. Otherwise set it to undef.
57
+ # flags - Any <Menu Entry Flags> that apply.
58
+ #
59
+ sub New #(type, title, target, flags)
60
+ {
61
+ # DEPENDENCY: This gode depends on the order of the constants.
62
+
63
+ my $package = shift;
64
+
65
+ my $object = [ @_ ];
66
+ bless $object, $package;
67
+
68
+ if ($object->[TYPE] == ::MENU_GROUP())
69
+ { $object->[TARGET] = [ ]; };
70
+ if (!defined $object->[FLAGS])
71
+ { $object->[FLAGS] = 0; };
72
+
73
+ return $object;
74
+ };
75
+
76
+
77
+ # Function: Type
78
+ # Returns the <MenuEntryType>.
79
+ sub Type
80
+ { return $_[0]->[TYPE]; };
81
+
82
+ # Function: Title
83
+ # Returns the title of the entry.
84
+ sub Title
85
+ { return $_[0]->[TITLE]; };
86
+
87
+ # Function: SetTitle
88
+ # Replaces the entry's title.
89
+ sub SetTitle #(title)
90
+ { $_[0]->[TITLE] = $_[1]; };
91
+
92
+ #
93
+ # Function: Target
94
+ #
95
+ # Returns the target of the entry, if applicable. If the type is <MENU_FILE>, it returns the source <FileName>. If the type is
96
+ # <MENU_LINK>, it returns the URL. If the type is <MENU_INDEX>, it returns the <TopicType>. Otherwise it returns undef.
97
+ #
98
+ sub Target
99
+ {
100
+ my $self = shift;
101
+
102
+ # Group entries are the only time when target won't be undef when it should be.
103
+ if ($self->Type() == ::MENU_GROUP())
104
+ { return undef; }
105
+ else
106
+ { return $self->[TARGET]; };
107
+ };
108
+
109
+ # Function: SetTarget
110
+ # Replaces the entry's target.
111
+ sub SetTarget #(target)
112
+ { $_[0]->[TARGET] = $_[1]; };
113
+
114
+ # Function: Flags
115
+ # Returns the <Menu Entry Flags>.
116
+ sub Flags
117
+ { return $_[0]->[FLAGS]; };
118
+
119
+ # Function: SetFlags
120
+ # Replaces the <Menu Entry Flags>.
121
+ sub SetFlags #(flags)
122
+ { $_[0]->[FLAGS] = $_[1]; };
123
+
124
+
125
+
126
+ ###############################################################################
127
+ # Group: Group Functions
128
+ #
129
+ # All of these functions assume the type is <MENU_GROUP>. Do *not* call any of these without checking <Type()> first.
130
+
131
+
132
+ #
133
+ # Function: GroupContent
134
+ #
135
+ # Returns an arrayref of <NaturalDocs::Menu::Entry> objects representing the contents of the
136
+ # group, or undef otherwise. This arrayref will always exist for <MENU_GROUP>'s and can be changed.
137
+ #
138
+ sub GroupContent
139
+ {
140
+ return $_[0]->[TARGET];
141
+ };
142
+
143
+
144
+ #
145
+ # Function: GroupIsEmpty
146
+ #
147
+ # If the type is <MENU_GROUP>, returns whether the group is empty.
148
+ #
149
+ sub GroupIsEmpty
150
+ {
151
+ my $self = shift;
152
+ return (scalar @{$self->GroupContent()} > 0);
153
+ };
154
+
155
+
156
+ #
157
+ # Function: PushToGroup
158
+ #
159
+ # Pushes the entry to the end of the group content.
160
+ #
161
+ sub PushToGroup #(entry)
162
+ {
163
+ my ($self, $entry) = @_;
164
+ push @{$self->GroupContent()}, $entry;
165
+ };
166
+
167
+
168
+ #
169
+ # Function: DeleteFromGroup
170
+ #
171
+ # Deletes an entry from the group content by index.
172
+ #
173
+ sub DeleteFromGroup #(index)
174
+ {
175
+ my ($self, $index) = @_;
176
+
177
+ my $groupContent = $self->GroupContent();
178
+
179
+ splice( @$groupContent, $index, 1 );
180
+ };
181
+
182
+
183
+ #
184
+ # Function: MarkEndOfOriginal
185
+ #
186
+ # If the group doesn't already have one, adds a <MENU_ENDOFORIGINAL> entry to the end and sets the
187
+ # <MENU_GROUP_HASENDOFORIGINAL> flag.
188
+ #
189
+ sub MarkEndOfOriginal
190
+ {
191
+ my $self = shift;
192
+
193
+ if (($self->Flags() & ::MENU_GROUP_HASENDOFORIGINAL()) == 0)
194
+ {
195
+ $self->PushToGroup( NaturalDocs::Menu::Entry->New(::MENU_ENDOFORIGINAL(), undef, undef, undef) );
196
+ $self->SetFlags( $self->Flags() | ::MENU_GROUP_HASENDOFORIGINAL() );
197
+ };
198
+ };
199
+
200
+
201
+ 1;
@@ -0,0 +1,76 @@
1
+ ###############################################################################
2
+ #
3
+ # Package: NaturalDocs::NDMarkup
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # A package of support functions for dealing with <NDMarkup>.
8
+ #
9
+ # Usage and Dependencies:
10
+ #
11
+ # The package doesn't depend on any Natural Docs packages and is ready to use right away.
12
+ #
13
+ ###############################################################################
14
+
15
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
16
+ # Natural Docs is licensed under the GPL
17
+
18
+
19
+ use strict;
20
+ use integer;
21
+
22
+ package NaturalDocs::NDMarkup;
23
+
24
+ #
25
+ # Function: ConvertAmpChars
26
+ #
27
+ # Substitutes certain characters with their <NDMarkup> amp chars.
28
+ #
29
+ # Parameters:
30
+ #
31
+ # text - The block of text to convert.
32
+ #
33
+ # Returns:
34
+ #
35
+ # The converted text block.
36
+ #
37
+ sub ConvertAmpChars #(text)
38
+ {
39
+ my ($self, $text) = @_;
40
+
41
+ $text =~ s/&/&amp;/g;
42
+ $text =~ s/</&lt;/g;
43
+ $text =~ s/>/&gt;/g;
44
+ $text =~ s/\"/&quot;/g;
45
+
46
+ return $text;
47
+ };
48
+
49
+
50
+ #
51
+ # Function: RestoreAmpChars
52
+ #
53
+ # Replaces <NDMarkup> amp chars with their original symbols.
54
+ #
55
+ # Parameters:
56
+ #
57
+ # text - The text to restore.
58
+ #
59
+ # Returns:
60
+ #
61
+ # The restored text.
62
+ #
63
+ sub RestoreAmpChars #(text)
64
+ {
65
+ my ($self, $text) = @_;
66
+
67
+ $text =~ s/&quot;/\"/g;
68
+ $text =~ s/&gt;/>/g;
69
+ $text =~ s/&lt;/</g;
70
+ $text =~ s/&amp;/&/g;
71
+
72
+ return $text;
73
+ };
74
+
75
+
76
+ 1;
@@ -0,0 +1,1331 @@
1
+ ###############################################################################
2
+ #
3
+ # Package: NaturalDocs::Parser
4
+ #
5
+ ###############################################################################
6
+ #
7
+ # A package that coordinates source file parsing between the <NaturalDocs::Languages::Base>-derived objects and its own
8
+ # sub-packages such as <NaturalDocs::Parser::Native>. Also handles sending symbols to <NaturalDocs::SymbolTable> and
9
+ # other generic topic processing.
10
+ #
11
+ # Usage and Dependencies:
12
+ #
13
+ # - Prior to use, <NaturalDocs::Settings>, <NaturalDocs::Languages>, <NaturalDocs::Project>, <NaturalDocs::SymbolTable>,
14
+ # and <NaturalDocs::ClassHierarchy> must be initialized. <NaturalDocs::SymbolTable> and <NaturalDocs::ClassHierarchy>
15
+ # do not have to be fully resolved.
16
+ #
17
+ # - Aside from that, the package is ready to use right away. It does not have its own initialization function.
18
+ #
19
+ ###############################################################################
20
+
21
+ # This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
22
+ # Natural Docs is licensed under the GPL
23
+
24
+ use NaturalDocs::Parser::ParsedTopic;
25
+ use NaturalDocs::Parser::Native;
26
+ use NaturalDocs::Parser::JavaDoc;
27
+
28
+ use strict;
29
+ use integer;
30
+
31
+ package NaturalDocs::Parser;
32
+
33
+
34
+
35
+ ###############################################################################
36
+ # Group: Variables
37
+
38
+
39
+ #
40
+ # var: sourceFile
41
+ #
42
+ # The source <FileName> currently being parsed.
43
+ #
44
+ my $sourceFile;
45
+
46
+ #
47
+ # var: language
48
+ #
49
+ # The language object for the file, derived from <NaturalDocs::Languages::Base>.
50
+ #
51
+ my $language;
52
+
53
+ #
54
+ # Array: parsedFile
55
+ #
56
+ # An array of <NaturalDocs::Parser::ParsedTopic> objects.
57
+ #
58
+ my @parsedFile;
59
+
60
+
61
+ #
62
+ # bool: parsingForInformation
63
+ # Whether <ParseForInformation()> was called. If false, then <ParseForBuild()> was called.
64
+ #
65
+ my $parsingForInformation;
66
+
67
+
68
+
69
+ ###############################################################################
70
+ # Group: Functions
71
+
72
+ #
73
+ # Function: ParseForInformation
74
+ #
75
+ # Parses the input file for information. Will update the information about the file in <NaturalDocs::SymbolTable> and
76
+ # <NaturalDocs::Project>.
77
+ #
78
+ # Parameters:
79
+ #
80
+ # file - The <FileName> to parse.
81
+ #
82
+ sub ParseForInformation #(file)
83
+ {
84
+ my ($self, $file) = @_;
85
+ $sourceFile = $file;
86
+
87
+ $parsingForInformation = 1;
88
+
89
+ # Watch this parse so we detect any changes.
90
+ NaturalDocs::SymbolTable->WatchFileForChanges($sourceFile);
91
+ NaturalDocs::ClassHierarchy->WatchFileForChanges($sourceFile);
92
+ NaturalDocs::SourceDB->WatchFileForChanges($sourceFile);
93
+
94
+ my $defaultMenuTitle = $self->Parse();
95
+
96
+ foreach my $topic (@parsedFile)
97
+ {
98
+ # Add a symbol for the topic.
99
+
100
+ my $type = $topic->Type();
101
+ if ($type eq ::TOPIC_ENUMERATION())
102
+ { $type = ::TOPIC_TYPE(); };
103
+
104
+ NaturalDocs::SymbolTable->AddSymbol($topic->Symbol(), $sourceFile, $type,
105
+ $topic->Prototype(), $topic->Summary());
106
+
107
+
108
+ # You can't put the function call directly in a while with a regex. It has to sit in a variable to work.
109
+ my $body = $topic->Body();
110
+
111
+
112
+ # If it's a list or enum topic, add a symbol for each description list entry.
113
+
114
+ if ($topic->IsList() || $topic->Type() eq ::TOPIC_ENUMERATION())
115
+ {
116
+ # We'll hijack the enum constants to apply to non-enum behavior too.
117
+ my $behavior;
118
+
119
+ if ($topic->Type() eq ::TOPIC_ENUMERATION())
120
+ {
121
+ $type = ::TOPIC_CONSTANT();
122
+ $behavior = $language->EnumValues();
123
+ }
124
+ elsif (NaturalDocs::Topics->TypeInfo($topic->Type())->Scope() == ::SCOPE_ALWAYS_GLOBAL())
125
+ {
126
+ $behavior = ::ENUM_GLOBAL();
127
+ }
128
+ else
129
+ {
130
+ $behavior = ::ENUM_UNDER_PARENT();
131
+ };
132
+
133
+ while ($body =~ /<ds>([^<]+)<\/ds><dd>(.*?)<\/dd>/g)
134
+ {
135
+ my ($listTextSymbol, $listSummary) = ($1, $2);
136
+
137
+ $listTextSymbol = NaturalDocs::NDMarkup->RestoreAmpChars($listTextSymbol);
138
+ my $listSymbol = NaturalDocs::SymbolString->FromText($listTextSymbol);
139
+
140
+ if ($behavior == ::ENUM_UNDER_PARENT())
141
+ { $listSymbol = NaturalDocs::SymbolString->Join($topic->Package(), $listSymbol); }
142
+ elsif ($behavior == ::ENUM_UNDER_TYPE())
143
+ { $listSymbol = NaturalDocs::SymbolString->Join($topic->Symbol(), $listSymbol); };
144
+
145
+ NaturalDocs::SymbolTable->AddSymbol($listSymbol, $sourceFile, $type, undef,
146
+ $self->GetSummaryFromDescriptionList($listSummary));
147
+ };
148
+ };
149
+
150
+
151
+ # Add references in the topic.
152
+
153
+ while ($body =~ /<link target=\"([^\"]*)\" name=\"[^\"]*\" original=\"[^\"]*\">/g)
154
+ {
155
+ my $linkText = NaturalDocs::NDMarkup->RestoreAmpChars($1);
156
+ my $linkSymbol = NaturalDocs::SymbolString->FromText($linkText);
157
+
158
+ NaturalDocs::SymbolTable->AddReference(::REFERENCE_TEXT(), $linkSymbol,
159
+ $topic->Package(), $topic->Using(), $sourceFile);
160
+ };
161
+
162
+
163
+ # Add images in the topic.
164
+
165
+ while ($body =~ /<img mode=\"[^\"]*\" target=\"([^\"]+)\" original=\"[^\"]*\">/g)
166
+ {
167
+ my $target = NaturalDocs::NDMarkup->RestoreAmpChars($1);
168
+ NaturalDocs::ImageReferenceTable->AddReference($sourceFile, $target);
169
+ };
170
+ };
171
+
172
+ # Handle any changes to the file.
173
+ NaturalDocs::ClassHierarchy->AnalyzeChanges();
174
+ NaturalDocs::SymbolTable->AnalyzeChanges();
175
+ NaturalDocs::SourceDB->AnalyzeWatchedFileChanges();
176
+
177
+ # Update project on the file's characteristics.
178
+ my $hasContent = (scalar @parsedFile > 0);
179
+
180
+ NaturalDocs::Project->SetHasContent($sourceFile, $hasContent);
181
+ if ($hasContent)
182
+ { NaturalDocs::Project->SetDefaultMenuTitle($sourceFile, $defaultMenuTitle); };
183
+
184
+ # We don't need to keep this around.
185
+ @parsedFile = ( );
186
+ };
187
+
188
+
189
+ #
190
+ # Function: ParseForBuild
191
+ #
192
+ # Parses the input file for building, returning it as a <NaturalDocs::Parser::ParsedTopic> arrayref.
193
+ #
194
+ # Note that all new and changed files should be parsed for symbols via <ParseForInformation()> before calling this function on
195
+ # *any* file. The reason is that <NaturalDocs::SymbolTable> needs to know about all the symbol definitions and references to
196
+ # resolve them properly.
197
+ #
198
+ # Parameters:
199
+ #
200
+ # file - The <FileName> to parse for building.
201
+ #
202
+ # Returns:
203
+ #
204
+ # An arrayref of the source file as <NaturalDocs::Parser::ParsedTopic> objects.
205
+ #
206
+ sub ParseForBuild #(file)
207
+ {
208
+ my ($self, $file) = @_;
209
+ $sourceFile = $file;
210
+
211
+ $parsingForInformation = undef;
212
+
213
+ $self->Parse();
214
+
215
+ return \@parsedFile;
216
+ };
217
+
218
+
219
+
220
+
221
+ ###############################################################################
222
+ # Group: Interface Functions
223
+
224
+
225
+ #
226
+ # Function: OnComment
227
+ #
228
+ # The function called by <NaturalDocs::Languages::Base>-derived objects when their parsers encounter a comment
229
+ # suitable for documentation.
230
+ #
231
+ # Parameters:
232
+ #
233
+ # commentLines - An arrayref of the comment's lines. The language's comment symbols should be converted to spaces,
234
+ # and there should be no line break characters at the end of each line. *The original memory will be
235
+ # changed.*
236
+ # lineNumber - The line number of the first of the comment lines.
237
+ # isJavaDoc - Whether the comment is in JavaDoc format.
238
+ #
239
+ # Returns:
240
+ #
241
+ # The number of topics created by this comment, or zero if none.
242
+ #
243
+ sub OnComment #(string[] commentLines, int lineNumber, bool isJavaDoc)
244
+ {
245
+ my ($self, $commentLines, $lineNumber, $isJavaDoc) = @_;
246
+
247
+ $self->CleanComment($commentLines);
248
+
249
+ # We check if it's definitely Natural Docs content first. This overrides all else, since it's possible that a comment could start
250
+ # with a topic line yet have something that looks like a JavaDoc tag. Natural Docs wins in this case.
251
+ if (NaturalDocs::Parser::Native->IsMine($commentLines, $isJavaDoc))
252
+ { return NaturalDocs::Parser::Native->ParseComment($commentLines, $isJavaDoc, $lineNumber, \@parsedFile); }
253
+
254
+ elsif (NaturalDocs::Parser::JavaDoc->IsMine($commentLines, $isJavaDoc))
255
+ { return NaturalDocs::Parser::JavaDoc->ParseComment($commentLines, $isJavaDoc, $lineNumber, \@parsedFile); }
256
+
257
+ # If the content is ambiguous and it's a JavaDoc-styled comment, treat it as Natural Docs content.
258
+ elsif ($isJavaDoc)
259
+ { return NaturalDocs::Parser::Native->ParseComment($commentLines, $isJavaDoc, $lineNumber, \@parsedFile); }
260
+ };
261
+
262
+
263
+ #
264
+ # Function: OnClass
265
+ #
266
+ # A function called by <NaturalDocs::Languages::Base>-derived objects when their parsers encounter a class declaration.
267
+ #
268
+ # Parameters:
269
+ #
270
+ # class - The <SymbolString> of the class encountered.
271
+ #
272
+ sub OnClass #(class)
273
+ {
274
+ my ($self, $class) = @_;
275
+
276
+ if ($parsingForInformation)
277
+ { NaturalDocs::ClassHierarchy->AddClass($sourceFile, $class); };
278
+ };
279
+
280
+
281
+ #
282
+ # Function: OnClassParent
283
+ #
284
+ # A function called by <NaturalDocs::Languages::Base>-derived objects when their parsers encounter a declaration of
285
+ # inheritance.
286
+ #
287
+ # Parameters:
288
+ #
289
+ # class - The <SymbolString> of the class we're in.
290
+ # parent - The <SymbolString> of the class it inherits.
291
+ # scope - The package <SymbolString> that the reference appeared in.
292
+ # using - An arrayref of package <SymbolStrings> that the reference has access to via "using" statements.
293
+ # resolvingFlags - Any <Resolving Flags> to be used when resolving the reference. <RESOLVE_NOPLURAL> is added
294
+ # automatically since that would never apply to source code.
295
+ #
296
+ sub OnClassParent #(class, parent, scope, using, resolvingFlags)
297
+ {
298
+ my ($self, $class, $parent, $scope, $using, $resolvingFlags) = @_;
299
+
300
+ if ($parsingForInformation)
301
+ {
302
+ NaturalDocs::ClassHierarchy->AddParentReference($sourceFile, $class, $parent, $scope, $using,
303
+ $resolvingFlags | ::RESOLVE_NOPLURAL());
304
+ };
305
+ };
306
+
307
+
308
+
309
+ ###############################################################################
310
+ # Group: Support Functions
311
+
312
+
313
+ # Function: Parse
314
+ #
315
+ # Opens the source file and parses process. Most of the actual parsing is done in <NaturalDocs::Languages::Base->ParseFile()>
316
+ # and <OnComment()>, though.
317
+ #
318
+ # *Do not call externally.* Rather, call <ParseForInformation()> or <ParseForBuild()>.
319
+ #
320
+ # Returns:
321
+ #
322
+ # The default menu title of the file. Will be the <FileName> if nothing better is found.
323
+ #
324
+ sub Parse
325
+ {
326
+ my ($self) = @_;
327
+
328
+ NaturalDocs::Error->OnStartParsing($sourceFile);
329
+
330
+ $language = NaturalDocs::Languages->LanguageOf($sourceFile);
331
+ NaturalDocs::Parser::Native->Start();
332
+ @parsedFile = ( );
333
+
334
+ my ($autoTopics, $scopeRecord) = $language->ParseFile($sourceFile, \@parsedFile);
335
+
336
+
337
+ $self->AddToClassHierarchy();
338
+
339
+ $self->BreakLists();
340
+
341
+ if (defined $autoTopics)
342
+ {
343
+ if (defined $scopeRecord)
344
+ { $self->RepairPackages($autoTopics, $scopeRecord); };
345
+
346
+ $self->MergeAutoTopics($language, $autoTopics);
347
+ };
348
+
349
+ $self->RemoveRemainingHeaderlessTopics();
350
+
351
+
352
+ # We don't need to do this if there aren't any auto-topics because the only package changes would be implied by the comments.
353
+ if (defined $autoTopics)
354
+ { $self->AddPackageDelineators(); };
355
+
356
+ if (!NaturalDocs::Settings->NoAutoGroup())
357
+ { $self->MakeAutoGroups($autoTopics); };
358
+
359
+
360
+ # Set the menu title.
361
+
362
+ my $defaultMenuTitle = $sourceFile;
363
+
364
+ if (scalar @parsedFile)
365
+ {
366
+ my $addFileTitle;
367
+
368
+ if (NaturalDocs::Settings->OnlyFileTitles())
369
+ {
370
+ # We still want to use the title from the topics if the first one is a file.
371
+ if ($parsedFile[0]->Type() eq ::TOPIC_FILE())
372
+ { $addFileTitle = 0; }
373
+ else
374
+ { $addFileTitle = 1; };
375
+ }
376
+ elsif (scalar @parsedFile == 1 || NaturalDocs::Topics->TypeInfo( $parsedFile[0]->Type() )->PageTitleIfFirst())
377
+ { $addFileTitle = 0; }
378
+ else
379
+ { $addFileTitle = 1; };
380
+
381
+ if (!$addFileTitle)
382
+ {
383
+ $defaultMenuTitle = $parsedFile[0]->Title();
384
+ }
385
+ else
386
+ {
387
+ # If the title ended up being the file name, add a leading section for it.
388
+
389
+ unshift @parsedFile,
390
+ NaturalDocs::Parser::ParsedTopic->New(::TOPIC_FILE(), (NaturalDocs::File->SplitPath($sourceFile))[2],
391
+ undef, undef, undef, undef, undef, 1, undef);
392
+ };
393
+ };
394
+
395
+ NaturalDocs::Error->OnEndParsing($sourceFile);
396
+
397
+ return $defaultMenuTitle;
398
+ };
399
+
400
+
401
+ #
402
+ # Function: CleanComment
403
+ #
404
+ # Removes any extraneous formatting and whitespace from the comment. Eliminates comment boxes, horizontal lines, trailing
405
+ # whitespace from lines, and expands all tab characters. It keeps leading whitespace, though, since it may be needed for
406
+ # example code, and blank lines, since the original line numbers are needed.
407
+ #
408
+ # Parameters:
409
+ #
410
+ # commentLines - An arrayref of the comment lines to clean. *The original memory will be changed.* Lines should have the
411
+ # language's comment symbols replaced by spaces and not have a trailing line break.
412
+ #
413
+ sub CleanComment #(commentLines)
414
+ {
415
+ my ($self, $commentLines) = @_;
416
+
417
+ use constant DONT_KNOW => 0;
418
+ use constant IS_UNIFORM => 1;
419
+ use constant IS_UNIFORM_IF_AT_END => 2;
420
+ use constant IS_NOT_UNIFORM => 3;
421
+
422
+ my $leftSide = DONT_KNOW;
423
+ my $rightSide = DONT_KNOW;
424
+ my $leftSideChar;
425
+ my $rightSideChar;
426
+
427
+ my $index = 0;
428
+ my $tabLength = NaturalDocs::Settings->TabLength();
429
+
430
+ while ($index < scalar @$commentLines)
431
+ {
432
+ # Strip trailing whitespace from the original.
433
+
434
+ $commentLines->[$index] =~ s/[ \t]+$//;
435
+
436
+
437
+ # Expand tabs in the original. This method is almost six times faster than Text::Tabs' method.
438
+
439
+ my $tabIndex = index($commentLines->[$index], "\t");
440
+
441
+ while ($tabIndex != -1)
442
+ {
443
+ substr( $commentLines->[$index], $tabIndex, 1, ' ' x ($tabLength - ($tabIndex % $tabLength)) );
444
+ $tabIndex = index($commentLines->[$index], "\t", $tabIndex);
445
+ };
446
+
447
+
448
+ # Make a working copy and strip leading whitespace as well. This has to be done after tabs are expanded because
449
+ # stripping indentation could change how far tabs are expanded.
450
+
451
+ my $line = $commentLines->[$index];
452
+ $line =~ s/^ +//;
453
+
454
+ # If the line is blank...
455
+ if (!length $line)
456
+ {
457
+ # If we have a potential vertical line, this only acceptable if it's at the end of the comment.
458
+ if ($leftSide == IS_UNIFORM)
459
+ { $leftSide = IS_UNIFORM_IF_AT_END; };
460
+ if ($rightSide == IS_UNIFORM)
461
+ { $rightSide = IS_UNIFORM_IF_AT_END; };
462
+ }
463
+
464
+ # If there's at least four symbols in a row, it's a horizontal line. The second regex supports differing edge characters. It
465
+ # doesn't matter if any of this matches the left and right side symbols. The length < 256 is a sanity check, because that
466
+ # regexp has caused the perl regexp engine to choke on an insane line someone sent me from an automatically generated
467
+ # file. It had over 10k characters on the first line, and most of them were 0x00.
468
+ elsif ($line =~ /^([^a-zA-Z0-9 ])\1{3,}$/ ||
469
+ (length $line < 256 && $line =~ /^([^a-zA-Z0-9 ])\1*([^a-zA-Z0-9 ])\2{3,}([^a-zA-Z0-9 ])\3*$/) )
470
+ {
471
+ # Ignore it. This has no effect on the vertical line detection. We want to keep it in the output though in case it was
472
+ # in a code section.
473
+ }
474
+
475
+ # If the line is not blank or a horizontal line...
476
+ else
477
+ {
478
+ # More content means any previous blank lines are no longer tolerated in vertical line detection. They are only
479
+ # acceptable at the end of the comment.
480
+
481
+ if ($leftSide == IS_UNIFORM_IF_AT_END)
482
+ { $leftSide = IS_NOT_UNIFORM; };
483
+ if ($rightSide == IS_UNIFORM_IF_AT_END)
484
+ { $rightSide = IS_NOT_UNIFORM; };
485
+
486
+
487
+ # Detect vertical lines. Lines are only lines if they are followed by whitespace or a connected horizontal line.
488
+ # Otherwise we may accidentally detect lines from short comments that just happen to have every first or last
489
+ # character the same.
490
+
491
+ if ($leftSide != IS_NOT_UNIFORM)
492
+ {
493
+ if ($line =~ /^([^a-zA-Z0-9])\1*(?: |$)/)
494
+ {
495
+ if ($leftSide == DONT_KNOW)
496
+ {
497
+ $leftSide = IS_UNIFORM;
498
+ $leftSideChar = $1;
499
+ }
500
+ else # ($leftSide == IS_UNIFORM) Other choices already ruled out.
501
+ {
502
+ if ($leftSideChar ne $1)
503
+ { $leftSide = IS_NOT_UNIFORM; };
504
+ };
505
+ }
506
+ # We'll tolerate the lack of symbols on the left on the first line, because it may be a
507
+ # /* Function: Whatever
508
+ # * Description.
509
+ # */
510
+ # comment which would have the leading /* blanked out.
511
+ elsif ($index != 0)
512
+ {
513
+ $leftSide = IS_NOT_UNIFORM;
514
+ };
515
+ };
516
+
517
+ if ($rightSide != IS_NOT_UNIFORM)
518
+ {
519
+ if ($line =~ / ([^a-zA-Z0-9])\1*$/)
520
+ {
521
+ if ($rightSide == DONT_KNOW)
522
+ {
523
+ $rightSide = IS_UNIFORM;
524
+ $rightSideChar = $1;
525
+ }
526
+ else # ($rightSide == IS_UNIFORM) Other choices already ruled out.
527
+ {
528
+ if ($rightSideChar ne $1)
529
+ { $rightSide = IS_NOT_UNIFORM; };
530
+ };
531
+ }
532
+ else
533
+ {
534
+ $rightSide = IS_NOT_UNIFORM;
535
+ };
536
+ };
537
+
538
+ # We'll remove vertical lines later if they're uniform throughout the entire comment.
539
+ };
540
+
541
+ $index++;
542
+ };
543
+
544
+
545
+ if ($leftSide == IS_UNIFORM_IF_AT_END)
546
+ { $leftSide = IS_UNIFORM; };
547
+ if ($rightSide == IS_UNIFORM_IF_AT_END)
548
+ { $rightSide = IS_UNIFORM; };
549
+
550
+
551
+ $index = 0;
552
+ my $inCodeSection = 0;
553
+
554
+ while ($index < scalar @$commentLines)
555
+ {
556
+ # Clear horizontal lines only if we're not in a code section.
557
+ if ($commentLines->[$index] =~ /^ *([^a-zA-Z0-9 ])\1{3,}$/ ||
558
+ ( length $commentLines->[$index] < 256 &&
559
+ $commentLines->[$index] =~ /^ *([^a-zA-Z0-9 ])\1*([^a-zA-Z0-9 ])\2{3,}([^a-zA-Z0-9 ])\3*$/ ) )
560
+ {
561
+ if (!$inCodeSection)
562
+ { $commentLines->[$index] = ''; }
563
+ }
564
+
565
+ else
566
+ {
567
+ # Clear vertical lines.
568
+
569
+ if ($leftSide == IS_UNIFORM)
570
+ {
571
+ # This works because every line should either start this way, be blank, or be the first line that doesn't start with a
572
+ # symbol.
573
+ $commentLines->[$index] =~ s/^ *([^a-zA-Z0-9 ])\1*//;
574
+ };
575
+
576
+ if ($rightSide == IS_UNIFORM)
577
+ {
578
+ $commentLines->[$index] =~ s/ *([^a-zA-Z0-9 ])\1*$//;
579
+ };
580
+
581
+
582
+ # Clear horizontal lines again if there were vertical lines. This catches lines that were separated from the verticals by
583
+ # whitespace.
584
+
585
+ if (($leftSide == IS_UNIFORM || $rightSide == IS_UNIFORM) && !$inCodeSection)
586
+ {
587
+ $commentLines->[$index] =~ s/^ *([^a-zA-Z0-9 ])\1{3,}$//;
588
+ $commentLines->[$index] =~ s/^ *([^a-zA-Z0-9 ])\1*([^a-zA-Z0-9 ])\2{3,}([^a-zA-Z0-9 ])\3*$//;
589
+ };
590
+
591
+
592
+ # Check for the start and end of code sections. Note that this doesn't affect vertical line removal.
593
+
594
+ if (!$inCodeSection &&
595
+ $commentLines->[$index] =~ /^ *\( *(?:(?:start|begin)? +)?(?:table|code|example|diagram) *\)$/i )
596
+ {
597
+ $inCodeSection = 1;
598
+ }
599
+ elsif ($inCodeSection &&
600
+ $commentLines->[$index] =~ /^ *\( *(?:end|finish|done)(?: +(?:table|code|example|diagram))? *\)$/i)
601
+ {
602
+ $inCodeSection = 0;
603
+ }
604
+ }
605
+
606
+
607
+ $index++;
608
+ };
609
+
610
+ };
611
+
612
+
613
+
614
+ ###############################################################################
615
+ # Group: Processing Functions
616
+
617
+
618
+ #
619
+ # Function: RepairPackages
620
+ #
621
+ # Recalculates the packages for all comment topics using the auto-topics and the scope record. Call this *before* calling
622
+ # <MergeAutoTopics()>.
623
+ #
624
+ # Parameters:
625
+ #
626
+ # autoTopics - A reference to the list of automatically generated <NaturalDocs::Parser::ParsedTopics>.
627
+ # scopeRecord - A reference to an array of <NaturalDocs::Languages::Advanced::ScopeChanges>.
628
+ #
629
+ sub RepairPackages #(autoTopics, scopeRecord)
630
+ {
631
+ my ($self, $autoTopics, $scopeRecord) = @_;
632
+
633
+ my $topicIndex = 0;
634
+ my $autoTopicIndex = 0;
635
+ my $scopeIndex = 0;
636
+
637
+ my $topic = $parsedFile[0];
638
+ my $autoTopic = $autoTopics->[0];
639
+ my $scopeChange = $scopeRecord->[0];
640
+
641
+ my $currentPackage;
642
+ my $inFakePackage;
643
+
644
+ while (defined $topic)
645
+ {
646
+ # First update the scope via the record if its defined and has the lowest line number.
647
+ if (defined $scopeChange &&
648
+ $scopeChange->LineNumber() <= $topic->LineNumber() &&
649
+ (!defined $autoTopic || $scopeChange->LineNumber() <= $autoTopic->LineNumber()) )
650
+ {
651
+ $currentPackage = $scopeChange->Scope();
652
+ $scopeIndex++;
653
+ $scopeChange = $scopeRecord->[$scopeIndex]; # Will be undef when past end.
654
+ $inFakePackage = undef;
655
+ }
656
+
657
+ # Next try to end a fake scope with an auto topic if its defined and has the lowest line number.
658
+ elsif (defined $autoTopic &&
659
+ $autoTopic->LineNumber() <= $topic->LineNumber())
660
+ {
661
+ if ($inFakePackage)
662
+ {
663
+ $currentPackage = $autoTopic->Package();
664
+ $inFakePackage = undef;
665
+ };
666
+
667
+ $autoTopicIndex++;
668
+ $autoTopic = $autoTopics->[$autoTopicIndex]; # Will be undef when past end.
669
+ }
670
+
671
+
672
+ # Finally try to handle the topic, since it has the lowest line number. Check for Type() because headerless topics won't have
673
+ # one.
674
+ else
675
+ {
676
+ my $scope;
677
+ if ($topic->Type())
678
+ { $scope = NaturalDocs::Topics->TypeInfo($topic->Type())->Scope(); }
679
+ else
680
+ { $scope = ::SCOPE_NORMAL(); };
681
+
682
+ if ($scope == ::SCOPE_START() || $scope == ::SCOPE_END())
683
+ {
684
+ # They should already have the correct class and scope.
685
+ $currentPackage = $topic->Package();
686
+ $inFakePackage = 1;
687
+ }
688
+ else
689
+ {
690
+ # Fix the package of everything else.
691
+
692
+ # Note that the first function or variable topic to appear in a fake package will assume that package even if it turns out
693
+ # to be incorrect in the actual code, since the topic will come before the auto-topic. This will be corrected in
694
+ # MergeAutoTopics().
695
+
696
+ $topic->SetPackage($currentPackage);
697
+ };
698
+
699
+ $topicIndex++;
700
+ $topic = $parsedFile[$topicIndex]; # Will be undef when past end.
701
+ };
702
+ };
703
+
704
+ };
705
+
706
+
707
+ #
708
+ # Function: MergeAutoTopics
709
+ #
710
+ # Merges the automatically generated topics into the file. If an auto-topic matches an existing topic, it will have it's prototype
711
+ # and package transferred. If it doesn't, the auto-topic will be inserted into the list unless
712
+ # <NaturalDocs::Settings->DocumentedOnly()> is set. If an existing topic doesn't have a title, it's assumed to be a headerless
713
+ # comment and will be merged with the next auto-topic or discarded.
714
+ #
715
+ # Parameters:
716
+ #
717
+ # language - The <NaturalDocs::Languages::Base>-derived class for the file.
718
+ # autoTopics - A reference to the list of automatically generated topics.
719
+ #
720
+ sub MergeAutoTopics #(language, autoTopics)
721
+ {
722
+ my ($self, $language, $autoTopics) = @_;
723
+
724
+ my $topicIndex = 0;
725
+ my $autoTopicIndex = 0;
726
+
727
+ # Keys are topic types, values are existence hashrefs of titles.
728
+ my %topicsInLists;
729
+
730
+ while ($topicIndex < scalar @parsedFile && $autoTopicIndex < scalar @$autoTopics)
731
+ {
732
+ my $topic = $parsedFile[$topicIndex];
733
+ my $autoTopic = $autoTopics->[$autoTopicIndex];
734
+
735
+ my $cleanTitle = $topic->Title();
736
+ $cleanTitle =~ s/[\t ]*\([^\(]*$//;
737
+
738
+ # Add the auto-topic if it's higher in the file than the current topic.
739
+ if ($autoTopic->LineNumber() < $topic->LineNumber())
740
+ {
741
+ if (exists $topicsInLists{$autoTopic->Type()} &&
742
+ exists $topicsInLists{$autoTopic->Type()}->{$autoTopic->Title()})
743
+ {
744
+ # Remove it from the list so a second one with the same name will be added.
745
+ delete $topicsInLists{$autoTopic->Type()}->{$autoTopic->Title()};
746
+ }
747
+ elsif (!NaturalDocs::Settings->DocumentedOnly())
748
+ {
749
+ splice(@parsedFile, $topicIndex, 0, $autoTopic);
750
+ $topicIndex++;
751
+ };
752
+
753
+ $autoTopicIndex++;
754
+ }
755
+
756
+ # Remove a headerless topic if there's another topic between it and the next auto-topic.
757
+ elsif (!$topic->Title() && $topicIndex + 1 < scalar @parsedFile &&
758
+ $parsedFile[$topicIndex+1]->LineNumber() < $autoTopic->LineNumber())
759
+ {
760
+ splice(@parsedFile, $topicIndex, 1);
761
+ }
762
+
763
+ # Transfer information if we have a match or a headerless topic.
764
+ elsif ( !$topic->Title() || ($topic->Type() == $autoTopic->Type() && index($autoTopic->Title(), $cleanTitle) != -1) )
765
+ {
766
+ $topic->SetType($autoTopic->Type());
767
+ $topic->SetPrototype($autoTopic->Prototype());
768
+ $topic->SetUsing($autoTopic->Using());
769
+
770
+ if (!$topic->Title())
771
+ { $topic->SetTitle($autoTopic->Title()); };
772
+
773
+ if (NaturalDocs::Topics->TypeInfo($topic->Type())->Scope() != ::SCOPE_START())
774
+ { $topic->SetPackage($autoTopic->Package()); }
775
+ elsif ($autoTopic->Package() ne $topic->Package())
776
+ {
777
+ my @autoPackageIdentifiers = NaturalDocs::SymbolString->IdentifiersOf($autoTopic->Package());
778
+ my @packageIdentifiers = NaturalDocs::SymbolString->IdentifiersOf($topic->Package());
779
+
780
+ while (scalar @autoPackageIdentifiers && $autoPackageIdentifiers[-1] eq $packageIdentifiers[-1])
781
+ {
782
+ pop @autoPackageIdentifiers;
783
+ pop @packageIdentifiers;
784
+ };
785
+
786
+ if (scalar @autoPackageIdentifiers)
787
+ { $topic->SetPackage( NaturalDocs::SymbolString->Join(@autoPackageIdentifiers) ); };
788
+ };
789
+
790
+ $topicIndex++;
791
+ $autoTopicIndex++;
792
+ }
793
+
794
+ # Extract topics in lists.
795
+ elsif ($topic->IsList())
796
+ {
797
+ if (!exists $topicsInLists{$topic->Type()})
798
+ { $topicsInLists{$topic->Type()} = { }; };
799
+
800
+ my $body = $topic->Body();
801
+
802
+ while ($body =~ /<ds>([^<]+)<\/ds>/g)
803
+ { $topicsInLists{$topic->Type()}->{NaturalDocs::NDMarkup->RestoreAmpChars($1)} = 1; };
804
+
805
+ $topicIndex++;
806
+ }
807
+
808
+ # Otherwise there's no match. Skip the topic. The auto-topic will be added later.
809
+ else
810
+ {
811
+ $topicIndex++;
812
+ }
813
+ };
814
+
815
+ # Add any auto-topics remaining.
816
+ if (!NaturalDocs::Settings->DocumentedOnly())
817
+ {
818
+ while ($autoTopicIndex < scalar @$autoTopics)
819
+ {
820
+ my $autoTopic = $autoTopics->[$autoTopicIndex];
821
+
822
+ if (exists $topicsInLists{$autoTopic->Type()} &&
823
+ exists $topicsInLists{$autoTopic->Type()}->{$autoTopic->Title()})
824
+ {
825
+ # Remove it from the list so a second one with the same name will be added.
826
+ delete $topicsInLists{$autoTopic->Type()}->{$autoTopic->Title()};
827
+ }
828
+ else
829
+ {
830
+ push(@parsedFile, $autoTopic);
831
+ };
832
+
833
+ $autoTopicIndex++;
834
+ };
835
+ };
836
+ };
837
+
838
+
839
+ #
840
+ # Function: RemoveRemainingHeaderlessTopics
841
+ #
842
+ # After <MergeAutoTopics()> is done, this function removes any remaining headerless topics from the file. If they don't merge
843
+ # into anything, they're not valid topics.
844
+ #
845
+ sub RemoveRemainingHeaderlessTopics
846
+ {
847
+ my ($self) = @_;
848
+
849
+ my $index = 0;
850
+ while ($index < scalar @parsedFile)
851
+ {
852
+ if ($parsedFile[$index]->Title())
853
+ { $index++; }
854
+ else
855
+ { splice(@parsedFile, $index, 1); };
856
+ };
857
+ };
858
+
859
+
860
+ #
861
+ # Function: MakeAutoGroups
862
+ #
863
+ # Creates group topics for files that do not have them.
864
+ #
865
+ sub MakeAutoGroups
866
+ {
867
+ my ($self) = @_;
868
+
869
+ # No groups only one topic.
870
+ if (scalar @parsedFile < 2)
871
+ { return; };
872
+
873
+ my $index = 0;
874
+ my $startStretch = 0;
875
+
876
+ # Skip the first entry if its the page title.
877
+ if (NaturalDocs::Topics->TypeInfo( $parsedFile[0]->Type() )->PageTitleIfFirst())
878
+ {
879
+ $index = 1;
880
+ $startStretch = 1;
881
+ };
882
+
883
+ # Make auto-groups for each stretch between scope-altering topics.
884
+ while ($index < scalar @parsedFile)
885
+ {
886
+ my $scope = NaturalDocs::Topics->TypeInfo($parsedFile[$index]->Type())->Scope();
887
+
888
+ if ($scope == ::SCOPE_START() || $scope == ::SCOPE_END())
889
+ {
890
+ if ($index > $startStretch)
891
+ { $index += $self->MakeAutoGroupsFor($startStretch, $index); };
892
+
893
+ $startStretch = $index + 1;
894
+ };
895
+
896
+ $index++;
897
+ };
898
+
899
+ if ($index > $startStretch)
900
+ { $self->MakeAutoGroupsFor($startStretch, $index); };
901
+ };
902
+
903
+
904
+ #
905
+ # Function: MakeAutoGroupsFor
906
+ #
907
+ # Creates group topics for sections of files that do not have them. A support function for <MakeAutoGroups()>.
908
+ #
909
+ # Parameters:
910
+ #
911
+ # startIndex - The index to start at.
912
+ # endIndex - The index to end at. Not inclusive.
913
+ #
914
+ # Returns:
915
+ #
916
+ # The number of group topics added.
917
+ #
918
+ sub MakeAutoGroupsFor #(startIndex, endIndex)
919
+ {
920
+ my ($self, $startIndex, $endIndex) = @_;
921
+
922
+ # No groups if any are defined already.
923
+ for (my $i = $startIndex; $i < $endIndex; $i++)
924
+ {
925
+ if ($parsedFile[$i]->Type() eq ::TOPIC_GROUP())
926
+ { return 0; };
927
+ };
928
+
929
+
930
+ use constant COUNT => 0;
931
+ use constant TYPE => 1;
932
+ use constant SECOND_TYPE => 2;
933
+ use constant SIZE => 3;
934
+
935
+ # This is an array of ( count, type, secondType ) triples. Count and Type will always be filled in; count is the number of
936
+ # consecutive topics of type. On the second pass, if small groups are combined secondType will be filled in. There will not be
937
+ # more than two types per group.
938
+ my @groups;
939
+ my $groupIndex = 0;
940
+
941
+
942
+ # First pass: Determine all the groups.
943
+
944
+ my $i = $startIndex;
945
+ my $currentType;
946
+
947
+ while ($i < $endIndex)
948
+ {
949
+ if (!defined $currentType || ($parsedFile[$i]->Type() ne $currentType && $parsedFile[$i]->Type() ne ::TOPIC_GENERIC()) )
950
+ {
951
+ if (defined $currentType)
952
+ { $groupIndex += SIZE; };
953
+
954
+ $currentType = $parsedFile[$i]->Type();
955
+
956
+ $groups[$groupIndex + COUNT] = 1;
957
+ $groups[$groupIndex + TYPE] = $currentType;
958
+ }
959
+ else
960
+ { $groups[$groupIndex + COUNT]++; };
961
+
962
+ $i++;
963
+ };
964
+
965
+
966
+ # Second pass: Combine groups based on "noise". Noise means types go from A to B to A at least once, and there are at least
967
+ # two groups in a row with three or less, and at least one of those groups is two or less. So 3, 3, 3 doesn't count as noise, but
968
+ # 3, 2, 3 does.
969
+
970
+ $groupIndex = 0;
971
+
972
+ # While there are at least three groups left...
973
+ while ($groupIndex < scalar @groups - (2 * SIZE))
974
+ {
975
+ # If the group two places in front of this one has the same type...
976
+ if ($groups[$groupIndex + (2 * SIZE) + TYPE] eq $groups[$groupIndex + TYPE])
977
+ {
978
+ # It means we went from A to B to A, which partially qualifies as noise.
979
+
980
+ my $firstType = $groups[$groupIndex + TYPE];
981
+ my $secondType = $groups[$groupIndex + SIZE + TYPE];
982
+
983
+ if (NaturalDocs::Topics->TypeInfo($firstType)->CanGroupWith($secondType) ||
984
+ NaturalDocs::Topics->TypeInfo($secondType)->CanGroupWith($firstType))
985
+ {
986
+ my $hasNoise;
987
+
988
+ my $hasThrees;
989
+ my $hasTwosOrOnes;
990
+
991
+ my $endIndex = $groupIndex;
992
+
993
+ while ($endIndex < scalar @groups &&
994
+ ($groups[$endIndex + TYPE] eq $firstType || $groups[$endIndex + TYPE] eq $secondType))
995
+ {
996
+ if ($groups[$endIndex + COUNT] > 3)
997
+ {
998
+ # They must be consecutive to count.
999
+ $hasThrees = 0;
1000
+ $hasTwosOrOnes = 0;
1001
+ }
1002
+ elsif ($groups[$endIndex + COUNT] == 3)
1003
+ {
1004
+ $hasThrees = 1;
1005
+
1006
+ if ($hasTwosOrOnes)
1007
+ { $hasNoise = 1; };
1008
+ }
1009
+ else # < 3
1010
+ {
1011
+ if ($hasThrees || $hasTwosOrOnes)
1012
+ { $hasNoise = 1; };
1013
+
1014
+ $hasTwosOrOnes = 1;
1015
+ };
1016
+
1017
+ $endIndex += SIZE;
1018
+ };
1019
+
1020
+ if (!$hasNoise)
1021
+ {
1022
+ $groupIndex = $endIndex - SIZE;
1023
+ }
1024
+ else # hasNoise
1025
+ {
1026
+ $groups[$groupIndex + SECOND_TYPE] = $secondType;
1027
+
1028
+ for (my $noiseIndex = $groupIndex + SIZE; $noiseIndex < $endIndex; $noiseIndex += SIZE)
1029
+ {
1030
+ $groups[$groupIndex + COUNT] += $groups[$noiseIndex + COUNT];
1031
+ };
1032
+
1033
+ splice(@groups, $groupIndex + SIZE, $endIndex - $groupIndex - SIZE);
1034
+
1035
+ $groupIndex += SIZE;
1036
+ };
1037
+ }
1038
+
1039
+ else # They can't group together
1040
+ {
1041
+ $groupIndex += SIZE;
1042
+ };
1043
+ }
1044
+
1045
+ else
1046
+ { $groupIndex += SIZE; };
1047
+ };
1048
+
1049
+
1050
+ # Finally, create group topics for the parsed file.
1051
+
1052
+ $groupIndex = 0;
1053
+ $i = $startIndex;
1054
+
1055
+ while ($groupIndex < scalar @groups)
1056
+ {
1057
+ if ($groups[$groupIndex + TYPE] ne ::TOPIC_GENERIC())
1058
+ {
1059
+ my $topic = $parsedFile[$i];
1060
+ my $title = NaturalDocs::Topics->NameOfType($groups[$groupIndex + TYPE], 1);
1061
+
1062
+ if (defined $groups[$groupIndex + SECOND_TYPE])
1063
+ { $title .= ' and ' . NaturalDocs::Topics->NameOfType($groups[$groupIndex + SECOND_TYPE], 1); };
1064
+
1065
+ splice(@parsedFile, $i, 0, NaturalDocs::Parser::ParsedTopic->New(::TOPIC_GROUP(),
1066
+ $title,
1067
+ $topic->Package(), $topic->Using(),
1068
+ undef, undef, undef,
1069
+ $topic->LineNumber()) );
1070
+ $i++;
1071
+ };
1072
+
1073
+ $i += $groups[$groupIndex + COUNT];
1074
+ $groupIndex += SIZE;
1075
+ };
1076
+
1077
+ return (scalar @groups / SIZE);
1078
+ };
1079
+
1080
+
1081
+ #
1082
+ # Function: AddToClassHierarchy
1083
+ #
1084
+ # Adds any class topics to the class hierarchy, since they may not have been called with <OnClass()> if they didn't match up to
1085
+ # an auto-topic.
1086
+ #
1087
+ sub AddToClassHierarchy
1088
+ {
1089
+ my ($self) = @_;
1090
+
1091
+ foreach my $topic (@parsedFile)
1092
+ {
1093
+ if ($topic->Type() && NaturalDocs::Topics->TypeInfo( $topic->Type() )->ClassHierarchy())
1094
+ {
1095
+ if ($topic->IsList())
1096
+ {
1097
+ my $body = $topic->Body();
1098
+
1099
+ while ($body =~ /<ds>([^<]+)<\/ds>/g)
1100
+ {
1101
+ $self->OnClass( NaturalDocs::SymbolString->FromText( NaturalDocs::NDMarkup->RestoreAmpChars($1) ) );
1102
+ };
1103
+ }
1104
+ else
1105
+ {
1106
+ $self->OnClass($topic->Package());
1107
+ };
1108
+ };
1109
+ };
1110
+ };
1111
+
1112
+
1113
+ #
1114
+ # Function: AddPackageDelineators
1115
+ #
1116
+ # Adds section and class topics to make sure the package is correctly represented in the documentation. Should be called last in
1117
+ # this process.
1118
+ #
1119
+ sub AddPackageDelineators
1120
+ {
1121
+ my ($self) = @_;
1122
+
1123
+ my $index = 0;
1124
+ my $currentPackage;
1125
+
1126
+ # Values are the arrayref [ title, type ];
1127
+ my %usedPackages;
1128
+
1129
+ while ($index < scalar @parsedFile)
1130
+ {
1131
+ my $topic = $parsedFile[$index];
1132
+
1133
+ if ($topic->Package() ne $currentPackage)
1134
+ {
1135
+ $currentPackage = $topic->Package();
1136
+ my $scopeType = NaturalDocs::Topics->TypeInfo($topic->Type())->Scope();
1137
+
1138
+ if ($scopeType == ::SCOPE_START())
1139
+ {
1140
+ $usedPackages{$currentPackage} = [ $topic->Title(), $topic->Type() ];
1141
+ }
1142
+ elsif ($scopeType == ::SCOPE_END())
1143
+ {
1144
+ my $newTopic;
1145
+
1146
+ if (!defined $currentPackage)
1147
+ {
1148
+ $newTopic = NaturalDocs::Parser::ParsedTopic->New(::TOPIC_SECTION(), 'Global',
1149
+ undef, undef,
1150
+ undef, undef, undef,
1151
+ $topic->LineNumber(), undef);
1152
+ }
1153
+ else
1154
+ {
1155
+ my ($title, $body, $summary, $type);
1156
+ my @packageIdentifiers = NaturalDocs::SymbolString->IdentifiersOf($currentPackage);
1157
+
1158
+ if (exists $usedPackages{$currentPackage})
1159
+ {
1160
+ $title = $usedPackages{$currentPackage}->[0];
1161
+ $type = $usedPackages{$currentPackage}->[1];
1162
+ $body = '<p>(continued)</p>';
1163
+ $summary = '(continued)';
1164
+ }
1165
+ else
1166
+ {
1167
+ $title = join($language->PackageSeparator(), @packageIdentifiers);
1168
+ $type = ::TOPIC_CLASS();
1169
+
1170
+ # Body and summary stay undef.
1171
+
1172
+ $usedPackages{$currentPackage} = $title;
1173
+ };
1174
+
1175
+ my @titleIdentifiers = NaturalDocs::SymbolString->IdentifiersOf( NaturalDocs::SymbolString->FromText($title) );
1176
+ for (my $i = 0; $i < scalar @titleIdentifiers; $i++)
1177
+ { pop @packageIdentifiers; };
1178
+
1179
+ $newTopic = NaturalDocs::Parser::ParsedTopic->New($type, $title,
1180
+ NaturalDocs::SymbolString->Join(@packageIdentifiers), undef,
1181
+ undef, $summary, $body,
1182
+ $topic->LineNumber(), undef);
1183
+ }
1184
+
1185
+ splice(@parsedFile, $index, 0, $newTopic);
1186
+ $index++;
1187
+ }
1188
+ };
1189
+
1190
+ $index++;
1191
+ };
1192
+ };
1193
+
1194
+
1195
+ #
1196
+ # Function: BreakLists
1197
+ #
1198
+ # Breaks list topics into individual topics.
1199
+ #
1200
+ sub BreakLists
1201
+ {
1202
+ my $self = shift;
1203
+
1204
+ my $index = 0;
1205
+
1206
+ while ($index < scalar @parsedFile)
1207
+ {
1208
+ my $topic = $parsedFile[$index];
1209
+
1210
+ if ($topic->IsList() && NaturalDocs::Topics->TypeInfo( $topic->Type() )->BreakLists())
1211
+ {
1212
+ my $body = $topic->Body();
1213
+
1214
+ my @newTopics;
1215
+ my $newBody;
1216
+
1217
+ my $bodyIndex = 0;
1218
+
1219
+ for (;;)
1220
+ {
1221
+ my $startList = index($body, '<dl>', $bodyIndex);
1222
+
1223
+ if ($startList == -1)
1224
+ { last; };
1225
+
1226
+ $newBody .= substr($body, $bodyIndex, $startList - $bodyIndex);
1227
+
1228
+ my $endList = index($body, '</dl>', $startList);
1229
+ my $listBody = substr($body, $startList, $endList - $startList);
1230
+
1231
+ while ($listBody =~ /<ds>([^<]+)<\/ds><dd>(.*?)<\/dd>/g)
1232
+ {
1233
+ my ($symbol, $description) = ($1, $2);
1234
+
1235
+ push @newTopics, NaturalDocs::Parser::ParsedTopic->New( $topic->Type(), $symbol, $topic->Package(),
1236
+ $topic->Using(), undef,
1237
+ $self->GetSummaryFromDescriptionList($description),
1238
+ '<p>' . $description . '</p>', $topic->LineNumber(),
1239
+ undef );
1240
+ };
1241
+
1242
+ $bodyIndex = $endList + 5;
1243
+ };
1244
+
1245
+ $newBody .= substr($body, $bodyIndex);
1246
+
1247
+ # Remove trailing headings.
1248
+ $newBody =~ s/(?:<h>[^<]+<\/h>)+$//;
1249
+
1250
+ # Remove empty headings.
1251
+ $newBody =~ s/(?:<h>[^<]+<\/h>)+(<h>[^<]+<\/h>)/$1/g;
1252
+
1253
+ if ($newBody)
1254
+ {
1255
+ unshift @newTopics, NaturalDocs::Parser::ParsedTopic->New( ::TOPIC_GROUP(), $topic->Title(), $topic->Package(),
1256
+ $topic->Using(), undef,
1257
+ $self->GetSummaryFromBody($newBody), $newBody,
1258
+ $topic->LineNumber(), undef );
1259
+ };
1260
+
1261
+ splice(@parsedFile, $index, 1, @newTopics);
1262
+
1263
+ $index += scalar @newTopics;
1264
+ }
1265
+
1266
+ else # not a list
1267
+ { $index++; };
1268
+ };
1269
+ };
1270
+
1271
+
1272
+ #
1273
+ # Function: GetSummaryFromBody
1274
+ #
1275
+ # Returns the summary text from the topic body.
1276
+ #
1277
+ # Parameters:
1278
+ #
1279
+ # body - The complete topic body, in <NDMarkup>.
1280
+ #
1281
+ # Returns:
1282
+ #
1283
+ # The topic summary, or undef if none.
1284
+ #
1285
+ sub GetSummaryFromBody #(body)
1286
+ {
1287
+ my ($self, $body) = @_;
1288
+
1289
+ my $summary;
1290
+
1291
+ # Extract the first sentence from the leading paragraph, if any. We'll tolerate a single header beforehand, but nothing else.
1292
+
1293
+ if ($body =~ /^(?:<h>[^<]*<\/h>)?<p>(.*?)(<\/p>|[\.\!\?](?:[\)\}\'\ ]|&quot;|&gt;))/x)
1294
+ {
1295
+ $summary = $1;
1296
+
1297
+ if ($2 ne '</p>')
1298
+ { $summary .= $2; };
1299
+ };
1300
+
1301
+ return $summary;
1302
+ };
1303
+
1304
+
1305
+ #
1306
+ # Function: GetSummaryFromDescriptionList
1307
+ #
1308
+ # Returns the summary text from a description list entry.
1309
+ #
1310
+ # Parameters:
1311
+ #
1312
+ # description - The description in <NDMarkup>. Should be the content between the <dd></dd> tags only.
1313
+ #
1314
+ # Returns:
1315
+ #
1316
+ # The description summary, or undef if none.
1317
+ #
1318
+ sub GetSummaryFromDescriptionList #(description)
1319
+ {
1320
+ my ($self, $description) = @_;
1321
+
1322
+ my $summary;
1323
+
1324
+ if ($description =~ /^(.*?)($|[\.\!\?](?:[\)\}\'\ ]|&quot;|&gt;))/)
1325
+ { $summary = $1 . $2; };
1326
+
1327
+ return $summary;
1328
+ };
1329
+
1330
+
1331
+ 1;