Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Implemented markdown output generator.

  • Loading branch information...
commit 8a491c3776dcf66d7bfa9e65770257f1ad3e189a 1 parent 329b067
@tomaz authored
View
42 CommandLineParser.h
@@ -145,6 +145,9 @@ This is used to generate the actual reference name and is visible on the final o
Note That @c createCleanXHTML() is a prerequisite for documentation set. */
@property(readonly) BOOL createDocSet;
+/** If @c YES, Markdown documentaiton is created. */
+@property(readonly) BOOL createMarkdown;
+
//////////////////////////////////////////////////////////////////////////////////////////
/// @name Properties - XHTML output creation
//////////////////////////////////////////////////////////////////////////////////////////
@@ -184,6 +187,45 @@ set to user's documentation set directory. */
@property(readonly) NSString* docsetInstallPath;
//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Properties - Markdown creation
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/** If @c YES, object files links are created using reference style, otherwise inline
+links are created. */
+@property(readonly) BOOL markdownReferenceStyleLinks;
+
+/** The maximum number of chars to use in one line.
+
+This is the desired maximum line length.
+*/
+@property(readonly) int markdownLineLength;
+
+/** The minimum number of chars in the line before considering wrapping.
+
+This value controls line wrapping when adding non-wrappable phrases. It works in
+pair with @c markdownLineLength() and @c markdownLineWrapMargin().
+
+If the line has less chars than this value, a non-wrappable phrase is still appended if
+the total line length including the phrase is below the sum of @c markdownLineLength() and
+@c markdownLineWrapMargin().
+
+@see markdownLineLength
+*/
+@property(readonly) int markdownLineWrapThreshold;
+
+/** The maximum number of chars to use in one line.
+
+This value controls line wrapping when adding non-wrappable phrases. It works in
+pair with @c markdownLineLength() and @c markdownLineWrapThreshold().
+
+If the line length is below or equal to the threshold, the phrase is added to it even if
+the new line length is over the @c markdownLineLength() however below the given margin.
+
+@see markdownLineLength
+*/
+@property(readonly) int markdownLineWrapMargin;
+
+//////////////////////////////////////////////////////////////////////////////////////////
/// @name Properties - miscellaneous
//////////////////////////////////////////////////////////////////////////////////////////
View
60 CommandLineParser.m
@@ -25,6 +25,7 @@
#define kTKCmdCreateCleanXHTMLKey @"CreateXHTML" // NSNumber / BOOL
#define kTKCmdCreateDocSetKey @"CreateDocSet" // NSNumber / BOOL
+#define kTKCmdCreateMarkdownKey @"CreateMarkdown" // NSNumber / BOOL
#define kTKCmdXHTMLBorderedExamplesKey @"XHTMLUseBorderedExamples" // NSNumber / BOOL
#define kTKCmdXHTMLBorderedWarningsKey @"XHTMLUseBorderedWarnings" // NSNumber / BOOL
@@ -36,6 +37,11 @@
#define kTKCmdDocSetUtilCommandLinKey @"DocSetUtilCommandLine" // NSString
#define kTKCmdDocSetInstallPathKey @"DocSetInstallPath" // NSString
+#define kTKCmdMarkdownRefStyleLinksKey @"MarkdownReferenceStyleLinks" // NSNumber / BOOL
+#define kTKCmdMarkdownLineLengthKey @"MarkdownLineLength" // NSNumber / int
+#define kTKCmdMarkdownLineThresholdKey @"MarkdownLineWrapThreshold" // NSNumber / int
+#define kTKCmdMarkdownLineMarginKey @"MarkdownLineWrapMargin" // NSNumber / int
+
#define kTKCmdFixClassLocationsKey @"FixClassLocations" // NSNumber / BOOL
#define kTKCmdRemoveEmptyParaKey @"RemoveEmptyParagraphs" // NSNumber / BOOL
#define kTKCmdMergeCategoriesKey @"MergeCategories" // NSNumber / BOOL
@@ -342,6 +348,7 @@ - (void) parseCommandLineArguments:(const char**) argv
[self parseBooleanWithShortcut:nil andName:@"--xhtml" withValue:YES forKey:kTKCmdCreateCleanXHTMLKey];
[self parseBooleanWithShortcut:nil andName:@"--docset" withValue:YES forKey:kTKCmdCreateDocSetKey];
+ [self parseBooleanWithShortcut:nil andName:@"--markdown" withValue:YES forKey:kTKCmdCreateMarkdownKey];
[self parseBooleanWithShortcut:nil andName:@"--xhtml-bordered-issues" withValue:YES forKey:kTKCmdXHTMLBorderedExamplesKey];
[self parseBooleanWithShortcut:nil andName:@"--xhtml-bordered-issues" withValue:YES forKey:kTKCmdXHTMLBorderedWarningsKey];
@@ -351,7 +358,12 @@ - (void) parseCommandLineArguments:(const char**) argv
[self parseStringWithShortcut:nil andName:@"--docfeed" forKey:kTKCmdDocSetBundleFeedKey];
[self parseStringWithShortcut:nil andName:@"--docplist" forKey:kTKCmdDocSetSourcePlistKey];
[self parseStringWithShortcut:nil andName:@"--docutil" forKey:kTKCmdDocSetUtilCommandLinKey];
-
+
+ [self parseBooleanWithShortcut:nil andName:@"--markdown-refstyle-links" withValue:YES forKey:kTKCmdMarkdownRefStyleLinksKey];
+ [self parseIntegerWithShortcut:nil andName:@"--markdown-line-length" forKey:kTKCmdMarkdownLineLengthKey];
+ [self parseIntegerWithShortcut:nil andName:@"--markdown-line-threshold" forKey:kTKCmdMarkdownLineThresholdKey];
+ [self parseIntegerWithShortcut:nil andName:@"--markdown-line-margin" forKey:kTKCmdMarkdownLineMarginKey];
+
[self parseStringWithShortcut:nil andName:@"--object-reference-template" forKey:kTKCmdObjectRefTemplate];
[self parseStringWithShortcut:nil andName:@"--member-reference-template" forKey:kTKCmdMemberRefTemplate];
[self parseStringWithShortcut:nil andName:@"--date-time-template" forKey:kTKCmdDateTimeTemplate];
@@ -463,6 +475,7 @@ - (void) printUsage
printf("OPTIONS - clean output creation\n");
printf(" --xhtml\n");
printf(" --docset\n");
+ printf(" --markdown\n");
printf("\n");
printf("OPTIONS - XHTML output creation\n");
printf(" --xhtml-bordered-issues\n");
@@ -473,6 +486,9 @@ - (void) printUsage
printf(" --docplist <path>\n");
printf(" --docutil <path>\n");
printf("\n");
+ printf("OPTIONS - markdown output creation\n");
+ printf(" --markdown-refstyle-links\n");
+ printf("\n");
printf("OPTIONS - miscellaneous\n");
printf(" --object-reference-template\n");
printf(" --member-reference-template\n");
@@ -518,8 +534,16 @@ - (void) setupFactoryDefaults
[parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdMergeCategoriesKey];
[parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdKeepMergedCategoriesSectionsKey];
[parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdRemoveEmptyParaKey];
+
[parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdCreateCleanXHTMLKey];
[parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdCreateDocSetKey];
+ [parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdCreateMarkdownKey];
+
+ [parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdMarkdownRefStyleLinksKey];
+ [parameters setObject:[NSNumber numberWithInt:80] forKey:kTKCmdMarkdownLineLengthKey];
+ [parameters setObject:[NSNumber numberWithInt:7] forKey:kTKCmdMarkdownLineThresholdKey];
+ [parameters setObject:[NSNumber numberWithInt:12] forKey:kTKCmdMarkdownLineMarginKey];
+
[parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdCleanTempFilesKey];
[parameters setObject:[NSNumber numberWithBool:NO] forKey:kTKCmdCleanBeforeBuildKey];
@@ -865,6 +889,12 @@ - (BOOL) createDocSet
return [[parameters objectForKey:kTKCmdCreateDocSetKey] boolValue];
}
+//----------------------------------------------------------------------------------------
+- (BOOL) createMarkdown
+{
+ return [[parameters objectForKey:kTKCmdCreateMarkdownKey] boolValue];
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Properties - XHTML creation
//////////////////////////////////////////////////////////////////////////////////////////
@@ -930,6 +960,34 @@ - (NSString*) docsetInstallPath
}
//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Properties - Markdown creation
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (BOOL) markdownReferenceStyleLinks
+{
+ return [[parameters objectForKey:kTKCmdMarkdownRefStyleLinksKey] boolValue];
+}
+
+//----------------------------------------------------------------------------------------
+- (int) markdownLineLength
+{
+ return [[parameters objectForKey:kTKCmdMarkdownLineLengthKey] intValue];
+}
+
+//----------------------------------------------------------------------------------------
+- (int) markdownLineWrapThreshold
+{
+ return [[parameters objectForKey:kTKCmdMarkdownLineThresholdKey] intValue];
+}
+
+//----------------------------------------------------------------------------------------
+- (int) markdownLineWrapMargin
+{
+ return [[parameters objectForKey:kTKCmdMarkdownLineMarginKey] intValue];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
#pragma mark Properties - miscellaneous
//////////////////////////////////////////////////////////////////////////////////////////
View
4 DoxygenConverter.m
@@ -14,6 +14,7 @@
#import "DoxygenOutputGenerator.h"
#import "XMLOutputGenerator.h"
+#import "MarkdownOutputGenerator.h"
#import "XHTMLOutputGenerator.h"
#import "DocSetOutputGenerator.h"
@@ -35,12 +36,14 @@ - (id)init
// Setup all output generators.
DoxygenOutputGenerator* doxygenGenerator = [[DoxygenOutputGenerator alloc] initWithDatabase:database];
XMLOutputGenerator* xmlGenerator = [[XMLOutputGenerator alloc] initWithDatabase:database];
+ MarkdownOutputGenerator* markdownGenerator = [[MarkdownOutputGenerator alloc] initWithDatabase:database];
XHTMLOutputGenerator* xhtmlGenerator = [[XHTMLOutputGenerator alloc] initWithDatabase:database];
DocSetOutputGenerator* docSetGenerator = [[DocSetOutputGenerator alloc] initWithDatabase:database];
// Setup all dependencies.
[doxygenGenerator registerDependentGenerator:xmlGenerator];
[xmlGenerator registerDependentGenerator:xhtmlGenerator];
+ [xmlGenerator registerDependentGenerator:markdownGenerator];
[xhtmlGenerator registerDependentGenerator:docSetGenerator];
xmlGenerator.doxygenInfoProvider = doxygenGenerator;
docSetGenerator.documentationFilesInfoProvider = xhtmlGenerator;
@@ -52,6 +55,7 @@ - (id)init
// We can now release generators because they are retained by their parents.
[doxygenGenerator release];
[xmlGenerator release];
+ [markdownGenerator release];
[xhtmlGenerator release];
[docSetGenerator release];
}
View
2  LoggingProvider.h
@@ -165,7 +165,7 @@ the moment, I cannot use lorem ipsum for that. And I also don't know it from the
There's much more important stuff to remember than that... Except for the cases like this
where the text is actually needed. Well, looks like my imagination is still working...
-Here's an example of how to get @b strong or @a emphasized items.
+Here's an example of how to get @b strong or @a emphasized words.
@param param The parameter.
@param value The value.
View
319 MarkdownOutputGenerator.h
@@ -0,0 +1,319 @@
+//
+// MarkdownOutputGenerator.h
+// appledoc
+//
+// Created by Tomaz Kragelj on 28.5.09.
+// Copyright (C) 2009, Tomaz Kragelj. All rights reserved.
+//
+
+#import "XMLBasedOutputGenerator.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+/** Defines a concrete @c XMLBasedOutputGenerator that generates Markdown output.
+
+Basically this produces text files which are fairly readable for humans and can be
+converted to simple HTML as a bonus (although @c XHTMLOutputGenerator is probably a
+better HTML output generator solution if HTML is the desired output). See
+http://daringfireball.net/projects/markdown for details on Markdown syntax.
+*/
+@interface MarkdownOutputGenerator : XMLBasedOutputGenerator
+{
+ NSMutableDictionary* linkReferences;
+ NSString* descriptionBlockPrefix;
+ NSString* descriptionBlockSuffix;
+ NSString* descriptionBlockLinePrefix;
+ BOOL descriptionBlockPrefixFirstLine;
+ BOOL descriptionDelimitSingleParameters;
+ BOOL descriptionDelimitLastParameter;
+ BOOL descriptionMarkEmphasis;
+ int descriptionBlockLineCount;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Object member helpers
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/** Appends the given member title.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberTitleToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member overview description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberOverviewToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member prototype description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberPrototypeToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member section type description.
+
+The type should be one of the following:
+- @c kTKObjectMemberSectionParameters: The array of all parameters will be returned.
+- @c kTKObjectMemberSectionExceptions: The array of all exceptions will be returned.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@param type The member section type.
+@param title The desired section title.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberSectionToData:(NSMutableData*) data
+ fromItem:(id) item
+ type:(int) type
+ title:(NSString*) title;
+
+/** Appends the given member return description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberReturnToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member discussion description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberDiscussionToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member warning description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberWarningToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member bug description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberBugToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member see also section description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberSeeAlsoToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the given member declaration file description.
+
+@param data The data to append to.
+@param item The member item to get information from.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendObjectMemberFileToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Description helpers
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/** Appends the brief description to the given data.
+
+First the brief description is retreived from the given node, then the data from the
+retreived nodes is converted to a proper Markdown format and is then appended to the end
+of the given data.
+
+Note that the generated output is affected by object's description variables and flags.
+@c resetDescriptionVarsToDefaults() can be used to reset these to defaults. See
+See @c resetDescriptionVarsToDefaults for the list of the variables and their meanings.
+
+@param data The data to append to.
+@param item The description item which brief subcsection to append.
+@exception NSException Thrown if appending fails.
+@see appendDetailedDescriptionToData:fromItem:
+@see appendDescriptionToData:fromDescriptionItems:
+@see resetDescriptionVarsToDefaults
+*/
+- (void) appendBriefDescriptionToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Appends the detailed description to the given data.
+
+First the detailed description is retreived from the given node, then the data from the
+retreived nodes is converted to a proper Markdown format and is then appended to the end
+of the given data.
+
+Note that the generated output is affected by object's description variables and flags.
+@c resetDescriptionVarsToDefaults() can be used to reset these to defaults. See
+See @c resetDescriptionVarsToDefaults for the list of the variables and their meanings.
+
+@param data The data to append to.
+@param item The description item which detailed subcsection to append.
+@exception NSException Thrown if appending fails.
+@see appendBriefDescriptionToData:fromItem:
+@see appendDescriptionToData:fromDescriptionItems:
+@see resetDescriptionVarsToDefaults
+*/
+- (void) appendDetailedDescriptionToData:(NSMutableData*) data
+ fromItem:(id) item;
+
+/** Converts the description data from the given paragraph to proper Markdown format and
+appends it to the given data.
+
+Note that the generated output is affected by object's description variables and flags.
+@c resetDescriptionVarsToDefaults() can be used to reset these to defaults. See
+See @c resetDescriptionVarsToDefaults for the list of the variables and their meanings.
+
+@param data The data to append to.
+@param items The array of description items which data to convert. If @c nil nothing happens.
+@exception NSException Thrown if convertion fails.
+@see appendBriefDescriptionToData:fromItem:
+@see appendDetailedDescriptionToData:fromItem:
+@see appendParagraphToData:fromString:
+@see resetDescriptionVarsToDefaults
+*/
+- (void) appendDescriptionToData:(NSMutableData*) data
+ fromDescriptionItems:(NSArray*) items;
+
+/** Appends the given string containing a paragraph text to the given data.
+
+This method cleans the output and takes care of formatting the text to fit to the desired
+line width. It is sent automatically from @c appendDescriptionToData:fromDescriptionItems:()
+and is not meant to be used otherwise.
+
+Note that this only appends the given paragraph text, it doesn't delimit the paragraph
+with an empty line and doesn't end the paragraph with a new line either.
+
+@param data The data to append to.
+@param string The paragraph text.
+@param prefix The prefix to append before each line.
+@param wrap If @c YES, paragraph text should be wrapped according to wrapping options,
+ otherwise not.
+@exception NSException Thrown if appending fails.
+@see appendDescriptionToData:fromDescriptionItems:
+*/
+- (void) appendParagraphToData:(NSMutableData*) data
+ fromString:(NSString*) string
+ linePrefix:(NSString*) prefix
+ wrap:(BOOL) wrap;
+
+/** Resets all description variables to default values.
+
+The description variables and their default values are:
+- @c descriptionDelimitSingleParameters: A boolean value indicating whether single
+ parameters should be delimited by a new line or not. If @c YES, all parameters are
+ delimited, if @c NO, parameters are delimited by a new line only if two or more are
+ detected. Defaults to @c YES.
+- @c descriptionDelimitLastParameter: A boolean value indicating whether last parameter
+ should be delimited by a new line or not. Note that if this is set to @c NO, the
+ @c descriptionDelimitSingleParameters has no effect. Defaults to @c YES.
+- @c descriptionMarkEmphasis: A boolean value indicating whether strong and emphasis
+ markers should be used or not. Defaults to @c YES.
+
+@see appendBriefDescriptionToData:fromItem:
+@see appendDetailedDescriptionToData:fromItem:
+@see appendDescriptionToData:fromDescriptionItems:
+*/
+- (void) resetDescriptionVarsToDefaults;
+
+//////////////////////////////////////////////////////////////////////////////////////////
+/// @name Helper methods
+//////////////////////////////////////////////////////////////////////////////////////////
+
+/** Appends the header of the given level for the given string.
+
+Depending of the settings, this creates properly formatted header for the given string.
+Afterwards it automatically adds one empty line.
+
+@param data The data to append to.
+@param string The header string.
+@param level The header level. Should be between @c 1 and @c 10.
+@exception NSException Thrown if the given level is not within expected range or appending fails.
+*/
+- (void) appendHeaderToData:(NSMutableData*) data
+ forString:(NSString*) string
+ level:(int) level;
+
+/** Appends the underline data for the given string.
+
+This is mostly used for generating underlines for the titles. Note that nothing will be
+output if the given @c string or @c underline are @c nil or empty strings.
+
+@param data The data to append to.
+@param string The string which should be underlines.
+@param underline The underline string. Should only contain 1 char!
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendUnderlineToData:(NSMutableData*) data
+ forString:(NSString*) string
+ underline:(NSString*) underline;
+
+/** Appends link to the given data.
+
+Depending on the style this either appends the link ID and the reference to the footnote
+or the actual link. If @c nil is passed for the reference, the method appends only the
+given description. However @c description may not be @c nil in such case.
+
+@param data The data to append to.
+@param reference The link reference. May be @c nil to only use the description.
+@param description The link description. May be @c nil to use the reference.
+@exception NSException Thrown if the @c reference and the @c description are @c nil or
+ appending fails.
+*/
+- (void) appendLinkToData:(NSMutableData*) data
+ fromReference:(NSString*) reference
+ andDescription:(NSString*) description;
+
+/** Appends all link footnotes to the given data.
+
+This message should be sent after handling the file is complete and all references
+are in the temporary array. This method will output the actual links as footnote
+markdown style if necessary. If footnote links are disabled or there is no reference
+for the current object, nothing happens.
+
+@param data The data to append to.
+@exception NSException Thrown if appending fails.
+*/
+- (void) appendLinkFootnotesToData:(NSMutableData*) data;
+
+/** Formats a link from the given data.
+
+Depending on the style this either formats the link as the reference to the footnote or
+the actual link. If @c nil is passed for the reference, the method appends only the
+given description. However @c description may not be @c nil in such case.
+
+Note that if the given reference points to the object's member, the link is not generated.
+Instead only the member name is emmited.
+
+Note that in case footnote style is used, the receiver's footnote index is automatically
+incremented if necessary.
+
+@param reference The link reference. May be @c nil to only use the description.
+@param description The link description. May be @c nil to use the reference.
+@return Returns the formatted link.
+@exception NSException Thrown if the @c reference and the @c description are @c nil or
+ appending fails.
+*/
+- (NSString*) formatLinkFromReference:(NSString*) reference
+ andDescription:(NSString*) description;
+
+@end
View
1,114 MarkdownOutputGenerator.m
@@ -0,0 +1,1114 @@
+//
+// MarkdownOutputGenerator.m
+// appledoc
+//
+// Created by Tomaz Kragelj on 28.5.09.
+// Copyright (C) 2009, Tomaz Kragelj. All rights reserved.
+//
+
+#import "MarkdownOutputGenerator.h"
+#import "XMLBasedOutputGenerator+GeneralParsingAPI.h"
+#import "XMLBasedOutputGenerator+ObjectParsingAPI.h"
+#import "XMLBasedOutputGenerator+ObjectSubclassAPI.h"
+#import "XMLBasedOutputGenerator+IndexParsingAPI.h"
+#import "XMLBasedOutputGenerator+IndexSubclassAPI.h"
+#import "XMLBasedOutputGenerator+HierarchyParsingAPI.h"
+#import "XMLBasedOutputGenerator+HierarchySubclassAPI.h"
+#import "Systemator.h"
+#import "LoggingProvider.h"
+#import "CommandLineParser.h"
+#import "DoxygenConverter.h"
+
+@implementation MarkdownOutputGenerator
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Initialization & disposal
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (id) initWithDatabase:(NSMutableDictionary*) data
+{
+ self = [super initWithDatabase:data];
+ if (self)
+ {
+ linkReferences = [[NSMutableDictionary alloc] init];
+ [self resetDescriptionVarsToDefaults];
+ }
+ return self;
+}
+
+//----------------------------------------------------------------------------------------
+- (void) dealloc
+{
+ [linkReferences release], linkReferences = nil;
+ [super dealloc];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark OutputInfoProvider protocol implementation
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (NSString*) outputFilesExtension
+{
+ return @".markdown";
+}
+
+//----------------------------------------------------------------------------------------
+- (NSString*) outputReferencesExtension
+{
+ return @".html";
+}
+
+//----------------------------------------------------------------------------------------
+- (NSString*) outputBasePath
+{
+ return [cmd.outputPath stringByAppendingPathComponent:@"markdown"];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Specific output generation entry points
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (BOOL) isOutputGenerationEnabled
+{
+ return cmd.createMarkdown;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Object file header and footer handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectHeaderToData:(NSMutableData*) data
+{
+ [linkReferences removeAllObjects];
+ [self appendHeaderToData:data forString:self.objectTitle level:1];
+ [self appendLine:@"" toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectFooterToData:(NSMutableData*) data
+{
+ // Append horizontal rule.
+ [self appendLine:@"- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -"
+ toData:data];
+
+ // Append last updated text with spaces at the end so line break is created.
+ [self appendString:self.lastUpdated toData:data];
+ [self appendLine:@" " toData:data];
+
+ // Append back to links.
+ [self appendString:@"Back to " toData:data];
+ [self appendLinkToData:data fromReference:[self outputIndexFilename] andDescription:@"Index"];
+ [self appendString:@" / " toData:data];
+ [self appendLinkToData:data fromReference:[self outputHierarchyFilename] andDescription:@"Hieararchy"];
+ [self appendLine:@"." toData:data];
+
+ // Append the links.
+ [self appendLinkFootnotesToData:data];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Object info table handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectInfoItemToData:(NSMutableData*) data
+ fromItems:(NSArray*) items
+ index:(int) index
+ type:(int) type;
+{
+ // Prepare the description and the delimiter. Note that the description already
+ // contains all spaces that align the data afterwards.
+ NSString* description = nil;
+ NSString* delimiter = nil;
+ NSString* formatter = nil;
+ switch (type)
+ {
+ case kTKObjectInfoItemInherits:
+ description = @"Inherits from: ";
+ delimiter = @" : ";
+ formatter = @"`";
+ break;
+ case kTKObjectInfoItemConforms:
+ description = @"Conforms to: ";
+ delimiter = @", ";
+ formatter = @"`";
+ break;
+ case kTKObjectInfoItemDeclared:
+ description = @"Declared in: ";
+ delimiter = @", ";
+ formatter = @"";
+ break;
+ }
+
+ // Append the line marker followed by the description.
+ [self appendString:@"* " toData:data];
+ [self appendString:description toData:data];
+
+ // Append all items.
+ for (int i = 0; i < [items count]; i++)
+ {
+ id item = [items objectAtIndex:i];
+ NSString* reference = [self extractObjectInfoItemRef:item];
+ NSString* value = [self extractObjectInfoItemValue:item];
+
+ // If the item is known, we should append it as a reference, otherwise as
+ // normal text.
+ if (!reference)
+ {
+ [self appendString:formatter toData:data];
+ [self appendString:value toData:data];
+ [self appendString:formatter toData:data];
+ }
+ else
+ {
+ [self appendLinkToData:data fromReference:reference andDescription:value];
+ }
+
+
+ // If there's more elements, append delimiter after each except last one.
+ if (i < [items count] - 1) [self appendString:delimiter toData:data];
+ }
+
+ // Finish with a new line.
+ [self appendLine:@"" toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectInfoFooterToData:(NSMutableData*) data
+{
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Object overview handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectOverviewToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ [self appendHeaderToData:data forString:@"Overview" level:2];
+ [self appendLine:@"" toData:data];
+
+ [self resetDescriptionVarsToDefaults];
+ [self appendBriefDescriptionToData:data fromItem:item];
+ [self appendDetailedDescriptionToData:data fromItem:item];
+
+ [self appendLine:@"" toData:data];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Object tasks handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectTasksHeaderToData:(NSMutableData*) data
+{
+ [self appendHeaderToData:data forString:@"Tasks" level:2];
+ [self appendLine:@"" toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectTasksFooterToData:(NSMutableData*) data
+{
+ [self appendLine:@"" toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectTaskHeaderToData:(NSMutableData*) data
+ fromItem:(id) item
+ index:(int) index
+{
+ [self appendHeaderToData:data forString:[self extractObjectTaskName:item] level:3];
+ [self appendLine:@"" toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectTaskMemberToData:(NSMutableData*) data
+ fromItem:(id) item
+ index:(int) index
+{
+ // Append list item marker.
+ [self appendString:@"*\t" toData:data];
+
+ // Append the name of the method or property.
+ [self appendString:@"`" toData:data];
+ [self appendString:[self extractObjectMemberName:item] toData:data];
+ [self appendLine:@"`" toData:data];
+
+ // Append brief description in the second line. Make sure it is properly indented.
+ [self appendString:@"\t" toData:data];
+ [self resetDescriptionVarsToDefaults];
+ [self appendBriefDescriptionToData:data
+ fromItem:[self extractObjectMemberDescriptionItem:item]];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Object members main documentation handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberGroupHeaderToData:(NSMutableData*) data
+ type:(int) type
+{
+ // Prepare the description.
+ NSString* description = nil;
+ switch (type)
+ {
+ case kTKObjectMemberTypeClass:
+ description = @"Class methods";
+ break;
+ case kTKObjectMemberTypeInstance:
+ description = @"Instance methods";
+ break;
+ default:
+ description = @"Properties";
+ break;
+ }
+
+ // Append the group header. Note that contrary to the rest of the headers which
+ // use a single line gap before the text is appended, group headers use two line
+ // gap to make the first item more distinguishable.
+ [self appendHeaderToData:data forString:description level:2];
+ [self appendLine:@"" toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberGroupFooterToData:(NSMutableData*) data
+ type:(int) type
+{
+ [self appendLine:@"" toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberToData:(NSMutableData*) data
+ fromItem:(id) item
+ index:(int) index
+{
+ [self appendObjectMemberTitleToData:data fromItem:item];
+ [self appendObjectMemberOverviewToData:data fromItem:item];
+ [self appendObjectMemberPrototypeToData:data fromItem:item];
+ [self appendObjectMemberSectionToData:data fromItem:item type:kTKObjectMemberSectionParameters title:@"Parameters"];
+ [self appendObjectMemberSectionToData:data fromItem:item type:kTKObjectMemberSectionExceptions title:@"Exceptions"];
+ [self appendObjectMemberReturnToData:data fromItem:item];
+ [self appendObjectMemberDiscussionToData:data fromItem:item];
+ [self appendObjectMemberWarningToData:data fromItem:item];
+ [self appendObjectMemberBugToData:data fromItem:item];
+ [self appendObjectMemberSeeAlsoToData:data fromItem:item];
+ [self appendObjectMemberFileToData:data fromItem:item];
+ [self appendLine:@"" toData:data];
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Member helpers
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberTitleToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ // Previous member (or header) already appended one empty line, however we want to
+ // delimit each member by two lines so they are more clearly visible in the output.
+ [self appendLine:@"" toData:data];
+ [self appendHeaderToData:data forString:[self extractObjectMemberName:item] level:3];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberOverviewToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ // Append the brief description. First get the description item and use it to append
+ // brief description to the output. The description is fully formatted.
+ id descriptionItem = [self extractObjectMemberDescriptionItem:item];
+ if (descriptionItem)
+ {
+ [self resetDescriptionVarsToDefaults];
+ descriptionDelimitSingleParameters = NO;
+ descriptionDelimitLastParameter = NO;
+ [self appendBriefDescriptionToData:data fromItem:descriptionItem];
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberPrototypeToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ // Append the prototype. We need to append an empty line afterwards (after the empty
+ // line which actually ends the prototype line).
+ id prototypeItem = [self extractObjectMemberPrototypeItem:item];
+ if (prototypeItem)
+ {
+ NSArray* items = [self extractObjectMemberPrototypeSubitems:prototypeItem];
+ if (items)
+ {
+ [self appendString:@"\t" toData:data];
+ for (id item in items)
+ {
+ [self appendString:[self extractObjectMemberPrototypeItemValue:item] toData:data];
+ }
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberSectionToData:(NSMutableData*) data
+ fromItem:(id) item
+ type:(int) type
+ title:(NSString*) title
+{
+ NSArray* parameterItems = [self extractObjectMemberSectionItems:item type:type];
+ if (parameterItems)
+ {
+ [self appendHeaderToData:data forString:title level:4];
+ for (id parameterItem in parameterItems)
+ {
+ // Append the section item list marker.
+ [self appendString:@"*\t" toData:data];
+
+ // Append the section name.
+ [self appendString:@"_" toData:data];
+ [self appendString:[self extractObjectParameterName:parameterItem] toData:data];
+ [self appendString:@"_" toData:data];
+
+ // Append the section item description. Since items are displayed as unordered
+ // list, place a tab before each line. However we don't want to prefix the
+ // first line, since we already did that after the item marker above.
+ [self appendString:@" " toData:data];
+ id descriptionItem = [self extractObjectParameterDescriptionItem:parameterItem];
+ if (descriptionItem)
+ {
+ NSArray* descriptions = [self extractDescriptionsFromItem:descriptionItem];
+ [self resetDescriptionVarsToDefaults];
+ descriptionBlockLinePrefix = @"\t";
+ descriptionBlockPrefixFirstLine = NO;
+ descriptionDelimitSingleParameters = NO;
+ descriptionDelimitLastParameter = NO;
+ [self appendDescriptionToData:data fromDescriptionItems:descriptions];
+ }
+
+ // End parameter description paragraph.
+ [self appendLine:@"" toData:data];
+ }
+
+ // Make a one line gap before the next section.
+ [self appendLine:@"" toData:data];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberReturnToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ id returnItem = [self extractObjectMemberReturnItem:item];
+ if (returnItem)
+ {
+ [self appendHeaderToData:data forString:@"Return value" level:4];
+
+ NSArray* descriptions = [self extractDescriptionsFromItem:returnItem];
+ [self resetDescriptionVarsToDefaults];
+ descriptionDelimitSingleParameters = NO;
+ descriptionDelimitLastParameter = NO;
+ [self appendDescriptionToData:data fromDescriptionItems:descriptions];
+
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberDiscussionToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ id descriptionItem = [self extractObjectMemberDescriptionItem:item];
+ if (descriptionItem)
+ {
+ NSArray* descriptions = [self extractDetailDescriptionsFromItem:descriptionItem];
+ if (descriptions && [self isDescriptionUsed:descriptions])
+ {
+ [self appendHeaderToData:data forString:@"Discussion" level:4];
+ [self resetDescriptionVarsToDefaults];
+ [self appendDetailedDescriptionToData:data fromItem:descriptionItem];
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberWarningToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ id warningItem = [self extractObjectMemberWarningItem:item];
+ if (warningItem)
+ {
+ NSArray* descriptions = [self extractDescriptionsFromItem:warningItem];
+
+ [self resetDescriptionVarsToDefaults];
+ descriptionBlockPrefix = @"__";
+ descriptionBlockSuffix = @"__";
+ descriptionDelimitSingleParameters = NO;
+ descriptionDelimitLastParameter = NO;
+ descriptionMarkEmphasis = NO;
+
+ [self appendDescriptionToData:data fromDescriptionItems:descriptions];
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberBugToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ id bugItem = [self extractObjectMemberBugItem:item];
+ if (bugItem)
+ {
+ NSArray* descriptions = [self extractDescriptionsFromItem:bugItem];
+
+ [self resetDescriptionVarsToDefaults];
+ descriptionBlockPrefix = @"__";
+ descriptionBlockSuffix = @"__";
+ descriptionDelimitSingleParameters = NO;
+ descriptionDelimitLastParameter = NO;
+ descriptionMarkEmphasis = NO;
+
+ [self appendDescriptionToData:data fromDescriptionItems:descriptions];
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberSeeAlsoToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ // Note that we only append text, we don't use member references, however we do
+ // use inter-object references.
+ NSArray* items = [self extractObjectMemberSeeAlsoItems:item];
+ if (items)
+ {
+ [self appendHeaderToData:data forString:@"See also" level:4];
+ for (id item in items)
+ {
+ NSString* reference = [self extractDescriptionReference:item];
+ NSString* text = [self extractDescriptionText:item];
+
+ [self appendString:@"*\t" toData:data];
+ [self appendLinkToData:data fromReference:reference andDescription:text];
+ [self appendLine:@"" toData:data];
+ }
+ [self appendLine:@"" toData:data];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendObjectMemberFileToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ NSString* filename = [self extractObjectMemberFile:item];
+ if (filename)
+ {
+ [self appendHeaderToData:data forString:@"Declared in" level:4];
+ [self appendLine:filename toData:data];
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Index file header and footer handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendIndexHeaderToData:(NSMutableData*) data
+{
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendIndexFooterToData:(NSMutableData*) data
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Index groups handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendIndexGroupHeaderToData:(NSMutableData*) data
+ type:(int) type
+{
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendIndexGroupFooterToData:(NSMutableData*) data
+ type:(int) type
+{
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendIndexGroupItemToData:(NSMutableData*) data
+ fromItem:(id) item
+ index:(int) index
+ type:(int) type
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Hierarchy groups handling
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendHierarchyHeaderToData:(NSMutableData*) data
+{
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendHierarchyFooterToData:(NSMutableData*) data
+{
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendHierarchyGroupHeaderToData:(NSMutableData*) data
+{
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendHierarchyGroupFooterToData:(NSMutableData*) data
+{
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendHierarchyGroupItemToData:(NSMutableData*) data
+ fromItem:(id) item
+ index:(int) index
+{
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Description helpers
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendBriefDescriptionToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ NSArray* descriptions = [self extractBriefDescriptionsFromItem:item];
+ [self appendDescriptionToData:data fromDescriptionItems:descriptions];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendDetailedDescriptionToData:(NSMutableData*) data
+ fromItem:(id) item
+{
+ NSArray* descriptions = [self extractDetailDescriptionsFromItem:item];
+ [self appendDescriptionToData:data fromDescriptionItems:descriptions];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendDescriptionToData:(NSMutableData*) data
+ fromDescriptionItems:(NSArray*) items
+{
+ NSMutableString* output = [NSMutableString string];
+ NSString* reference = nil;
+ BOOL handleCodeEnd = YES;
+ int paragraphsCount = 0;
+ descriptionBlockLineCount = 0;
+
+ // Append block prefix.
+ [self appendString:descriptionBlockPrefix toData:data];
+
+ // Append all descriptions.
+ for (id item in items)
+ {
+ int type = [self extractDescriptionType:item];
+ switch (type)
+ {
+ // If a second or greater parameter is detected, we should delimit previous
+ // one, otherwise not. Note that we handle the last parameter after the loop
+ // ends - see code below the for statement below.
+ case kTKDescriptionParagraphStart:
+ if (paragraphsCount >= 1)
+ {
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+ paragraphsCount++;
+ break;
+ case kTKDescriptionParagraphEnd:
+ if ([output length] > 0)
+ {
+ [self appendParagraphToData:data fromString:output linePrefix:@"" wrap:YES];
+ [output setString:@""];
+ }
+ break;
+
+ // Handle the lists. Note that we treat each list item as a paragraph but
+ // without incrementing the paragraph count. When list starts, we finish
+ // current paragraph (if any) and make sure the list is started with one
+ // empty line break. When the list ends, we make sure the list is delimited
+ // by an empty line break before any other text is appended.
+ case kTKDescriptionListStart:
+ if ([output length] > 0)
+ {
+ [self appendParagraphToData:data fromString:output linePrefix:@"" wrap:YES];
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ [output setString:@""];
+ }
+ break;
+ case kTKDescriptionListEnd:
+ [self appendLine:@"" toData:data];
+ break;
+ case kTKDescriptionListItemStart:
+ [output appendString:@"*"];
+ break;
+ case kTKDescriptionListItemEnd:
+ if ([output length] > 0)
+ {
+ [self appendParagraphToData:data fromString:output linePrefix:@"\t" wrap:YES];
+ [self appendLine:@"" toData:data];
+ [output setString:@""];
+ }
+ break;
+
+ // Setup word formatting markers.
+ case kTKDescriptionCodeStart:
+ [output appendString:@"##{"];
+ [output appendString:@"`"];
+ handleCodeEnd = YES;
+ break;
+ case kTKDescriptionCodeEnd:
+ if (handleCodeEnd) [output appendString:@"`"];
+ [output appendString:@"}##"];
+ break;
+ case kTKDescriptionStrongStart:
+ if (descriptionMarkEmphasis) [output appendString:@"*"];
+ break;
+ case kTKDescriptionStrongEnd:
+ if (descriptionMarkEmphasis) [output appendString:@"*"];
+ break;
+ case kTKDescriptionEmphasisStart:
+ if (descriptionMarkEmphasis) [output appendString:@"__"];
+ break;
+ case kTKDescriptionEmphasisEnd:
+ if (descriptionMarkEmphasis) [output appendString:@"__"];
+ break;
+
+ // When starting example, flush current output. When ending example, create
+ // an empty, delimiter, line. Note that we handle example as new paragraph.
+ // If there was a paragraph before, we should append new line before it.
+ // Note that we need to indent each line of the example. Also note that we
+ // need to make sure the example is indented in both cases - if the whole
+ // example is enclosed within kTKDescriptionExampleStart and kTKDescriptionExampleEnd
+ // block (i.e. not part of a paragraph) or the example is part of the paragraph.
+ // In the first case, we only do it if there was a paragraph written before.
+ case kTKDescriptionExampleStart:
+ if ([output length] > 0)
+ {
+ [self appendParagraphToData:data fromString:output linePrefix:@"" wrap:YES];
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ [output setString:@""];
+ }
+ else if (paragraphsCount >= 1)
+ {
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+ break;
+ case kTKDescriptionExampleEnd:
+ if ([output length] > 0)
+ {
+ [self appendParagraphToData:data fromString:output linePrefix:@"\t" wrap:NO];
+ [output setString:@""];
+ }
+ break;
+
+ // When reference is being handled, tread the text as the reference, not
+ // as normal text. Here we only set the flag which we check when text is
+ // reported (see below). Note that we need to remove the code prefix if
+ // used. We handle this manually for references.
+ case kTKDescriptionReferenceStart:
+ if ([output hasSuffix:@"`"])
+ {
+ NSRange range = NSMakeRange([output length] - 1, 1);
+ [output deleteCharactersInRange:range];
+ handleCodeEnd = NO;
+ }
+ reference = [self extractDescriptionReference:item];
+ break;
+ case kTKDescriptionReferenceEnd:
+ reference = nil;
+ break;
+
+ // If we are handling reference, treat the text as the reference, otherwise
+ // treat it as normal text.
+ case kTKDescriptionText: {
+ NSString* value = [self extractDescriptionText:item];
+ if (reference)
+ {
+ value = [self formatLinkFromReference:reference andDescription:value];
+ value = [NSString stringWithFormat:@"##{%@}##", value];
+ }
+ [output appendString:value];
+ } break;
+ }
+ }
+
+ // Append block suffix.
+ [self appendString:descriptionBlockSuffix toData:data];
+
+ // Close the parameter is necessary. We should only delimit the last parameter if
+ // needed. However if there was only one parameter, we should only delimit it if
+ // the flag is set.
+ if (descriptionDelimitLastParameter)
+ {
+ if (paragraphsCount > 1 || descriptionDelimitSingleParameters)
+ {
+ [self appendLine:@"" toData:data];
+ [self appendLine:@"" toData:data];
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendParagraphToData:(NSMutableData*) data
+ fromString:(NSString*) string
+ linePrefix:(NSString*) prefix
+ wrap:(BOOL) wrap
+{
+ // Cleanup double code markers from references. These are added by kTKDescriptionCodeStart
+ // and kTKDescriptionCodeEnd cases and the additional with link generation code. Also
+ // remove starting and trailing new lines - these are dealt with in the "parent" method.
+ NSCharacterSet* newlineSet = [NSCharacterSet newlineCharacterSet];
+ string = [string stringByReplacingOccurrencesOfString:@"##{`##{`" withString:@"##{`"];
+ string = [string stringByReplacingOccurrencesOfString:@"`}##`}##" withString:@"`}##"];
+ string = [string stringByTrimmingCharactersInSet:newlineSet];
+
+ // If no word wrap is desired, just emmit the whole string.
+ if (cmd.markdownLineLength <= 0)
+ {
+ if ([string length] > 0)
+ {
+ if (descriptionBlockLineCount > 0 || descriptionBlockPrefixFirstLine)
+ {
+ [self appendString:descriptionBlockLinePrefix toData:data];
+ [self appendString:prefix toData:data];
+ }
+ [self appendString:string toData:data];
+ descriptionBlockLineCount++;
+ }
+ return;
+ }
+
+ // If we need to wrap words, append words to the line until the line reaches
+ // it's maximum width. At that point append the line and continue with a new.
+ if (wrap)
+ {
+ // Setup the emmiting variables.
+ NSCharacterSet* delimitersSet = [NSCharacterSet whitespaceCharacterSet];
+ NSMutableString* line = [NSMutableString string];
+ NSMutableString* phrase = [NSMutableString string];
+ NSString* word = nil;
+ BOOL canWrap = YES;
+
+ // Append the given paragraph and make sure it fits the maximum line width.
+ NSScanner* scanner = [NSScanner scannerWithString:string];
+ while (![scanner isAtEnd])
+ {
+ if ([scanner scanUpToCharactersFromSet:delimitersSet intoString:&word])
+ {
+ // Don't allow wrapping multiple word code such as method names. However
+ // if the word is too long, we should wrap it to the start of next line.
+ // First we need to add the word to the phrase string which is used
+ // temporarily until all words constituting the phrase are processed.
+ // Then we use the phrase string to see the actual length of the phrase.
+ // Note that we use the actual phrase string to determine if we are in
+ // the middle of the multi-word phrase.
+ BOOL isNonWrapStart = ([word rangeOfString:@"##{"].location != NSNotFound);
+ BOOL isNonWrapEnd = ([word rangeOfString:@"}##"].location != NSNotFound);
+ if (isNonWrapStart) canWrap = NO;
+ if (isNonWrapEnd) canWrap = YES;
+
+ // Remove wrapping prefix and/or suffix.
+ if (isNonWrapStart) word = [word stringByReplacingOccurrencesOfString:@"##{" withString:@""];
+ if (isNonWrapEnd) word = [word stringByReplacingOccurrencesOfString:@"}##" withString:@""];
+
+ // Start the phrase if we detect non-wrap start prefix. If the phrase
+ // string is non-empty, or non-wrap end suffix is detected, append the
+ // word to existing phrase string. Note that we must make sure to append
+ // only if the phrase is not single word (single word phrases have non-wrap
+ // start and end markers present at the same time). Also note that we need
+ // to append a space in between phrase words.
+ if (isNonWrapStart) [phrase setString:word];
+ else if ([phrase length] > 0) [phrase appendFormat:@" %@", word];
+
+ // Finish the line when necessary (if allowed - we postpone this until
+ // non-wrappable phrases are parsed completely).
+ if (canWrap)
+ {
+ // If we just finished the phrase, set it as current word since the
+ // code below uses that for processing (we handle multiple words
+ // non-wrapping phrases as a single words).
+ if ([phrase length] > 0)
+ {
+ word = [phrase copy];
+ [phrase setString:@""];
+ }
+
+ // If the line cannot accomodate the word, break it. Note that we
+ // still allow the line to continue if it is short enough and the
+ // added word keeps it within certain tolerance.
+ int newLineLength = [line length] + [word length];
+ if (newLineLength > cmd.markdownLineLength)
+ {
+ if ([line length] > cmd.markdownLineLength - cmd.markdownLineWrapThreshold ||
+ newLineLength > cmd.markdownLineLength + cmd.markdownLineWrapMargin)
+ {
+ if (descriptionBlockLineCount > 0 || descriptionBlockPrefixFirstLine)
+ {
+ [self appendString:descriptionBlockLinePrefix toData:data];
+ [self appendString:prefix toData:data];
+ }
+ [self appendLine:line toData:data];
+ [line setString:@""];
+ }
+ }
+
+ // Append the word to the line.
+ [line appendString:word];
+ [line appendString:@" "];
+ }
+ }
+ }
+
+ // Append the remaining text.
+ if ([line length] > 0)
+ {
+ if (descriptionBlockLineCount > 0 || descriptionBlockPrefixFirstLine)
+ {
+ [self appendString:descriptionBlockLinePrefix toData:data];
+ [self appendString:prefix toData:data];
+ }
+ [self appendString:line toData:data];
+ }
+ }
+
+ // If non-wrapping mode is desired, get individual lines from the string and prefix
+ // each with global and current prefix.
+ else
+ {
+ NSArray* lines = [string componentsSeparatedByCharactersInSet:newlineSet];
+ for (NSString* line in lines)
+ {
+ [self appendString:descriptionBlockLinePrefix toData:data];
+ [self appendString:prefix toData:data];
+ [self appendLine:line toData:data];
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) resetDescriptionVarsToDefaults
+{
+ descriptionBlockPrefix = @"";
+ descriptionBlockSuffix = @"";
+ descriptionBlockLinePrefix = @"";
+ descriptionBlockPrefixFirstLine = YES;
+ descriptionDelimitSingleParameters = YES;
+ descriptionDelimitLastParameter = YES;
+ descriptionMarkEmphasis = YES;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Helper methods
+//////////////////////////////////////////////////////////////////////////////////////////
+
+//----------------------------------------------------------------------------------------
+- (void) appendHeaderToData:(NSMutableData*) data
+ forString:(NSString*) string
+ level:(int) level
+{
+ NSParameterAssert(level >= 1 && level <= 10);
+
+ // If header level is 3 or greater or atx style should be used for all, prepare the
+ // prefix and suffix string and write it to the data, followed by a space.
+ NSString* headerMarker = nil;
+ if (level >= 3)
+ {
+ // Prepare the string.
+ NSMutableString* marker = [NSMutableString string];
+ for (int i = 0; i < level; i++)
+ {
+ [marker appendString:@"#"];
+ }
+ headerMarker = marker;
+
+ // Write it and append a space.
+ [self appendString:headerMarker toData:data];
+ [self appendString:@" " toData:data];
+ }
+
+ // Write the actual title.
+ [self appendString:string toData:data];
+
+ // Write the suffix or underline.
+ if (level >= 3)
+ {
+ [self appendString:@" " toData:data];
+ [self appendLine:headerMarker toData:data];
+ }
+ else if (level == 2)
+ {
+ [self appendLine:@"" toData:data];
+ [self appendUnderlineToData:data forString:string underline:@"-"];
+ }
+ else if (level == 1)
+ {
+ [self appendLine:@"" toData:data];
+ [self appendUnderlineToData:data forString:string underline:@"="];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendUnderlineToData:(NSMutableData*) data
+ forString:(NSString*) string
+ underline:(NSString*) underline
+{
+ if ([string length] > 0 && [underline length] > 0)
+ {
+ NSMutableString* underlineString = [NSMutableString stringWithCapacity:[string length]];
+ while ([underlineString length] < [string length])
+ {
+ [underlineString appendString:underline];
+ }
+ [self appendLine:underlineString toData:data];
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendLinkToData:(NSMutableData*) data
+ fromReference:(NSString*) reference
+ andDescription:(NSString*) description
+{
+ NSString* link = [self formatLinkFromReference:reference andDescription:description];
+ [self appendString:link toData:data];
+}
+
+//----------------------------------------------------------------------------------------
+- (void) appendLinkFootnotesToData:(NSMutableData*) data
+{
+ if (cmd.markdownReferenceStyleLinks && [linkReferences count] > 0)
+ {
+ [self appendLine:@"" toData:data];
+
+ // Get the dictionary of all footnote numbers and the corresponding data.
+ // Note that we calculate the largest reference length so that we can align
+ // the output better later on.
+ int maxReferenceLength = 0;
+ NSMutableDictionary* numbers = [NSMutableDictionary dictionary];
+ for (NSString* reference in [linkReferences allKeys])
+ {
+ NSDictionary* footnoteData = [linkReferences objectForKey:reference];
+
+ int referenceLength = [[footnoteData objectForKey:@"Reference"] length];
+ if (referenceLength > maxReferenceLength) maxReferenceLength = referenceLength;
+
+ NSNumber* number = [footnoteData objectForKey:@"Number"];
+ [numbers setObject:footnoteData forKey:number];
+ }
+
+ // Prepare the sorted array of all numbers and calculate the greatest number size
+ // again for better alignement later on.
+ NSArray* sortedKeys = [[numbers allKeys] sortedArrayUsingSelector:@selector(compare:)];
+ int maxNumberLength = [[[sortedKeys lastObject] stringValue] length];
+
+ // Emmit all link footnotes sorted by their number.
+ for (NSNumber* number in sortedKeys)
+ {
+ NSDictionary* footnoteData = [numbers objectForKey:number];
+ NSString* numberText = [number stringValue];
+ int length = [numberText length];
+
+ // Right pad numbers.
+ while (length < maxNumberLength)
+ {
+ [self appendString:@" " toData:data];
+ length++;
+ }
+ [self appendString:@"[" toData:data];
+ [self appendString:numberText toData:data];
+ [self appendString:@"]: " toData:data];
+
+ // Append the reference.
+ NSString* reference = [footnoteData objectForKey:@"Reference"];
+ [self appendString:@"<" toData:data];
+ [self appendString:reference toData:data];
+ [self appendString:@"> " toData:data];
+
+ // Pad description so that all are aligned properly - i.e. all start at the
+ // same column.
+ length = [reference length];
+ while (length < maxReferenceLength)
+ {
+ [self appendString:@" " toData:data];
+ length++;
+ }
+ [self appendString:@"\"" toData:data];
+ [self appendString:[footnoteData objectForKey:@"Description"] toData:data];
+ [self appendLine:@"\"" toData:data];
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------
+- (NSString*) formatLinkFromReference:(NSString*) reference
+ andDescription:(NSString*) description
+{
+ NSParameterAssert(reference != nil || description != nil);
+
+ // If the link description is not given, use reference.
+ if (!description) description = reference;
+
+ // If this is a member link, only emmit the description.
+ if (![self isInterObjectReference:reference]) reference = nil;
+
+ // If reference is given, emmit standard reference and text.
+ if (reference)
+ {
+ // If we should use reference style links, we only output the link description
+ // and ID. We should handle IDs properly - if the link was already used, use
+ // it's original ID, otherwise create a ID and add it to the dictionary.
+ if (cmd.markdownReferenceStyleLinks)
+ {
+ NSNumber* footnoteNumber = [linkReferences objectForKey:reference];
+ if (!footnoteNumber)
+ {
+ int count = [linkReferences count];
+ footnoteNumber = [NSNumber numberWithInt:count + 1];
+ NSDictionary* footnoteData = [NSDictionary dictionaryWithObjectsAndKeys:
+ footnoteNumber, @"Number",
+ reference, @"Reference",
+ description, @"Description", nil];
+ [linkReferences setObject:footnoteData forKey:reference];
+ }
+
+ // Append the description and footnote index.
+ return [NSString stringWithFormat:@"[`%@`][%@]", description, footnoteNumber];
+ }
+
+ // If we use inline style links, output the description and reference.
+ return [NSString stringWithFormat:@"[%@](%@)", reference, description];
+ }
+
+ // If reference is not given, emmit text only.
+ return [NSString stringWithFormat:@"`%@`", description];
+}
+
+@end
+
View
40 Readme.markdown
@@ -216,6 +216,7 @@ or more of the following options to actually produce something more readable...
* `--xhtml`: Generate XHTML documentation.
* `--docset`: Generate documentation set (this will automatically enable xhtml as well!).
+* `--markdown`: Generate Markdown documentation.
XHTML output options
@@ -239,6 +240,33 @@ Documentation set related options
the created documentation set. Defaults to `/Developer/usr/bin/docsetutils` which is
the default install location, however if you use another path, you must manually
specify it.
+
+
+Markdown output options
+-----------------------
+
+* `--markdown-line-length <number>`: The number of chars to use before forcing a new
+ line. Setting this value below or equal to 0 prevents wrapping take place. Defaults to 80.
+ note that wrapping for non-wrappable phrases (method names for example) can be controller
+ finer with `--markdown-line-threshold` and `--markdown-line-margin`. Note that line
+ wrapping values may not seem intuitive from the start on, so play with them a bit to
+ get a feel.
+* `--markdown-line-threshold <number>`: If a non-wrappable phrase is being added to a
+ line and causes the line to break, this setting prevents break if the line length is
+ below the given threshold of the `--markdown-line-length` and the phrase length is not
+ too big. This value should be kept reasonably small. Defaults to 7.
+* `--markdown-line-margin <number>`: If a non-wrappable phrase is being added to a line
+ and the line length passes the `--markdown-line-threshold` "test" above and the overall
+ length of the line including the phrase is still below the given margin (added to the
+ value of `--markdown-line-length`), the phrase is kept in the same line. This value
+ should be kept reasonably small. Defaults to 12.
+* `--markdown-refstyle-links`: Use reference style links. When used, the links to
+ same or inter-object members will be created using reference style links which are
+ generated as footnotes. Numbers will be used for link IDs, starting with 1 and
+ links to the same object or member will be properly handled (i.e. will not be repeated).
+ Using this option will result in much more readable output. If this option is not used,
+ inline links will be generated which is the default. Note that this option only affects
+ object files creation, index and hierarchy always use inline links!
Formatting options
@@ -320,27 +348,39 @@ line counterparts is:
* `DoxygenCommandLine` (String): `--doxygen`
* `DoxygenConfigFile` (String): `--doxyfile`
+
* `CreateXHTML` (Boolean): `--xhtml`
* `CreateDocSet` (Boolean): `--docset`
+* `CreateMarkdown` (Boolean): `--markdown`
+
* `XHTMLUseBorderedExamples` (Boolean): `--xhtml-bordered-issues` can be used to set
XHTMLUseBorderedExamples, XHTMLUseBorderedWarnings and XHTMLUseBorderedBugs in one
setting. There is no way to specify each separately over command line. There's also
no way to specify all three with a single setting in global parameters.
* `XHTMLUseBorderedWarnings` (Boolean): see previous item.
* `XHTMLUseBorderedBugs` (Boolean): see previous item.
+
* `DocSetBundleID` (String): `--docid`
* `DocSetBundleFeed` (String): `--docfeed`
* `DocSetSourcePlist` (String): `--docplist`
* `DocSetUtilCommandLine` (String): `--docutil`
* `DocSetInstallPath` (String): The path for installing the documentation set. Not
possible to change over command line.
+
+* `MarkdownLineLength` (Number): `--markdown-line-length`
+* `MarkdownLineWrapThreshold` (Number): `--markdown-line-threshold`
+* `MarkdownLineWrapMargin` (Number): `--markdown-line-margin`
+* `MarkdownReferenceStyleLinks` (Boolean): `--markdown-refstyle-links`
+
* `FixClassLocations` (Boolean): `--fix-class-locations`
* `RemoveEmptyParagraphs` (Boolean): `--remove-empty-paragraphs`
* `MergeCategories` (Boolean): `--merge-categories`
* `KeepMergedSections` (Boolean): `--keep-merged-sections`
+
* `ObjectReferenceTemplate` (String): `--object-reference-template`
* `MemberReferenceTemplate` (String): `--member-reference-template`
* `DateTimeTemplate` (String): `--date-time-template`
+
* `CleanTemporaryFilesAfterBuild` (Boolean): `--clean-temp-files`
* `CleanOutputFilesBeforeBuild` (Boolean): `--clean-before-build`
* `VerboseLevel` (Number): `--verbose`
View
8 Templates/screen.css
@@ -276,14 +276,6 @@ dl.parameterList dd {
padding-top: 0.3em;
}
-.strong {
- font-weight: bold;
-}
-
-.emphasize {
- font-style: italic;
-}
-
/* @end */
/* @group Tooltips */
View
14 XMLBasedOutputGenerator+GeneralParsingAPI.h
@@ -184,9 +184,23 @@ item extracted through one of the following methods: @c extractBriefDescriptions
@see extractDescriptionsFromItem:
@see extractDescriptionType:
@see extractDescriptionText:
+@see isInterObjectReference
*/
- (NSString*) extractDescriptionText:(id) item;
+/** Determines if the given reference is inter-object or member reference.
+
+This method can be used to determine the type of the given reference. It should be
+passed the reference obtained from the @c extractDescriptionReference:() method. If
+@c mil is passed, @c NO is returned.
+
+@param reference The reference to check.
+@return Returns @c YES if the given reference represents an inter-object reference,
+ @c NO otherwise. Also returns @c NO if @c mil is passed as the parameter.
+@see extractDescriptionReference:
+*/
+- (BOOL) isInterObjectReference:(NSString*) reference;
+
/** Determines if at least one of the given brief or detailed paragraphs is used or not.
If at least one paragraph from the given array contains some tekst, the method assumes
View
11 XMLBasedOutputGenerator+GeneralParsingAPI.m
@@ -112,6 +112,17 @@ - (NSString*) extractDescriptionText:(id) item
}
//----------------------------------------------------------------------------------------
+- (BOOL) isInterObjectReference:(NSString*) reference
+{
+ if (reference)
+ {
+ NSRange range = [reference rangeOfString:@"#"];
+ return (range.location == NSNotFound);
+ }
+ return NO;
+}
+
+//----------------------------------------------------------------------------------------
- (BOOL) isDescriptionUsed:(NSArray*) items
{
for (NSXMLElement* subnode in items)
View
10 XMLBasedOutputGenerator+HierarchySubclassAPI.h
@@ -27,7 +27,7 @@ first message. It gives subclasses a chance to append data to the output before
output generation starts. After this message is sent, the rest of the messages are followed
and as the last one, @c appendHierarchyFooterToData:() is sent.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForHierarchy
@see appendHierarchyFooterToData:
@@ -40,7 +40,7 @@ The message is sent from the @c XMLBasedOutputGenerator::outputDataForHierarchy(
last message. It gives subclasses a chance to append data to the output after the rest of
the output is generated. This is ussually the place to "close" open tags or similar.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForHierarchy
@see appendHierarchyHeaderToData:
@@ -59,7 +59,7 @@ to the output before the generation for group items starts. After this message i
at least one @c appendHierarchyGroupItemToData:fromItem:index:() message is sent and then
@c appendHierarchyGroupFooterToData:() is sent at the end.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForHierarchy
@see appendHierarchyGroupItemToData:fromItem:index:
@@ -77,7 +77,7 @@ tags or similar.
Note that this message is sent after all children of all the group items are processed
so that the subclass can safely assume the whole group is processed well.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForHierarchy
@see appendHierarchyGroupHeaderToData:
@@ -92,7 +92,7 @@ group member. The subclass should append the data for the given item. The subcla
get more information about the member by using the hierarchy member data methods from the
@c XMLBasedOutputGenerator(HierarchyParsingAPI) category.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param item The data item describing the given member.
@param index Zero based index of the member within the group.
@exception NSException Thrown if appending fails.
View
10 XMLBasedOutputGenerator+IndexSubclassAPI.h
@@ -27,7 +27,7 @@ message. It gives subclasses a chance to append data to the output before the ac
generation starts. After this message is sent, the rest of the messages are followed and as
the last one, @c appendIndexFooterToData:() is sent.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForIndex
@see appendIndexFooterToData:
@@ -40,7 +40,7 @@ The message is sent from the @c XMLBasedOutputGenerator::outputDataForIndex() as
message. It gives subclasses a chance to append data to the output after the rest of the
output is generated. This is ussually the place to "close" open tags or similar.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForIndex
@see appendIndexHeaderToData:
@@ -64,7 +64,7 @@ The type identifies the type of the index group and can be one of the following:
- @c kTKIndexGroupProtocols: This group will append all protocols.
- @c kTKIndexGroupCategories: This group will append all categories.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param type The type of the index group.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForIndex
@@ -85,7 +85,7 @@ The type identifies the type of the index group and can be one of the following:
- @c kTKIndexGroupProtocols: This group will append all protocols.
- @c kTKIndexGroupCategories: This group will append all categories.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param type The type of the index group.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::outputDataForIndex
@@ -107,7 +107,7 @@ The type identifies the type of the index group and can be one of the following:
- @c kTKIndexGroupProtocols: This group will append all protocols.
- @c kTKIndexGroupCategories: This group will append all categories.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param item The data item describing the given member.
@param index Zero based index of the member within the group.
@param type The type of the index group.
View
32 XMLBasedOutputGenerator+ObjectSubclassAPI.h
@@ -27,7 +27,7 @@ the first message. It gives subclasses a chance to append data to the output bef
actual output generation starts. After this message is sent, the rest of the messages are
followed and as the last one, @c appendObjectFooterToData:() is sent.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectFooterToData:
@@ -40,7 +40,7 @@ The message is sent from the @c XMLBasedOutputGenerator::generateOutputForObject
last message. It gives subclasses a chance to append data to the output after the rest
of the output is generated. This is ussually the place to "close" open tags or similar.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectHeaderToData:
@@ -59,7 +59,7 @@ the output before the generation for secion items starts. After this message is
at least one @c appendObjectInfoItemToData:fromItems:index:type:() message is sent and
then @c appendObjectInfoHeaderToData:() is sent at the end.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectInfoItemToData:fromItems:index:type:
@@ -74,7 +74,7 @@ last info generation message. It gives subclasses a chance to append data to the
after the info items generation is finished. This is ussually the place to "close" open
tags or similar.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectInfoHeaderToData:
@@ -98,7 +98,7 @@ The type identifies the type of the info item and can be one of the following:
- @c kTKInfoItemDeclared: The @c nodex contain declared in information. Only one node
is in the list in most (all) cases.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param items The array of info items instances describing individual items.
@param index Zero based index of the item within the info object info.
@param type The type of the item.
@@ -123,7 +123,7 @@ has brief and or detailed documentation assigned. It gives subclasses a chance t
object overview from the gathered documentation. The given @c item contains brief and
detailed object description and can be treated as any other description item.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param item The item that contains the brief and detailed description.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@@ -143,7 +143,7 @@ output before any individual task handling is started. After this message is sen
individual task is handled and when all tasks are done, @c appendObjectTasksFooterToData:()
is sent.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectTaskHeaderToData:fromItem:index:
@@ -158,7 +158,7 @@ The message is sent from the @c XMLBasedOutputGenerator::generateOutputForObject
tasks have been processed. It gives subclasses a chance to append data to the output at
that point. This is ussually the place to "close" tasks open tags or similar.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectTasksHeaderToData:
@@ -174,7 +174,7 @@ The message is sent from the @c XMLBasedOutputGenerator::generateOutputForObject
task which has at least one member. It gives subclasses a chance to append data to the
output before member handling for the given task starts.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param item The item that contains the task description.
@param index Zero based index of the task.
@exception NSException Thrown if appending fails.
@@ -194,7 +194,7 @@ The message is sent from the @c XMLBasedOutputGenerator::generateOutputForObject
task members have been processed. It gives subclasses a chance to append data to the output
at that point. This is ussually the place to "close" tasks open tags or similar.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param item The item that contains the task description.
@param index Zero based index of the task.
@exception NSException Thrown if appending fails.
@@ -214,7 +214,7 @@ This message is sent from the @c XMLBasedOutputGenerator::generateOutputForObjec
task member (class or instance method or property). Subclasses should append any desired
data for the given member.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param item The item that contains the task member description.
@param index Zero based index of the member within the task.
@exception NSException Thrown if appending fails.
@@ -240,7 +240,7 @@ data to the output before any individual member handling is started. After this
is sent, each individual member group is handled and when all members are done,
@c appendObjectMembersFooterToData:() is sent.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectMembersFooterToData:
@@ -256,7 +256,7 @@ The message is sent from the @c XMLBasedOutputGenerator::generateOutputForObject
member groups have been processed. It gives subclasses a chance to append data to the
output at that point. This is ussually the place to "close" sections open tags or similar.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@see appendObjectMembersHeaderToData:
@@ -281,7 +281,7 @@ message one or more @c appendObjectMemberToData:fromItem:index:() messages are s
for each documented member of the given group and after all members output is generated,
@c appendObjectMemberGroupHeaderToData:type:() is sent.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param type The type of the group that is being described.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@@ -306,7 +306,7 @@ Subclasses should append any desired data for the given group type. In most case
is the place to close any open tags or similar. The message is only sent if the
corresponding @c appendObjectMemberGroupHeaderToData:type:() was sent.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param type The type of the group that is being described.
@exception NSException Thrown if appending fails.
@see XMLBasedOutputGenerator::generateOutputForObject:
@@ -323,7 +323,7 @@ corresponding @c appendObjectMemberGroupHeaderToData:type:() was sent.
This message is sent from @c XMLBasedOutputGenerator::generateOutputForObject:() for each
documented member. Subclasses should output the full documentation for the given member.
-@param data The data to append to. This is guaranteed to be non @c null.
+@param data The data to append to. This is guaranteed to be non @c mil.
@param item The item that describes the member data.
@param index Zero based index of the member within the group.
@exception NSException Thrown if appending fails.
View
6 appledoc.xcodeproj/project.pbxproj
@@ -21,6 +21,7 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 7325D2200FE5811400596AFB /* MarkdownOutputGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = 7325D21F0FE5811400596AFB /* MarkdownOutputGenerator.m */; };
733560550FD3E08300C19DED /* XMLBasedOutputGenerator+GeneralParsingAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 733560530FD3E08300C19DED /* XMLBasedOutputGenerator+GeneralParsingAPI.m */; };
73399E710FD40C9700B65E5C /* XMLBasedOutputGenerator+ObjectSubclassAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 73399E700FD40C9700B65E5C /* XMLBasedOutputGenerator+ObjectSubclassAPI.m */; };
73399F070FD4160300B65E5C /* XMLBasedOutputGenerator+IndexSubclassAPI.m in Sources */ = {isa = PBXBuildFile; fileRef = 73399F050FD4160300B65E5C /* XMLBasedOutputGenerator+IndexSubclassAPI.m */; };
@@ -64,6 +65,8 @@
08FB7796FE84155DC02AAC07 /* appledoc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = appledoc.m; sourceTree = "<group>"; };
08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
32A70AAB03705E1F00C91783 /* appledoc_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = appledoc_Prefix.pch; sourceTree = "<group>"; };
+ 7325D21E0FE5811400596AFB /* MarkdownOutputGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkdownOutputGenerator.h; sourceTree = "<group>"; };
+ 7325D21F0FE5811400596AFB /* MarkdownOutputGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MarkdownOutputGenerator.m; sourceTree = "<group>"; wrapsLines = 0; };
733560530FD3E08300C19DED /* XMLBasedOutputGenerator+GeneralParsingAPI.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XMLBasedOutputGenerator+GeneralParsingAPI.m"; sourceTree = "<group>"; };
733560540FD3E08300C19DED /* XMLBasedOutputGenerator+GeneralParsingAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XMLBasedOutputGenerator+GeneralParsingAPI.h"; sourceTree = "<group>"; };
73399E6F0FD40C9700B65E5C /* XMLBasedOutputGenerator+ObjectSubclassAPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XMLBasedOutputGenerator+ObjectSubclassAPI.h"; sourceTree = "<group>"; };
@@ -176,6 +179,8 @@
739C8E1C0FE1A06900E6D950 /* DoxygenOutputGenerator.m */,
73B88AEC0FE245CE004C31DC /* XMLOutputGenerator.h */,
73B88AEB0FE245CE004C31DC /* XMLOutputGenerator.m */,
+ 7325D21E0FE5811400596AFB /* MarkdownOutputGenerator.h */,
+ 7325D21F0FE5811400596AFB /* MarkdownOutputGenerator.m */,
734470290FCF169400D8FDCE /* XHTMLOutputGenerator.h */,
7344702A0FCF169400D8FDCE /* XHTMLOutputGenerator.m */,
73B88BD20FE26842004C31DC /* DocSetOutputGenerator.h */,
@@ -331,6 +336,7 @@
73B88A140FE22D73004C31DC /* Constants.m in Sources */,
73B88AED0FE245CE004C31DC /* XMLOutputGenerator.m in Sources */,
73B88BD30FE26842004C31DC /* DocSetOutputGenerator.m in Sources */,
+ 7325D2200FE5811400596AFB /* MarkdownOutputGenerator.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Please sign in to comment.
Something went wrong with that request. Please try again.