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.
- data/LICENSE +20 -0
- data/README.markdown +49 -0
- data/VERSION +1 -0
- data/bin/bixbite +73 -0
- data/lib/bixbite.rb +13 -0
- data/lib/bixbite/command.rb +14 -0
- data/lib/bixbite/create.rb +76 -0
- data/template/Rakefile +25 -0
- data/template/assets/bixbite/Rakefile.rb +297 -0
- data/template/assets/naturaldocs/NaturalDocs/Config/Languages.txt +286 -0
- data/template/assets/naturaldocs/NaturalDocs/Config/Topics.txt +382 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/customizinglanguages.html +52 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/customizingtopics.html +74 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/documenting.html +58 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/documenting/reference.html +146 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/documenting/walkthrough.html +180 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/example/Default.css +528 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/example/NaturalDocs.js +204 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/examples.css +90 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/background.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/leftside.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/logo.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbody.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overbodybg.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overleftmargin.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenu.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/overmenubg.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/header/rightside.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/logo.gif +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/about.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/background.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomleft.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/bottomright.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/community.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/customizing.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/images/menu/using.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/index.html +9 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/javascript/BrowserStyles.js +77 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/javascript/PNGHandling.js +72 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/keywords.html +38 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/languages.html +32 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/menu.html +79 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/output.html +84 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/running.html +40 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/styles.css +290 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/styles.html +52 -0
- data/template/assets/naturaldocs/NaturalDocs/Help/troubleshooting.html +18 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/CSSGuide.txt +947 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/File Parsing.txt +83 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/HTMLTestCases.pm +269 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/Languages.txt +107 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/NDMarkup.txt +91 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/Symbol Management.txt +59 -0
- data/template/assets/naturaldocs/NaturalDocs/Info/images/Logo.png +0 -0
- data/template/assets/naturaldocs/NaturalDocs/JavaScript/NaturalDocs.js +836 -0
- data/template/assets/naturaldocs/NaturalDocs/License-GPL.txt +341 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/BinaryFile.pm +294 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder.pm +280 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/Base.pm +348 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/FramedHTML.pm +345 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTML.pm +398 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Builder/HTMLBase.pm +3693 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy.pm +860 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/Class.pm +412 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ClassHierarchy/File.pm +157 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ConfigFile.pm +497 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Constants.pm +165 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/DefineMembers.pm +100 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Error.pm +305 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/File.pm +540 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable.pm +383 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/Reference.pm +44 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ImageReferenceTable/String.pm +110 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages.pm +1475 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/ActionScript.pm +1473 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Ada.pm +38 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced.pm +828 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/Scope.pm +95 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Advanced/ScopeChange.pm +70 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Base.pm +832 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/CSharp.pm +1484 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/PLSQL.pm +319 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Pascal.pm +143 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Perl.pm +1370 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype.pm +92 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Prototype/Parameter.pm +87 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Simple.pm +503 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Languages/Tcl.pm +219 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu.pm +3406 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Menu/Entry.pm +201 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/NDMarkup.pm +76 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser.pm +1331 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/JavaDoc.pm +464 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/Native.pm +1060 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Parser/ParsedTopic.pm +253 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project.pm +1402 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/ImageFile.pm +160 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Project/SourceFile.pm +113 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/ReferenceString.pm +334 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings.pm +1418 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Settings/BuildTarget.pm +66 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB.pm +678 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Extension.pm +84 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/File.pm +129 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/Item.pm +201 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/ItemDefinition.pm +45 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SourceDB/WatchedFileDefinitions.pm +159 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/StatusMessage.pm +102 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolString.pm +212 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable.pm +1984 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/File.pm +186 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/IndexElement.pm +522 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Reference.pm +273 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/ReferenceTarget.pm +97 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/Symbol.pm +428 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/SymbolTable/SymbolDefinition.pm +96 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics.pm +1319 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Topics/Type.pm +151 -0
- data/template/assets/naturaldocs/NaturalDocs/Modules/NaturalDocs/Version.pm +384 -0
- data/template/assets/naturaldocs/NaturalDocs/NaturalDocs +400 -0
- data/template/assets/naturaldocs/NaturalDocs/NaturalDocs.bat +17 -0
- data/template/assets/naturaldocs/NaturalDocs/Styles/Default.css +767 -0
- data/template/assets/naturaldocs/NaturalDocs/Styles/Roman.css +765 -0
- data/template/assets/naturaldocs/NaturalDocs/Styles/Small.css +763 -0
- data/template/assets/utilities/pngout +0 -0
- data/template/deploy/public_html/.htaccess +0 -0
- data/template/documentation/js/.htaccess +0 -0
- data/template/src/html/.htaccess +76 -0
- data/template/src/html/css/cmn/global.css +96 -0
- data/template/src/html/css/cmn/ie.css +15 -0
- data/template/src/html/css/cmn/ie6.css +15 -0
- data/template/src/html/images/cmn/.htaccess +0 -0
- data/template/src/html/images/tmp/.htaccess +0 -0
- data/template/src/html/includes/debug.inc +5 -0
- data/template/src/html/includes/footer.inc +52 -0
- data/template/src/html/includes/header.inc +61 -0
- data/template/src/html/includes/html.inc +3 -0
- data/template/src/html/includes/namespace.inc +19 -0
- data/template/src/html/includes/page.inc +151 -0
- data/template/src/html/index.html +35 -0
- data/template/src/html/js/cmn/bootstrap.js +74 -0
- data/template/src/html/js/cmn/global.js +142 -0
- data/template/src/html/js/cmn/lib/LAB.js +348 -0
- data/template/src/html/min/.htaccess +4 -0
- data/template/src/html/min/MinifyCLI.php +19 -0
- data/template/src/html/min/README.txt +132 -0
- data/template/src/html/min/builder/_index.js +242 -0
- data/template/src/html/min/builder/bm.js +36 -0
- data/template/src/html/min/builder/index.php +182 -0
- data/template/src/html/min/builder/ocCheck.php +36 -0
- data/template/src/html/min/builder/rewriteTest.js +1 -0
- data/template/src/html/min/config.php +187 -0
- data/template/src/html/min/groupsConfig.php +34 -0
- data/template/src/html/min/index.php +66 -0
- data/template/src/html/min/lib/FirePHP.php +1370 -0
- data/template/src/html/min/lib/HTTP/ConditionalGet.php +348 -0
- data/template/src/html/min/lib/HTTP/Encoder.php +326 -0
- data/template/src/html/min/lib/JSMin.php +314 -0
- data/template/src/html/min/lib/JSMinPlus.php +1872 -0
- data/template/src/html/min/lib/Minify.php +532 -0
- data/template/src/html/min/lib/Minify/Build.php +103 -0
- data/template/src/html/min/lib/Minify/CSS.php +83 -0
- data/template/src/html/min/lib/Minify/CSS/Compressor.php +250 -0
- data/template/src/html/min/lib/Minify/CSS/UriRewriter.php +270 -0
- data/template/src/html/min/lib/Minify/Cache/APC.php +130 -0
- data/template/src/html/min/lib/Minify/Cache/File.php +125 -0
- data/template/src/html/min/lib/Minify/Cache/Memcache.php +137 -0
- data/template/src/html/min/lib/Minify/ClosureCompiler.php +85 -0
- data/template/src/html/min/lib/Minify/CommentPreserver.php +90 -0
- data/template/src/html/min/lib/Minify/Controller/Base.php +202 -0
- data/template/src/html/min/lib/Minify/Controller/Files.php +78 -0
- data/template/src/html/min/lib/Minify/Controller/Groups.php +94 -0
- data/template/src/html/min/lib/Minify/Controller/MinApp.php +132 -0
- data/template/src/html/min/lib/Minify/Controller/Page.php +82 -0
- data/template/src/html/min/lib/Minify/Controller/Version1.php +118 -0
- data/template/src/html/min/lib/Minify/HTML.php +245 -0
- data/template/src/html/min/lib/Minify/ImportProcessor.php +157 -0
- data/template/src/html/min/lib/Minify/Lines.php +131 -0
- data/template/src/html/min/lib/Minify/Logger.php +45 -0
- data/template/src/html/min/lib/Minify/Packer.php +37 -0
- data/template/src/html/min/lib/Minify/Source.php +187 -0
- data/template/src/html/min/lib/Minify/YUICompressor.php +139 -0
- data/template/src/html/min/lib/Solar/Dir.php +199 -0
- data/template/src/html/min/lib/closure-compiler.jar +0 -0
- data/template/src/html/min/lib/yuicompressor-2.4.2.jar +0 -0
- data/template/src/html/min/utils.php +90 -0
- data/template/src/templates/css/template.css +7 -0
- data/template/src/templates/js/template.js +72 -0
- data/template/src/templates/template.html +18 -0
- data/template/src/yaml/config.yml +46 -0
- data/template/src/yaml/deploy.yml +35 -0
- data/test/bixbite_test.rb +7 -0
- data/test/test_helper.rb +10 -0
- metadata +278 -0
@@ -0,0 +1,1060 @@
|
|
1
|
+
###############################################################################
|
2
|
+
#
|
3
|
+
# Package: NaturalDocs::Parser::Native
|
4
|
+
#
|
5
|
+
###############################################################################
|
6
|
+
#
|
7
|
+
# A package that converts comments from Natural Docs' native format into <NaturalDocs::Parser::ParsedTopic> objects.
|
8
|
+
# Unlike most second-level packages, these are packages and not object classes.
|
9
|
+
#
|
10
|
+
###############################################################################
|
11
|
+
|
12
|
+
# This file is part of Natural Docs, which is Copyright (C) 2003-2008 Greg Valure
|
13
|
+
# Natural Docs is licensed under the GPL
|
14
|
+
|
15
|
+
|
16
|
+
use strict;
|
17
|
+
use integer;
|
18
|
+
|
19
|
+
package NaturalDocs::Parser::Native;
|
20
|
+
|
21
|
+
|
22
|
+
###############################################################################
|
23
|
+
# Group: Variables
|
24
|
+
|
25
|
+
|
26
|
+
# Return values of TagType(). Not documented here.
|
27
|
+
use constant POSSIBLE_OPENING_TAG => 1;
|
28
|
+
use constant POSSIBLE_CLOSING_TAG => 2;
|
29
|
+
use constant NOT_A_TAG => 3;
|
30
|
+
|
31
|
+
|
32
|
+
#
|
33
|
+
# var: package
|
34
|
+
#
|
35
|
+
# A <SymbolString> representing the package normal topics will be a part of at the current point in the file. This is a package variable
|
36
|
+
# because it needs to be reserved between function calls.
|
37
|
+
#
|
38
|
+
my $package;
|
39
|
+
|
40
|
+
#
|
41
|
+
# hash: functionListIgnoredHeadings
|
42
|
+
#
|
43
|
+
# An existence hash of all the headings that prevent the parser from creating function list symbols. Whenever one of
|
44
|
+
# these headings are used in a function list topic, symbols are not created from definition lists until the next heading. The keys
|
45
|
+
# are in all lowercase.
|
46
|
+
#
|
47
|
+
my %functionListIgnoredHeadings = ( 'parameters' => 1,
|
48
|
+
'parameter' => 1,
|
49
|
+
'params' => 1,
|
50
|
+
'param' => 1,
|
51
|
+
'arguments' => 1,
|
52
|
+
'argument' => 1,
|
53
|
+
'args' => 1,
|
54
|
+
'arg' => 1 );
|
55
|
+
|
56
|
+
|
57
|
+
###############################################################################
|
58
|
+
# Group: Interface Functions
|
59
|
+
|
60
|
+
|
61
|
+
#
|
62
|
+
# Function: Start
|
63
|
+
#
|
64
|
+
# This will be called whenever a file is about to be parsed. It allows the package to reset its internal state.
|
65
|
+
#
|
66
|
+
sub Start
|
67
|
+
{
|
68
|
+
my ($self) = @_;
|
69
|
+
$package = undef;
|
70
|
+
};
|
71
|
+
|
72
|
+
|
73
|
+
#
|
74
|
+
# Function: IsMine
|
75
|
+
#
|
76
|
+
# Examines the comment and returns whether it is *definitely* Natural Docs content, i.e. it is owned by this package. Note
|
77
|
+
# that a comment can fail this function and still be interpreted as a Natural Docs content, for example a JavaDoc-styled comment
|
78
|
+
# that doesn't have header lines but no JavaDoc tags either.
|
79
|
+
#
|
80
|
+
# Parameters:
|
81
|
+
#
|
82
|
+
# commentLines - An arrayref of the comment lines. Must have been run through <NaturalDocs::Parser->CleanComment()>.
|
83
|
+
# isJavaDoc - Whether the comment was JavaDoc-styled.
|
84
|
+
#
|
85
|
+
# Returns:
|
86
|
+
#
|
87
|
+
# Whether the comment is *definitely* Natural Docs content.
|
88
|
+
#
|
89
|
+
sub IsMine #(string[] commentLines, bool isJavaDoc)
|
90
|
+
{
|
91
|
+
my ($self, $commentLines, $isJavaDoc) = @_;
|
92
|
+
|
93
|
+
# Skip to the first line with content.
|
94
|
+
my $line = 0;
|
95
|
+
|
96
|
+
while ($line < scalar @$commentLines && !length $commentLines->[$line])
|
97
|
+
{ $line++; };
|
98
|
+
|
99
|
+
return $self->ParseHeaderLine($commentLines->[$line]);
|
100
|
+
};
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
#
|
105
|
+
# Function: ParseComment
|
106
|
+
#
|
107
|
+
# This will be called whenever a comment capable of containing Natural Docs content is found.
|
108
|
+
#
|
109
|
+
# Parameters:
|
110
|
+
#
|
111
|
+
# commentLines - An arrayref of the comment lines. Must have been run through <NaturalDocs::Parser->CleanComment()>.
|
112
|
+
# *The original memory will be changed.*
|
113
|
+
# isJavaDoc - Whether the comment is JavaDoc styled.
|
114
|
+
# lineNumber - The line number of the first of the comment lines.
|
115
|
+
# parsedTopics - A reference to the array where any new <NaturalDocs::Parser::ParsedTopics> should be placed.
|
116
|
+
#
|
117
|
+
# Returns:
|
118
|
+
#
|
119
|
+
# The number of parsed topics added to the array, or zero if none.
|
120
|
+
#
|
121
|
+
sub ParseComment #(commentLines, isJavaDoc, lineNumber, parsedTopics)
|
122
|
+
{
|
123
|
+
my ($self, $commentLines, $isJavaDoc, $lineNumber, $parsedTopics) = @_;
|
124
|
+
|
125
|
+
my $topicCount = 0;
|
126
|
+
my $prevLineBlank = 1;
|
127
|
+
my $inCodeSection = 0;
|
128
|
+
|
129
|
+
my ($type, $scope, $isPlural, $title, $symbol);
|
130
|
+
#my $package; # package variable.
|
131
|
+
my ($newKeyword, $newTitle);
|
132
|
+
|
133
|
+
my $index = 0;
|
134
|
+
|
135
|
+
my $bodyStart = 0;
|
136
|
+
my $bodyEnd = 0; # Not inclusive.
|
137
|
+
|
138
|
+
while ($index < scalar @$commentLines)
|
139
|
+
{
|
140
|
+
# Everything but leading whitespace was removed beforehand.
|
141
|
+
|
142
|
+
# If we're in a code section...
|
143
|
+
if ($inCodeSection)
|
144
|
+
{
|
145
|
+
if ($commentLines->[$index] =~ /^ *\( *(?:end|finish|done)(?: +(?:table|code|example|diagram))? *\)$/i)
|
146
|
+
{ $inCodeSection = undef; };
|
147
|
+
|
148
|
+
$prevLineBlank = 0;
|
149
|
+
$bodyEnd++;
|
150
|
+
}
|
151
|
+
|
152
|
+
# If the line is empty...
|
153
|
+
elsif (!length($commentLines->[$index]))
|
154
|
+
{
|
155
|
+
$prevLineBlank = 1;
|
156
|
+
|
157
|
+
if ($topicCount)
|
158
|
+
{ $bodyEnd++; };
|
159
|
+
}
|
160
|
+
|
161
|
+
# If the line has a recognized header and the previous line is blank...
|
162
|
+
elsif ($prevLineBlank && (($newKeyword, $newTitle) = $self->ParseHeaderLine($commentLines->[$index])) )
|
163
|
+
{
|
164
|
+
# Process the previous one, if any.
|
165
|
+
|
166
|
+
if ($topicCount)
|
167
|
+
{
|
168
|
+
if ($scope == ::SCOPE_START() || $scope == ::SCOPE_END())
|
169
|
+
{ $package = undef; };
|
170
|
+
|
171
|
+
my $body = $self->FormatBody($commentLines, $bodyStart, $bodyEnd, $type, $isPlural);
|
172
|
+
my $newTopic = $self->MakeParsedTopic($type, $title, $package, $body, $lineNumber + $bodyStart - 1, $isPlural);
|
173
|
+
push @$parsedTopics, $newTopic;
|
174
|
+
|
175
|
+
$package = $newTopic->Package();
|
176
|
+
};
|
177
|
+
|
178
|
+
$title = $newTitle;
|
179
|
+
|
180
|
+
my $typeInfo;
|
181
|
+
($type, $typeInfo, $isPlural) = NaturalDocs::Topics->KeywordInfo($newKeyword);
|
182
|
+
$scope = $typeInfo->Scope();
|
183
|
+
|
184
|
+
$bodyStart = $index + 1;
|
185
|
+
$bodyEnd = $index + 1;
|
186
|
+
|
187
|
+
$topicCount++;
|
188
|
+
|
189
|
+
$prevLineBlank = 0;
|
190
|
+
}
|
191
|
+
|
192
|
+
# If we're on a non-empty, non-header line of a JavaDoc-styled comment and we haven't started a topic yet...
|
193
|
+
elsif ($isJavaDoc && !$topicCount)
|
194
|
+
{
|
195
|
+
$type = undef;
|
196
|
+
$scope = ::SCOPE_NORMAL(); # The scope repair and topic merging processes will handle if this is a class topic.
|
197
|
+
$isPlural = undef;
|
198
|
+
$title = undef;
|
199
|
+
$symbol = undef;
|
200
|
+
|
201
|
+
$bodyStart = $index;
|
202
|
+
$bodyEnd = $index + 1;
|
203
|
+
|
204
|
+
$topicCount++;
|
205
|
+
|
206
|
+
$prevLineBlank = undef;
|
207
|
+
}
|
208
|
+
|
209
|
+
# If we're on a normal content line within a topic
|
210
|
+
elsif ($topicCount)
|
211
|
+
{
|
212
|
+
$prevLineBlank = 0;
|
213
|
+
$bodyEnd++;
|
214
|
+
|
215
|
+
if ($commentLines->[$index] =~ /^ *\( *(?:(?:start|begin)? +)?(?:table|code|example|diagram) *\)$/i)
|
216
|
+
{ $inCodeSection = 1; };
|
217
|
+
};
|
218
|
+
|
219
|
+
|
220
|
+
$index++;
|
221
|
+
};
|
222
|
+
|
223
|
+
|
224
|
+
# Last one, if any. This is the only one that gets the prototypes.
|
225
|
+
if ($bodyStart)
|
226
|
+
{
|
227
|
+
if ($scope == ::SCOPE_START() || $scope == ::SCOPE_END())
|
228
|
+
{ $package = undef; };
|
229
|
+
|
230
|
+
my $body = $self->FormatBody($commentLines, $bodyStart, $bodyEnd, $type, $isPlural);
|
231
|
+
my $newTopic = $self->MakeParsedTopic($type, $title, $package, $body, $lineNumber + $bodyStart - 1, $isPlural);
|
232
|
+
push @$parsedTopics, $newTopic;
|
233
|
+
$topicCount++;
|
234
|
+
|
235
|
+
$package = $newTopic->Package();
|
236
|
+
};
|
237
|
+
|
238
|
+
return $topicCount;
|
239
|
+
};
|
240
|
+
|
241
|
+
|
242
|
+
#
|
243
|
+
# Function: ParseHeaderLine
|
244
|
+
#
|
245
|
+
# If the passed line is a topic header, returns the array ( keyword, title ). Otherwise returns an empty array.
|
246
|
+
#
|
247
|
+
sub ParseHeaderLine #(line)
|
248
|
+
{
|
249
|
+
my ($self, $line) = @_;
|
250
|
+
|
251
|
+
if ($line =~ /^ *([a-z0-9 ]*[a-z0-9]): +(.*)$/i)
|
252
|
+
{
|
253
|
+
my ($keyword, $title) = ($1, $2);
|
254
|
+
|
255
|
+
# We need to do it this way because if you do "if (ND:T->KeywordInfo($keyword)" and the last element of the array it
|
256
|
+
# returns is false, the statement is false. That is really retarded, but there it is.
|
257
|
+
my ($type, undef, undef) = NaturalDocs::Topics->KeywordInfo($keyword);
|
258
|
+
|
259
|
+
if ($type)
|
260
|
+
{ return ($keyword, $title); }
|
261
|
+
else
|
262
|
+
{ return ( ); };
|
263
|
+
}
|
264
|
+
else
|
265
|
+
{ return ( ); };
|
266
|
+
};
|
267
|
+
|
268
|
+
|
269
|
+
|
270
|
+
###############################################################################
|
271
|
+
# Group: Support Functions
|
272
|
+
|
273
|
+
|
274
|
+
#
|
275
|
+
# Function: MakeParsedTopic
|
276
|
+
#
|
277
|
+
# Creates a <NaturalDocs::Parser::ParsedTopic> object for the passed parameters. Scope is gotten from
|
278
|
+
# the package variable <package> instead of from the parameters. The summary is generated from the body.
|
279
|
+
#
|
280
|
+
# Parameters:
|
281
|
+
#
|
282
|
+
# type - The <TopicType>. May be undef for headerless topics.
|
283
|
+
# title - The title of the topic. May be undef for headerless topics.
|
284
|
+
# package - The package <SymbolString> the topic appears in.
|
285
|
+
# body - The topic's body in <NDMarkup>.
|
286
|
+
# lineNumber - The topic's line number.
|
287
|
+
# isList - Whether the topic is a list.
|
288
|
+
#
|
289
|
+
# Returns:
|
290
|
+
#
|
291
|
+
# The <NaturalDocs::Parser::ParsedTopic> object.
|
292
|
+
#
|
293
|
+
sub MakeParsedTopic #(type, title, package, body, lineNumber, isList)
|
294
|
+
{
|
295
|
+
my ($self, $type, $title, $package, $body, $lineNumber, $isList) = @_;
|
296
|
+
|
297
|
+
my $summary;
|
298
|
+
|
299
|
+
if (defined $body)
|
300
|
+
{ $summary = NaturalDocs::Parser->GetSummaryFromBody($body); };
|
301
|
+
|
302
|
+
return NaturalDocs::Parser::ParsedTopic->New($type, $title, $package, undef, undef, $summary,
|
303
|
+
$body, $lineNumber, $isList);
|
304
|
+
};
|
305
|
+
|
306
|
+
|
307
|
+
#
|
308
|
+
# Function: FormatBody
|
309
|
+
#
|
310
|
+
# Converts the section body to <NDMarkup>.
|
311
|
+
#
|
312
|
+
# Parameters:
|
313
|
+
#
|
314
|
+
# commentLines - The arrayref of comment lines.
|
315
|
+
# startingIndex - The starting index of the body to format.
|
316
|
+
# endingIndex - The ending index of the body to format, *not* inclusive.
|
317
|
+
# type - The type of the section. May be undef for headerless comments.
|
318
|
+
# isList - Whether it's a list topic.
|
319
|
+
#
|
320
|
+
# Returns:
|
321
|
+
#
|
322
|
+
# The body formatted in <NDMarkup>.
|
323
|
+
#
|
324
|
+
sub FormatBody #(commentLines, startingIndex, endingIndex, type, isList)
|
325
|
+
{
|
326
|
+
my ($self, $commentLines, $startingIndex, $endingIndex, $type, $isList) = @_;
|
327
|
+
|
328
|
+
use constant TAG_NONE => 1;
|
329
|
+
use constant TAG_PARAGRAPH => 2;
|
330
|
+
use constant TAG_BULLETLIST => 3;
|
331
|
+
use constant TAG_DESCRIPTIONLIST => 4;
|
332
|
+
use constant TAG_HEADING => 5;
|
333
|
+
use constant TAG_PREFIXCODE => 6;
|
334
|
+
use constant TAG_TAGCODE => 7;
|
335
|
+
|
336
|
+
my %tagEnders = ( TAG_NONE() => '',
|
337
|
+
TAG_PARAGRAPH() => '</p>',
|
338
|
+
TAG_BULLETLIST() => '</li></ul>',
|
339
|
+
TAG_DESCRIPTIONLIST() => '</dd></dl>',
|
340
|
+
TAG_HEADING() => '</h>',
|
341
|
+
TAG_PREFIXCODE() => '</code>',
|
342
|
+
TAG_TAGCODE() => '</code>' );
|
343
|
+
|
344
|
+
my $topLevelTag = TAG_NONE;
|
345
|
+
|
346
|
+
my $output;
|
347
|
+
my $textBlock;
|
348
|
+
my $prevLineBlank = 1;
|
349
|
+
|
350
|
+
my $codeBlock;
|
351
|
+
my $removedCodeSpaces;
|
352
|
+
|
353
|
+
my $ignoreListSymbols;
|
354
|
+
|
355
|
+
my $index = $startingIndex;
|
356
|
+
|
357
|
+
while ($index < $endingIndex)
|
358
|
+
{
|
359
|
+
# If we're in a tagged code section...
|
360
|
+
if ($topLevelTag == TAG_TAGCODE)
|
361
|
+
{
|
362
|
+
if ($commentLines->[$index] =~ /^ *\( *(?:end|finish|done)(?: +(?:table|code|example|diagram))? *\)$/i)
|
363
|
+
{
|
364
|
+
$codeBlock =~ s/\n+$//;
|
365
|
+
$output .= NaturalDocs::NDMarkup->ConvertAmpChars($codeBlock) . '</code>';
|
366
|
+
$codeBlock = undef;
|
367
|
+
$topLevelTag = TAG_NONE;
|
368
|
+
$prevLineBlank = undef;
|
369
|
+
}
|
370
|
+
else
|
371
|
+
{
|
372
|
+
$self->AddToCodeBlock($commentLines->[$index], \$codeBlock, \$removedCodeSpaces);
|
373
|
+
};
|
374
|
+
}
|
375
|
+
|
376
|
+
# If the line starts with a code designator...
|
377
|
+
elsif ($commentLines->[$index] =~ /^ *[>:|](.*)$/)
|
378
|
+
{
|
379
|
+
my $code = $1;
|
380
|
+
|
381
|
+
if ($topLevelTag == TAG_PREFIXCODE)
|
382
|
+
{
|
383
|
+
$self->AddToCodeBlock($code, \$codeBlock, \$removedCodeSpaces);
|
384
|
+
}
|
385
|
+
else # $topLevelTag != TAG_PREFIXCODE
|
386
|
+
{
|
387
|
+
if (defined $textBlock)
|
388
|
+
{
|
389
|
+
$output .= $self->RichFormatTextBlock($textBlock) . $tagEnders{$topLevelTag};
|
390
|
+
$textBlock = undef;
|
391
|
+
};
|
392
|
+
|
393
|
+
$topLevelTag = TAG_PREFIXCODE;
|
394
|
+
$output .= '<code>';
|
395
|
+
$self->AddToCodeBlock($code, \$codeBlock, \$removedCodeSpaces);
|
396
|
+
};
|
397
|
+
}
|
398
|
+
|
399
|
+
# If we're not in either code style...
|
400
|
+
else
|
401
|
+
{
|
402
|
+
# Strip any leading whitespace.
|
403
|
+
$commentLines->[$index] =~ s/^ +//;
|
404
|
+
|
405
|
+
# If we were in a prefixed code section...
|
406
|
+
if ($topLevelTag == TAG_PREFIXCODE)
|
407
|
+
{
|
408
|
+
$codeBlock =~ s/\n+$//;
|
409
|
+
$output .= NaturalDocs::NDMarkup->ConvertAmpChars($codeBlock) . '</code>';
|
410
|
+
$codeBlock = undef;
|
411
|
+
$topLevelTag = TAG_NONE;
|
412
|
+
$prevLineBlank = undef;
|
413
|
+
};
|
414
|
+
|
415
|
+
|
416
|
+
# If the line is blank...
|
417
|
+
if (!length($commentLines->[$index]))
|
418
|
+
{
|
419
|
+
# End a paragraph. Everything else ignores it for now.
|
420
|
+
if ($topLevelTag == TAG_PARAGRAPH)
|
421
|
+
{
|
422
|
+
$output .= $self->RichFormatTextBlock($textBlock) . '</p>';
|
423
|
+
$textBlock = undef;
|
424
|
+
$topLevelTag = TAG_NONE;
|
425
|
+
};
|
426
|
+
|
427
|
+
$prevLineBlank = 1;
|
428
|
+
}
|
429
|
+
|
430
|
+
# If the line starts with a bullet...
|
431
|
+
elsif ($commentLines->[$index] =~ /^[-\*o+] +([^ ].*)$/ &&
|
432
|
+
substr($1, 0, 2) ne '- ') # Make sure "o - Something" is a definition, not a bullet.
|
433
|
+
{
|
434
|
+
my $bulletedText = $1;
|
435
|
+
|
436
|
+
if (defined $textBlock)
|
437
|
+
{ $output .= $self->RichFormatTextBlock($textBlock); };
|
438
|
+
|
439
|
+
if ($topLevelTag == TAG_BULLETLIST)
|
440
|
+
{
|
441
|
+
$output .= '</li><li>';
|
442
|
+
}
|
443
|
+
else #($topLevelTag != TAG_BULLETLIST)
|
444
|
+
{
|
445
|
+
$output .= $tagEnders{$topLevelTag} . '<ul><li>';
|
446
|
+
$topLevelTag = TAG_BULLETLIST;
|
447
|
+
};
|
448
|
+
|
449
|
+
$textBlock = $bulletedText;
|
450
|
+
|
451
|
+
$prevLineBlank = undef;
|
452
|
+
}
|
453
|
+
|
454
|
+
# If the line looks like a description list entry...
|
455
|
+
elsif ($commentLines->[$index] =~ /^(.+?) +- +([^ ].*)$/ && $topLevelTag != TAG_PARAGRAPH)
|
456
|
+
{
|
457
|
+
my $entry = $1;
|
458
|
+
my $description = $2;
|
459
|
+
|
460
|
+
if (defined $textBlock)
|
461
|
+
{ $output .= $self->RichFormatTextBlock($textBlock); };
|
462
|
+
|
463
|
+
if ($topLevelTag == TAG_DESCRIPTIONLIST)
|
464
|
+
{
|
465
|
+
$output .= '</dd>';
|
466
|
+
}
|
467
|
+
else #($topLevelTag != TAG_DESCRIPTIONLIST)
|
468
|
+
{
|
469
|
+
$output .= $tagEnders{$topLevelTag} . '<dl>';
|
470
|
+
$topLevelTag = TAG_DESCRIPTIONLIST;
|
471
|
+
};
|
472
|
+
|
473
|
+
if (($isList && !$ignoreListSymbols) || $type eq ::TOPIC_ENUMERATION())
|
474
|
+
{
|
475
|
+
$output .= '<ds>' . NaturalDocs::NDMarkup->ConvertAmpChars($entry) . '</ds><dd>';
|
476
|
+
}
|
477
|
+
else
|
478
|
+
{
|
479
|
+
$output .= '<de>' . NaturalDocs::NDMarkup->ConvertAmpChars($entry) . '</de><dd>';
|
480
|
+
};
|
481
|
+
|
482
|
+
$textBlock = $description;
|
483
|
+
|
484
|
+
$prevLineBlank = undef;
|
485
|
+
}
|
486
|
+
|
487
|
+
# If the line could be a header...
|
488
|
+
elsif ($prevLineBlank && $commentLines->[$index] =~ /^(.*)([^ ]):$/)
|
489
|
+
{
|
490
|
+
my $headerText = $1 . $2;
|
491
|
+
|
492
|
+
if (defined $textBlock)
|
493
|
+
{
|
494
|
+
$output .= $self->RichFormatTextBlock($textBlock);
|
495
|
+
$textBlock = undef;
|
496
|
+
}
|
497
|
+
|
498
|
+
$output .= $tagEnders{$topLevelTag};
|
499
|
+
$topLevelTag = TAG_NONE;
|
500
|
+
|
501
|
+
$output .= '<h>' . $self->RichFormatTextBlock($headerText) . '</h>';
|
502
|
+
|
503
|
+
if ($type eq ::TOPIC_FUNCTION() && $isList)
|
504
|
+
{
|
505
|
+
$ignoreListSymbols = exists $functionListIgnoredHeadings{lc($headerText)};
|
506
|
+
};
|
507
|
+
|
508
|
+
$prevLineBlank = undef;
|
509
|
+
}
|
510
|
+
|
511
|
+
# If the line looks like a code tag...
|
512
|
+
elsif ($commentLines->[$index] =~ /^\( *(?:(?:start|begin)? +)?(?:table|code|example|diagram) *\)$/i)
|
513
|
+
{
|
514
|
+
if (defined $textBlock)
|
515
|
+
{
|
516
|
+
$output .= $self->RichFormatTextBlock($textBlock);
|
517
|
+
$textBlock = undef;
|
518
|
+
};
|
519
|
+
|
520
|
+
$output .= $tagEnders{$topLevelTag} . '<code>';
|
521
|
+
$topLevelTag = TAG_TAGCODE;
|
522
|
+
}
|
523
|
+
|
524
|
+
# If the line looks like an inline image...
|
525
|
+
elsif ($commentLines->[$index] =~ /^(\( *see +)([^\)]+?)( *\))$/i)
|
526
|
+
{
|
527
|
+
if (defined $textBlock)
|
528
|
+
{
|
529
|
+
$output .= $self->RichFormatTextBlock($textBlock);
|
530
|
+
$textBlock = undef;
|
531
|
+
};
|
532
|
+
|
533
|
+
$output .= $tagEnders{$topLevelTag};
|
534
|
+
$topLevelTag = TAG_NONE;
|
535
|
+
|
536
|
+
$output .= '<img mode="inline" target="' . NaturalDocs::NDMarkup->ConvertAmpChars($2) . '" '
|
537
|
+
. 'original="' . NaturalDocs::NDMarkup->ConvertAmpChars($1 . $2 . $3) . '">';
|
538
|
+
|
539
|
+
$prevLineBlank = undef;
|
540
|
+
}
|
541
|
+
|
542
|
+
# If the line isn't any of those, we consider it normal text.
|
543
|
+
else
|
544
|
+
{
|
545
|
+
# A blank line followed by normal text ends lists. We don't handle this when we detect if the line's blank because
|
546
|
+
# we don't want blank lines between list items to break the list.
|
547
|
+
if ($prevLineBlank && ($topLevelTag == TAG_BULLETLIST || $topLevelTag == TAG_DESCRIPTIONLIST))
|
548
|
+
{
|
549
|
+
$output .= $self->RichFormatTextBlock($textBlock) . $tagEnders{$topLevelTag} . '<p>';
|
550
|
+
|
551
|
+
$topLevelTag = TAG_PARAGRAPH;
|
552
|
+
$textBlock = undef;
|
553
|
+
}
|
554
|
+
|
555
|
+
elsif ($topLevelTag == TAG_NONE)
|
556
|
+
{
|
557
|
+
$output .= '<p>';
|
558
|
+
$topLevelTag = TAG_PARAGRAPH;
|
559
|
+
# textBlock will already be undef.
|
560
|
+
};
|
561
|
+
|
562
|
+
if (defined $textBlock)
|
563
|
+
{ $textBlock .= ' '; };
|
564
|
+
|
565
|
+
$textBlock .= $commentLines->[$index];
|
566
|
+
|
567
|
+
$prevLineBlank = undef;
|
568
|
+
};
|
569
|
+
};
|
570
|
+
|
571
|
+
$index++;
|
572
|
+
};
|
573
|
+
|
574
|
+
# Clean up anything left dangling.
|
575
|
+
if (defined $textBlock)
|
576
|
+
{
|
577
|
+
$output .= $self->RichFormatTextBlock($textBlock) . $tagEnders{$topLevelTag};
|
578
|
+
}
|
579
|
+
elsif (defined $codeBlock)
|
580
|
+
{
|
581
|
+
$codeBlock =~ s/\n+$//;
|
582
|
+
$output .= NaturalDocs::NDMarkup->ConvertAmpChars($codeBlock) . '</code>';
|
583
|
+
};
|
584
|
+
|
585
|
+
return $output;
|
586
|
+
};
|
587
|
+
|
588
|
+
|
589
|
+
#
|
590
|
+
# Function: AddToCodeBlock
|
591
|
+
#
|
592
|
+
# Adds a line of text to a code block, handling all the indentation processing required.
|
593
|
+
#
|
594
|
+
# Parameters:
|
595
|
+
#
|
596
|
+
# line - The line of text to add.
|
597
|
+
# codeBlockRef - A reference to the code block to add it to.
|
598
|
+
# removedSpacesRef - A reference to a variable to hold the number of spaces removed. It needs to be stored between calls.
|
599
|
+
# It will reset itself automatically when the code block codeBlockRef points to is undef.
|
600
|
+
#
|
601
|
+
sub AddToCodeBlock #(line, codeBlockRef, removedSpacesRef)
|
602
|
+
{
|
603
|
+
my ($self, $line, $codeBlockRef, $removedSpacesRef) = @_;
|
604
|
+
|
605
|
+
$line =~ /^( *)(.*)$/;
|
606
|
+
my ($spaces, $code) = ($1, $2);
|
607
|
+
|
608
|
+
if (!defined $$codeBlockRef)
|
609
|
+
{
|
610
|
+
if (length($code))
|
611
|
+
{
|
612
|
+
$$codeBlockRef = $code . "\n";
|
613
|
+
$$removedSpacesRef = length($spaces);
|
614
|
+
};
|
615
|
+
# else ignore leading line breaks.
|
616
|
+
}
|
617
|
+
|
618
|
+
elsif (length $code)
|
619
|
+
{
|
620
|
+
# Make sure we have the minimum amount of spaces to the left possible.
|
621
|
+
if (length($spaces) != $$removedSpacesRef)
|
622
|
+
{
|
623
|
+
my $spaceDifference = abs( length($spaces) - $$removedSpacesRef );
|
624
|
+
my $spacesToAdd = ' ' x $spaceDifference;
|
625
|
+
|
626
|
+
if (length($spaces) > $$removedSpacesRef)
|
627
|
+
{
|
628
|
+
$$codeBlockRef .= $spacesToAdd;
|
629
|
+
}
|
630
|
+
else
|
631
|
+
{
|
632
|
+
$$codeBlockRef =~ s/^(.)/$spacesToAdd . $1/gme;
|
633
|
+
$$removedSpacesRef = length($spaces);
|
634
|
+
};
|
635
|
+
};
|
636
|
+
|
637
|
+
$$codeBlockRef .= $code . "\n";
|
638
|
+
}
|
639
|
+
|
640
|
+
else # (!length $code)
|
641
|
+
{
|
642
|
+
$$codeBlockRef .= "\n";
|
643
|
+
};
|
644
|
+
};
|
645
|
+
|
646
|
+
|
647
|
+
#
|
648
|
+
# Function: RichFormatTextBlock
|
649
|
+
#
|
650
|
+
# Applies rich <NDMarkup> formatting to a chunk of text. This includes both amp chars, formatting tags, and link tags.
|
651
|
+
#
|
652
|
+
# Parameters:
|
653
|
+
#
|
654
|
+
# text - The block of text to format.
|
655
|
+
#
|
656
|
+
# Returns:
|
657
|
+
#
|
658
|
+
# The formatted text block.
|
659
|
+
#
|
660
|
+
sub RichFormatTextBlock #(text)
|
661
|
+
{
|
662
|
+
my ($self, $text) = @_;
|
663
|
+
my $output;
|
664
|
+
|
665
|
+
|
666
|
+
# First find bare urls, e-mail addresses, and images. We have to do this before the split because they may contain underscores
|
667
|
+
# or asterisks. We have to mark the tags with \x1E and \x1F so they don't get confused with angle brackets from the comment.
|
668
|
+
# We can't convert the amp chars beforehand because we need lookbehinds in the regexps below and they need to be
|
669
|
+
# constant length. Sucks, huh?
|
670
|
+
|
671
|
+
$text =~ s{
|
672
|
+
# The previous character can't be an alphanumeric or an opening angle bracket.
|
673
|
+
(?<! [a-z0-9<] )
|
674
|
+
|
675
|
+
# Optional mailto:. Ignored in output.
|
676
|
+
(?:mailto\:)?
|
677
|
+
|
678
|
+
# Begin capture
|
679
|
+
(
|
680
|
+
|
681
|
+
# The user portion. Alphanumeric and - _. Dots can appear between, but not at the edges or more than
|
682
|
+
# one in a row.
|
683
|
+
(?: [a-z0-9\-_]+ \. )* [a-z0-9\-_]+
|
684
|
+
|
685
|
+
@
|
686
|
+
|
687
|
+
# The domain. Alphanumeric and -. Dots same as above, however, there must be at least two sections
|
688
|
+
# and the last one must be two to four alphanumeric characters (.com, .uk, .info, .203 for IP addresses)
|
689
|
+
(?: [a-z0-9\-]+ \. )+ [a-z]{2,4}
|
690
|
+
|
691
|
+
# End capture.
|
692
|
+
)
|
693
|
+
|
694
|
+
# The next character can't be an alphanumeric, which should prevent .abcde from matching the two to
|
695
|
+
# four character requirement, or a closing angle bracket.
|
696
|
+
(?! [a-z0-9>] )
|
697
|
+
|
698
|
+
}
|
699
|
+
|
700
|
+
{"\x1E" . 'email target="' . NaturalDocs::NDMarkup->ConvertAmpChars($1) . '" '
|
701
|
+
. 'name="' . NaturalDocs::NDMarkup->ConvertAmpChars($1) . '"' . "\x1F"}igxe;
|
702
|
+
|
703
|
+
$text =~ s{
|
704
|
+
# The previous character can't be an alphanumeric or an opening angle bracket.
|
705
|
+
(?<! [a-z0-9<] )
|
706
|
+
|
707
|
+
# Begin capture.
|
708
|
+
(
|
709
|
+
|
710
|
+
# URL must start with one of the acceptable protocols.
|
711
|
+
(?:http|https|ftp|news|file)\:
|
712
|
+
|
713
|
+
# The acceptable URL characters as far as I know.
|
714
|
+
[a-z0-9\-\=\~\@\#\%\&\_\+\/\;\:\?\*\.\,]*
|
715
|
+
|
716
|
+
# The URL characters minus period and comma. If it ends on them, they're probably intended as
|
717
|
+
# punctuation.
|
718
|
+
[a-z0-9\-\=\~\@\#\%\&\_\+\/\;\:\?\*]
|
719
|
+
|
720
|
+
# End capture.
|
721
|
+
)
|
722
|
+
|
723
|
+
# The next character must not be an acceptable character or a closing angle bracket. This will prevent the URL
|
724
|
+
# from ending early just to get a match.
|
725
|
+
(?! [a-z0-9\-\=\~\@\#\%\&\_\+\/\;\:\?\*\>] )
|
726
|
+
|
727
|
+
}
|
728
|
+
|
729
|
+
{"\x1E" . 'url target="' . NaturalDocs::NDMarkup->ConvertAmpChars($1) . '" '
|
730
|
+
. 'name="' . NaturalDocs::NDMarkup->ConvertAmpChars($1) . '"' . "\x1F"}igxe;
|
731
|
+
|
732
|
+
|
733
|
+
# Find image links. Inline images should already be pulled out by now.
|
734
|
+
|
735
|
+
$text =~ s{(\( *see +)([^\)]+?)( *\))}
|
736
|
+
{"\x1E" . 'img mode="link" target="' . NaturalDocs::NDMarkup->ConvertAmpChars($2) . '" '
|
737
|
+
. 'original="' . NaturalDocs::NDMarkup->ConvertAmpChars($1 . $2 . $3) . '"' . "\x1F"}gie;
|
738
|
+
|
739
|
+
|
740
|
+
|
741
|
+
# Split the text from the potential tags.
|
742
|
+
|
743
|
+
my @tempTextBlocks = split(/([\*_<>\x1E\x1F])/, $text);
|
744
|
+
|
745
|
+
# Since the symbols are considered dividers, empty strings could appear between two in a row or at the beginning/end of the
|
746
|
+
# array. This could seriously screw up TagType(), so we need to get rid of them.
|
747
|
+
my @textBlocks;
|
748
|
+
|
749
|
+
while (scalar @tempTextBlocks)
|
750
|
+
{
|
751
|
+
my $tempTextBlock = shift @tempTextBlocks;
|
752
|
+
|
753
|
+
if (length $tempTextBlock)
|
754
|
+
{ push @textBlocks, $tempTextBlock; };
|
755
|
+
};
|
756
|
+
|
757
|
+
|
758
|
+
my $bold;
|
759
|
+
my $underline;
|
760
|
+
my $underlineHasWhitespace;
|
761
|
+
|
762
|
+
my $index = 0;
|
763
|
+
|
764
|
+
while ($index < scalar @textBlocks)
|
765
|
+
{
|
766
|
+
if ($textBlocks[$index] eq "\x1E")
|
767
|
+
{
|
768
|
+
$output .= '<';
|
769
|
+
$index++;
|
770
|
+
|
771
|
+
while ($textBlocks[$index] ne "\x1F")
|
772
|
+
{
|
773
|
+
$output .= $textBlocks[$index];
|
774
|
+
$index++;
|
775
|
+
};
|
776
|
+
|
777
|
+
$output .= '>';
|
778
|
+
}
|
779
|
+
|
780
|
+
elsif ($textBlocks[$index] eq '<' && $self->TagType(\@textBlocks, $index) == POSSIBLE_OPENING_TAG)
|
781
|
+
{
|
782
|
+
my $endingIndex = $self->ClosingTag(\@textBlocks, $index, undef);
|
783
|
+
|
784
|
+
if ($endingIndex != -1)
|
785
|
+
{
|
786
|
+
my $linkText;
|
787
|
+
$index++;
|
788
|
+
|
789
|
+
while ($index < $endingIndex)
|
790
|
+
{
|
791
|
+
$linkText .= $textBlocks[$index];
|
792
|
+
$index++;
|
793
|
+
};
|
794
|
+
# Index will be incremented again at the end of the loop.
|
795
|
+
|
796
|
+
$linkText = NaturalDocs::NDMarkup->ConvertAmpChars($linkText);
|
797
|
+
|
798
|
+
if ($linkText =~ /^(?:mailto\:)?((?:[a-z0-9\-_]+\.)*[a-z0-9\-_]+@(?:[a-z0-9\-]+\.)+[a-z]{2,4})$/i)
|
799
|
+
{ $output .= '<email target="' . $1 . '" name="' . $1 . '">'; }
|
800
|
+
elsif ($linkText =~ /^(?:http|https|ftp|news|file)\:/i)
|
801
|
+
{ $output .= '<url target="' . $linkText . '" name="' . $linkText . '">'; }
|
802
|
+
else
|
803
|
+
{ $output .= '<link target="' . $linkText . '" name="' . $linkText . '" original="<' . $linkText . '>">'; };
|
804
|
+
}
|
805
|
+
|
806
|
+
else # it's not a link.
|
807
|
+
{
|
808
|
+
$output .= '<';
|
809
|
+
};
|
810
|
+
}
|
811
|
+
|
812
|
+
elsif ($textBlocks[$index] eq '*')
|
813
|
+
{
|
814
|
+
my $tagType = $self->TagType(\@textBlocks, $index);
|
815
|
+
|
816
|
+
if ($tagType == POSSIBLE_OPENING_TAG && $self->ClosingTag(\@textBlocks, $index, undef) != -1)
|
817
|
+
{
|
818
|
+
# ClosingTag() makes sure tags aren't opened multiple times in a row.
|
819
|
+
$bold = 1;
|
820
|
+
$output .= '<b>';
|
821
|
+
}
|
822
|
+
elsif ($bold && $tagType == POSSIBLE_CLOSING_TAG)
|
823
|
+
{
|
824
|
+
$bold = undef;
|
825
|
+
$output .= '</b>';
|
826
|
+
}
|
827
|
+
else
|
828
|
+
{
|
829
|
+
$output .= '*';
|
830
|
+
};
|
831
|
+
}
|
832
|
+
|
833
|
+
elsif ($textBlocks[$index] eq '_')
|
834
|
+
{
|
835
|
+
my $tagType = $self->TagType(\@textBlocks, $index);
|
836
|
+
|
837
|
+
if ($tagType == POSSIBLE_OPENING_TAG && $self->ClosingTag(\@textBlocks, $index, \$underlineHasWhitespace) != -1)
|
838
|
+
{
|
839
|
+
# ClosingTag() makes sure tags aren't opened multiple times in a row.
|
840
|
+
$underline = 1;
|
841
|
+
#underlineHasWhitespace is set by ClosingTag().
|
842
|
+
$output .= '<u>';
|
843
|
+
}
|
844
|
+
elsif ($underline && $tagType == POSSIBLE_CLOSING_TAG)
|
845
|
+
{
|
846
|
+
$underline = undef;
|
847
|
+
#underlineHasWhitespace will be reset by the next opening underline.
|
848
|
+
$output .= '</u>';
|
849
|
+
}
|
850
|
+
elsif ($underline && !$underlineHasWhitespace)
|
851
|
+
{
|
852
|
+
# If there's no whitespace between underline tags, all underscores are replaced by spaces so
|
853
|
+
# _some_underlined_text_ becomes <u>some underlined text</u>. The standard _some underlined text_
|
854
|
+
# will work too.
|
855
|
+
$output .= ' ';
|
856
|
+
}
|
857
|
+
else
|
858
|
+
{
|
859
|
+
$output .= '_';
|
860
|
+
};
|
861
|
+
}
|
862
|
+
|
863
|
+
else # plain text or a > that isn't part of a link
|
864
|
+
{
|
865
|
+
$output .= NaturalDocs::NDMarkup->ConvertAmpChars($textBlocks[$index]);
|
866
|
+
};
|
867
|
+
|
868
|
+
$index++;
|
869
|
+
};
|
870
|
+
|
871
|
+
return $output;
|
872
|
+
};
|
873
|
+
|
874
|
+
|
875
|
+
#
|
876
|
+
# Function: TagType
|
877
|
+
#
|
878
|
+
# Returns whether the tag is a possible opening or closing tag, or neither. "Possible" because it doesn't check if an opening tag is
|
879
|
+
# closed or a closing tag is opened, just whether the surrounding characters allow it to be a candidate for a tag. For example, in
|
880
|
+
# "A _B" the underscore is a possible opening underline tag, but in "A_B" it is not. Support function for <RichFormatTextBlock()>.
|
881
|
+
#
|
882
|
+
# Parameters:
|
883
|
+
#
|
884
|
+
# textBlocks - A reference to an array of text blocks.
|
885
|
+
# index - The index of the tag.
|
886
|
+
#
|
887
|
+
# Returns:
|
888
|
+
#
|
889
|
+
# POSSIBLE_OPENING_TAG, POSSIBLE_CLOSING_TAG, or NOT_A_TAG.
|
890
|
+
#
|
891
|
+
sub TagType #(textBlocks, index)
|
892
|
+
{
|
893
|
+
my ($self, $textBlocks, $index) = @_;
|
894
|
+
|
895
|
+
|
896
|
+
# Possible opening tags
|
897
|
+
|
898
|
+
if ( ( $textBlocks->[$index] =~ /^[\*_<]$/ ) &&
|
899
|
+
|
900
|
+
# Before it must be whitespace, the beginning of the text, or ({["'-/*_.
|
901
|
+
( $index == 0 || $textBlocks->[$index-1] =~ /[\ \t\n\(\{\[\"\'\-\/\*\_]$/ ) &&
|
902
|
+
|
903
|
+
# Notes for 2.0: Include Spanish upside down ! and ? as well as opening quotes (66) and apostrophes (6). Look into
|
904
|
+
# Unicode character classes as well.
|
905
|
+
|
906
|
+
# After it must be non-whitespace.
|
907
|
+
( $index + 1 < scalar @$textBlocks && $textBlocks->[$index+1] !~ /^[\ \t\n]/) &&
|
908
|
+
|
909
|
+
# Make sure we don't accept <<, <=, <-, or *= as opening tags.
|
910
|
+
( $textBlocks->[$index] ne '<' || $textBlocks->[$index+1] !~ /^[<=-]/ ) &&
|
911
|
+
( $textBlocks->[$index] ne '*' || $textBlocks->[$index+1] !~ /^[\=\*]/ ) &&
|
912
|
+
|
913
|
+
# Make sure we don't accept * or _ before it unless it's <.
|
914
|
+
( $textBlocks->[$index] eq '<' || $index == 0 || $textBlocks->[$index-1] !~ /[\*\_]$/) )
|
915
|
+
{
|
916
|
+
return POSSIBLE_OPENING_TAG;
|
917
|
+
}
|
918
|
+
|
919
|
+
|
920
|
+
# Possible closing tags
|
921
|
+
|
922
|
+
elsif ( ( $textBlocks->[$index] =~ /^[\*_>]$/) &&
|
923
|
+
|
924
|
+
# After it must be whitespace, the end of the text, or )}].,!?"';:-/*_.
|
925
|
+
( $index + 1 == scalar @$textBlocks || $textBlocks->[$index+1] =~ /^[ \t\n\)\]\}\.\,\!\?\"\'\;\:\-\/\*\_]/ ||
|
926
|
+
# Links also get plurals, like <link>s, <linx>es, <link>'s, and <links>'.
|
927
|
+
( $textBlocks->[$index] eq '>' && $textBlocks->[$index+1] =~ /^(?:es|s|\')/ ) ) &&
|
928
|
+
|
929
|
+
# Notes for 2.0: Include closing quotes (99) and apostrophes (9). Look into Unicode character classes as well.
|
930
|
+
|
931
|
+
# Before it must be non-whitespace.
|
932
|
+
( $index != 0 && $textBlocks->[$index-1] !~ /[ \t\n]$/ ) &&
|
933
|
+
|
934
|
+
# Make sure we don't accept >>, ->, or => as closing tags. >= is already taken care of.
|
935
|
+
( $textBlocks->[$index] ne '>' || $textBlocks->[$index-1] !~ /[>=-]$/ ) &&
|
936
|
+
|
937
|
+
# Make sure we don't accept * or _ after it unless it's >.
|
938
|
+
( $textBlocks->[$index] eq '>' || $textBlocks->[$index+1] !~ /[\*\_]$/) )
|
939
|
+
{
|
940
|
+
return POSSIBLE_CLOSING_TAG;
|
941
|
+
}
|
942
|
+
|
943
|
+
else
|
944
|
+
{
|
945
|
+
return NOT_A_TAG;
|
946
|
+
};
|
947
|
+
|
948
|
+
};
|
949
|
+
|
950
|
+
|
951
|
+
#
|
952
|
+
# Function: ClosingTag
|
953
|
+
#
|
954
|
+
# Returns whether a tag is closed or not, where it's closed if it is, and optionally whether there is any whitespace between the
|
955
|
+
# tags. Support function for <RichFormatTextBlock()>.
|
956
|
+
#
|
957
|
+
# The results of this function are in full context, meaning that if it says a tag is closed, it can be interpreted as that tag in the
|
958
|
+
# final output. It takes into account any spoiling factors, like there being two opening tags in a row.
|
959
|
+
#
|
960
|
+
# Parameters:
|
961
|
+
#
|
962
|
+
# textBlocks - A reference to an array of text blocks.
|
963
|
+
# index - The index of the opening tag.
|
964
|
+
# hasWhitespaceRef - A reference to the variable that will hold whether there is whitespace between the tags or not. If
|
965
|
+
# undef, the function will not check. If the tag is not closed, the variable will not be changed.
|
966
|
+
#
|
967
|
+
# Returns:
|
968
|
+
#
|
969
|
+
# If the tag is closed, it returns the index of the closing tag and puts whether there was whitespace between the tags in
|
970
|
+
# hasWhitespaceRef if it was specified. If the tag is not closed, it returns -1 and doesn't touch the variable pointed to by
|
971
|
+
# hasWhitespaceRef.
|
972
|
+
#
|
973
|
+
sub ClosingTag #(textBlocks, index, hasWhitespace)
|
974
|
+
{
|
975
|
+
my ($self, $textBlocks, $index, $hasWhitespaceRef) = @_;
|
976
|
+
|
977
|
+
my $hasWhitespace;
|
978
|
+
my $closingTag;
|
979
|
+
|
980
|
+
if ($textBlocks->[$index] eq '*' || $textBlocks->[$index] eq '_')
|
981
|
+
{ $closingTag = $textBlocks->[$index]; }
|
982
|
+
elsif ($textBlocks->[$index] eq '<')
|
983
|
+
{ $closingTag = '>'; }
|
984
|
+
else
|
985
|
+
{ return -1; };
|
986
|
+
|
987
|
+
my $beginningIndex = $index;
|
988
|
+
$index++;
|
989
|
+
|
990
|
+
while ($index < scalar @$textBlocks)
|
991
|
+
{
|
992
|
+
if ($textBlocks->[$index] eq '<' && $self->TagType($textBlocks, $index) == POSSIBLE_OPENING_TAG)
|
993
|
+
{
|
994
|
+
# If we hit a < and we're checking whether a link is closed, it's not. The first < becomes literal and the second one
|
995
|
+
# becomes the new link opening.
|
996
|
+
if ($closingTag eq '>')
|
997
|
+
{
|
998
|
+
return -1;
|
999
|
+
}
|
1000
|
+
|
1001
|
+
# If we're not searching for the end of a link, we have to skip the link because formatting tags cannot appear within
|
1002
|
+
# them. That's of course provided it's closed.
|
1003
|
+
else
|
1004
|
+
{
|
1005
|
+
my $linkHasWhitespace;
|
1006
|
+
|
1007
|
+
my $endIndex = $self->ClosingTag($textBlocks, $index,
|
1008
|
+
($hasWhitespaceRef && !$hasWhitespace ? \$linkHasWhitespace : undef) );
|
1009
|
+
|
1010
|
+
if ($endIndex != -1)
|
1011
|
+
{
|
1012
|
+
if ($linkHasWhitespace)
|
1013
|
+
{ $hasWhitespace = 1; };
|
1014
|
+
|
1015
|
+
# index will be incremented again at the end of the loop, which will bring us past the link's >.
|
1016
|
+
$index = $endIndex;
|
1017
|
+
};
|
1018
|
+
};
|
1019
|
+
}
|
1020
|
+
|
1021
|
+
elsif ($textBlocks->[$index] eq $closingTag)
|
1022
|
+
{
|
1023
|
+
my $tagType = $self->TagType($textBlocks, $index);
|
1024
|
+
|
1025
|
+
if ($tagType == POSSIBLE_CLOSING_TAG)
|
1026
|
+
{
|
1027
|
+
# There needs to be something between the tags for them to count.
|
1028
|
+
if ($index == $beginningIndex + 1)
|
1029
|
+
{ return -1; }
|
1030
|
+
else
|
1031
|
+
{
|
1032
|
+
# Success!
|
1033
|
+
|
1034
|
+
if ($hasWhitespaceRef)
|
1035
|
+
{ $$hasWhitespaceRef = $hasWhitespace; };
|
1036
|
+
|
1037
|
+
return $index;
|
1038
|
+
};
|
1039
|
+
}
|
1040
|
+
|
1041
|
+
# If there are two opening tags of the same type, the first becomes literal and the next becomes part of a tag.
|
1042
|
+
elsif ($tagType == POSSIBLE_OPENING_TAG)
|
1043
|
+
{ return -1; }
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
elsif ($hasWhitespaceRef && !$hasWhitespace)
|
1047
|
+
{
|
1048
|
+
if ($textBlocks->[$index] =~ /[ \t\n]/)
|
1049
|
+
{ $hasWhitespace = 1; };
|
1050
|
+
};
|
1051
|
+
|
1052
|
+
$index++;
|
1053
|
+
};
|
1054
|
+
|
1055
|
+
# Hit the end of the text blocks if we're here.
|
1056
|
+
return -1;
|
1057
|
+
};
|
1058
|
+
|
1059
|
+
|
1060
|
+
1;
|