Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Implemented documentation set Info.plist generation.

  • Loading branch information...
commit 3434f62745b4b33c1403860199da26fed5e1b66e 1 parent b78cb9b
@tomaz authored
View
43 Application/GBApplicationSettingsProvider.m
@@ -16,6 +16,8 @@ - (NSString *)relativePathPrefixFromObject:(GBModelBase *)source toObject:(GBMod
- (NSString *)htmlReferenceForObjectFromIndex:(GBModelBase *)object;
- (NSString *)htmlReferenceForTopLevelObject:(GBModelBase *)object fromTopLevelObject:(GBModelBase *)source;
- (NSString *)htmlReferenceForMember:(GBModelBase *)member prefixedWith:(NSString *)prefix;
+@property (readonly) NSDateFormatter *yearDateFormatter;
+@property (readonly) NSDateFormatter *yearToDayDateFormatter;
@end
@@ -34,6 +36,19 @@ - (id)init {
if (self) {
self.projectName = @"PROJECT";
self.projectCompany = @"COMPANY";
+ self.docsetBundleIdentifier = @"com.company.project";
+ self.docsetBundleName = @"$PROJECT Documentation";
+ self.docsetCertificateIssuer = @"";
+ self.docsetCertificateSigner = @"";
+ self.docsetDescription = @"";
+ self.docsetFallbackURL = @"";
+ self.docsetFeedName = @"";
+ self.docsetFeedURL = @"";
+ self.docsetMinimumXcodeVersion = @"3.0";
+ self.docsetPlatformFamily = @"macosx";
+ self.docsetPublisherIdentifier = @"com.company.documentation";
+ self.docsetPublisherName = @"COMPANY";
+ self.docsetCopyrightMessage = @"© $YEAR $COMPANY. All rights reserved.";
self.outputPath = @"~/Downloads/examples/AppledocHtml";
self.templatesPath = @"~/Dropbox/Xcode/Projects/Tools/appledoc/Project/Templates";
self.ignoredPaths = [NSMutableSet set];
@@ -122,6 +137,34 @@ - (NSString *)htmlExtension {
return @"html";
}
+#pragma mark Date and time helpers
+
+- (NSString *)yearStringFromDate:(NSDate *)date {
+ return [self.yearDateFormatter stringFromDate:date];
+}
+
+- (NSString *)yearToDayStringFromDate:(NSDate *)date {
+ return [self.yearToDayDateFormatter stringFromDate:date];
+}
+
+- (NSDateFormatter *)yearDateFormatter {
+ static NSDateFormatter *result = nil;
+ if (!result) {
+ result = [[NSDateFormatter alloc] init];
+ [result setDateFormat:@"yyyy"];
+ }
+ return result;
+}
+
+- (NSDateFormatter *)yearToDayDateFormatter {
+ static NSDateFormatter *result = nil;
+ if (!result) {
+ result = [[NSDateFormatter alloc] init];
+ [result setDateFormat:@"yyyy-MM-dd"];
+ }
+ return result;
+}
+
#pragma mark Paths helper methods
- (NSString *)outputPathForObject:(id)object withExtension:(NSString *)extension {
View
55 Application/GBApplicationSettingsProviding.h
@@ -19,7 +19,7 @@
@protocol GBApplicationSettingsProviding
///---------------------------------------------------------------------------------------
-/// @name Common values handling
+/// @name Project values handling
///---------------------------------------------------------------------------------------
/** Human readable name of the project. */
@@ -29,6 +29,59 @@
@property (copy) NSString *projectCompany;
///---------------------------------------------------------------------------------------
+/// @name Documentation set handling
+///---------------------------------------------------------------------------------------
+
+/** Documentation set bundle identifier. */
+@property (copy) NSString *docsetBundleIdentifier;
+
+/** Documentation set bundle name. */
+@property (copy) NSString *docsetBundleName;
+
+/** Documentation set certificate issuer. */
+@property (copy) NSString *docsetCertificateIssuer;
+
+/** Documentation set certificate signer. */
+@property (copy) NSString *docsetCertificateSigner;
+
+/** Documentation set description. */
+@property (copy) NSString *docsetDescription;
+
+/** Documentation set fallback URL. */
+@property (copy) NSString *docsetFallbackURL;
+
+/** Documentation set feed name. */
+@property (copy) NSString *docsetFeedName;
+
+/** Documentation set feed URL. */
+@property (copy) NSString *docsetFeedURL;
+
+/** Documentation set minimum Xcode version. */
+@property (copy) NSString *docsetMinimumXcodeVersion;
+
+/** Documentation set platform family. */
+@property (copy) NSString *docsetPlatformFamily;
+
+/** Documentation set publisher identifier. */
+@property (copy) NSString *docsetPublisherIdentifier;
+
+/** Documentation set publisher name. */
+@property (copy) NSString *docsetPublisherName;
+
+/** Documentation set human readble copyright message. */
+@property (copy) NSString *docsetCopyrightMessage;
+
+///---------------------------------------------------------------------------------------
+/// @name Date and time handling
+///---------------------------------------------------------------------------------------
+
+/** Returns string representing the year of the given date. */
+- (NSString *)yearStringFromDate:(NSDate *)date;
+
+/** Returns string representing year-month-day of the given date. */
+- (NSString *)yearToDayStringFromDate:(NSDate *)date;
+
+///---------------------------------------------------------------------------------------
/// @name Paths handling
///---------------------------------------------------------------------------------------
View
24 Common/NSError+GBError.h
@@ -0,0 +1,24 @@
+//
+// NSError+GBError.h
+// appledoc
+//
+// Created by Tomaz Kragelj on 29.11.10.
+// Copyright 2010 Gentle Bytes. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+/** Adds helper methods to `NSError` for more organized code.
+ */
+@interface NSError (GBError)
+
+/** Creates a new `NSError` with appledoc domain and given information.
+
+ @param code Error code.
+ @param description Error localized description.
+ @param reason Error localized failure reason.
+ @return Returns autoreleased `NSError` with the given data.
+ */
++ (NSError *)errorWithCode:(NSInteger)code description:(NSString *)description reason:(NSString *)reason;
+
+@end
View
23 Common/NSError+GBError.m
@@ -0,0 +1,23 @@
+//
+// NSError+GBError.m
+// appledoc
+//
+// Created by Tomaz Kragelj on 29.11.10.
+// Copyright 2010 Gentle Bytes. All rights reserved.
+//
+
+#import "NSError+GBError.h"
+
+@implementation NSError (GBError)
+
++ (NSError *)errorWithCode:(NSInteger)code description:(NSString *)description reason:(NSString *)reason {
+ NSMutableDictionary *info = nil;
+ if ([description length] > 0 || [reason length] > 0) {
+ info = [NSMutableDictionary dictionaryWithCapacity:2];
+ if ([description length] > 0) [info setObject:description forKey:NSLocalizedDescriptionKey];
+ if ([reason length] > 0) [info setObject:reason forKey:NSLocalizedFailureReasonErrorKey];
+ }
+ return [self errorWithDomain:@"appledoc" code:code userInfo:info];
+}
+
+@end
View
75 Generating/GBDocSetOutputGenerator.m
@@ -6,11 +6,15 @@
// Copyright 2010 Gentle Bytes. All rights reserved.
//
+#import "GBApplicationSettingsProvider.h"
+#import "GBTemplateHandler.h"
#import "GBDocSetOutputGenerator.h"
@interface GBDocSetOutputGenerator ()
- (BOOL)moveSourceFilesToDocuments:(NSError **)error;
+- (BOOL)processInfoPlist:(NSError **)error;
+- (NSString *)replacePlaceholdersInString:(NSString *)string;
@end
@@ -24,39 +28,78 @@ - (BOOL)generateOutputWithStore:(id<GBStoreProviding>)store error:(NSError **)er
NSParameterAssert(self.previousGenerator != nil);
if (![super generateOutputWithStore:store error:error]) return NO;
if (![self moveSourceFilesToDocuments:error]) return NO;
+ if (![self processInfoPlist:error]) return NO;
return YES;
}
- (BOOL)moveSourceFilesToDocuments:(NSError **)error {
- // Prepare all paths. Note that we determine the exact subdirectory by searching for documents-template and using it's subdirectory as the guide.
- NSString *sourceFilesPath = [self.previousGenerator.outputUserPath stringByStandardizingPath];
- NSString *documentsPath = nil;
- for (NSString *template in [self.templateFiles allKeys]) {
- if ([template hasSuffix:@"documents-template"]) {
- documentsPath = [template stringByDeletingLastPathComponent];
- break;
- }
- }
+ GBLogInfo(@"Moving HTML files to DocSet bundle...");
- // If documents template wasn't found, exit.
+ // Prepare all paths. Note that we determine the exact subdirectory by searching for documents-template and using it's subdirectory as the guide. If documents template wasn't found, exit.
+ NSString *sourceFilesPath = [self.previousGenerator.outputUserPath stringByStandardizingPath];
+ NSString *documentsPath = [self templateFileKeyEndingWith:@"documents-template"];
if (!documentsPath) {
- if (error) {
- NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:
- @"Documents template is missing!", NSLocalizedDescriptionKey,
- @"documents-template file is required to determine location for Documents path in DocSet bundle!", NSLocalizedFailureReasonErrorKey, nil];
- *error = [NSError errorWithDomain:@"appledoc" code:1 userInfo:info];
- }
+ if (error) *error = [NSError errorWithCode:1 description:@"Documents template is missing!" reason:@"documents-template file is required to determine location for Documents path in DocSet bundle!"];
GBLogWarn(@"Failed finding documents-template in '%@'!", self.templateUserPath);
return NO;
}
// First step is to move all files generated by previous generator as the Documents subfolder of docset structure.
+ documentsPath = [documentsPath stringByDeletingLastPathComponent];
NSString *destPath = [self.outputUserPath stringByAppendingPathComponent:documentsPath];
NSString *movePath = [destPath stringByAppendingPathComponent:@"Documents"];
if (![self.fileManager moveItemAtPath:sourceFilesPath toPath:[movePath stringByStandardizingPath] error:error]) {
GBLogWarn(@"Failed moving files from '%@' to '%@'!", self.previousGenerator.outputUserPath, movePath);
return NO;
}
+ return YES;
+}
+
+- (BOOL)processInfoPlist:(NSError **)error {
+ GBLogInfo(@"Writting DocSet Info.plist...");
+ NSString *templatePath = [self templateFileKeyEndingWith:@"info-template.plist"];
+ if (!templatePath) {
+ if (error) *error = [NSError errorWithCode:2 description:@"Info.plist template is missing!" reason:@"info-template.plist file is required to specify information about DocSet!"];
+ GBLogWarn(@"Failed finding info-template.plist in '%@'!", self.templateUserPath);
+ return NO;
+ }
+
+ // Prepare template variables and replace all placeholders with actual values.
+ NSMutableDictionary *vars = [NSMutableDictionary dictionaryWithCapacity:20];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetBundleIdentifier] forKey:@"bundleIdentifier"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetBundleName] forKey:@"bundleName"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetCertificateIssuer] forKey:@"certificateIssuer"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetCertificateSigner] forKey:@"certificateSigner"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetDescription] forKey:@"description"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetFallbackURL] forKey:@"fallbackURL"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetFeedName] forKey:@"feedName"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetFeedURL] forKey:@"feedURL"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetMinimumXcodeVersion] forKey:@"minimumXcodeVersion"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetPlatformFamily] forKey:@"platformFamily"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetPublisherIdentifier] forKey:@"publisherIdentifier"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetPublisherName] forKey:@"publisherName"];
+ [vars setObject:[self replacePlaceholdersInString:self.settings.docsetCopyrightMessage] forKey:@"copyrightMessage"];
+
+ // Run the template and save the results as Info.plist.
+ GBTemplateHandler *handler = [self.templateFiles objectForKey:templatePath];
+ NSString *output = [handler renderObject:vars];
+ NSString *path = [[templatePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"Info.plist"];
+ NSString *filename = [self.outputUserPath stringByAppendingPathComponent:path];
+ if (![self writeString:output toFile:[filename stringByStandardizingPath] error:error]) {
+ GBLogWarn(@"Failed writting Info.plist to '%@'!", filename);
+ return NO;
+ }
+ return YES;
+}
+
+#pragma mark Helper methods
+
+- (NSString *)replacePlaceholdersInString:(NSString *)string {
+ string = [string stringByReplacingOccurrencesOfString:@"$PROJECT" withString:self.settings.projectName];
+ string = [string stringByReplacingOccurrencesOfString:@"$COMPANY" withString:self.settings.projectCompany];
+ string = [string stringByReplacingOccurrencesOfString:@"$YEAR" withString:[self.settings yearStringFromDate:[NSDate date]]];
+ string = [string stringByReplacingOccurrencesOfString:@"$UPDATEDATE" withString:[self.settings yearToDayStringFromDate:[NSDate date]]];
+ return string;
}
#pragma mark Overriden methods
View
7 Generating/GBGenerator.m
@@ -65,15 +65,16 @@ - (void)runGeneratorStepsWithStore:(id<GBStoreProviding>)store {
__block GBOutputGenerator *previous = nil;
[self.outputGenerators enumerateObjectsUsingBlock:^(GBOutputGenerator *generator, NSUInteger idx, BOOL *stop) {
NSError *error = nil;
- GBLogVerbose(@"Step %ld/%ld: Running %@...", idx, stepsCount, [generator className]);
+ NSUInteger index = idx + 1;
+ GBLogVerbose(@"Step %ld/%ld: Running %@...", index, stepsCount, [generator className]);
generator.previousGenerator = previous;
if (![generator copyTemplateFilesToOutputPath:&error]) {
- GBLogNSError(error, @"Step %ld/%ld failed: %@ failed copying template files to output, aborting!", idx, stepsCount, [generator className]);
+ GBLogNSError(error, @"Step %ld/%ld failed: %@ failed copying template files to output, aborting!", index, stepsCount, [generator className]);
*stop = YES;
return;
}
if (![generator generateOutputWithStore:store error:&error]) {
- GBLogNSError(error, @"Step %ld/%ld failed: %@ failed generaing output, aborting!", idx, stepsCount, [generator className]);
+ GBLogNSError(error, @"Step %ld/%ld failed: %@ failed generaing output, aborting!", index, stepsCount, [generator className]);
*stop = YES;
return;
}
View
24 Generating/GBHTMLTemplateVariablesProvider.m
@@ -20,8 +20,6 @@ @interface GBHTMLTemplateVariablesProvider ()
- (NSString *)hrefForObject:(id)object fromObject:(id)source;
- (NSDictionary *)arrayDescriptorForArray:(NSArray *)array;
- (void)addFooterVarsToDictionary:(NSMutableDictionary *)dict;
-@property (readonly) NSDateFormatter *yearDateFormatter;
-@property (readonly) NSDateFormatter *yearToDayDateFormatter;
@property (retain) id<GBApplicationSettingsProviding> settings;
@property (retain) id<GBStoreProviding> store;
@@ -171,26 +169,8 @@ - (NSDictionary *)arrayDescriptorForArray:(NSArray *)array {
- (void)addFooterVarsToDictionary:(NSMutableDictionary *)dict {
[dict setObject:self.settings.projectCompany forKey:@"copyrightHolder"];
- [dict setObject:[self.yearDateFormatter stringFromDate:[NSDate date]] forKey:@"copyrightDate"];
- [dict setObject:[self.yearToDayDateFormatter stringFromDate:[NSDate date]] forKey:@"lastUpdatedDate"];
-}
-
-- (NSDateFormatter *)yearDateFormatter {
- static NSDateFormatter *result = nil;
- if (!result) {
- result = [[NSDateFormatter alloc] init];
- [result setDateFormat:@"yyyy"];
- }
- return result;
-}
-
-- (NSDateFormatter *)yearToDayDateFormatter {
- static NSDateFormatter *result = nil;
- if (!result) {
- result = [[NSDateFormatter alloc] init];
- [result setDateFormat:@"yyyy-MM-dd"];
- }
- return result;
+ [dict setObject:[self.settings yearStringFromDate:[NSDate date]] forKey:@"copyrightDate"];
+ [dict setObject:[self.settings yearToDayStringFromDate:[NSDate date]] forKey:@"lastUpdatedDate"];
}
#pragma mark Properties
View
11 Generating/GBOutputGenerator.h
@@ -86,6 +86,16 @@
/// @name Subclass parameters and helpers
///---------------------------------------------------------------------------------------
+/** Searches `templateFiles` dictionary for a key ending with the given suffix and returns the whole key if found.
+
+ If the key is not found, `nil` is returned. This method is useful for finding keys for which we only know partial name (ussually the name of the file, but not the path to it).
+
+ @param suffix Template file suffix to search for.
+ @return Returns full key if found, `nil` otherwise.
+ @see templateFiles
+ */
+- (NSString *)templateFileKeyEndingWith:(NSString *)suffix;
+
/** The dictionary of all template files detected within `copyTemplateFilesToOutputPath:`.
Each object has a key of template file name and relative path from `templateUserPath`. The keys are mapped to `GBTemplateHandler` instances associated with the template.
@@ -93,6 +103,7 @@
This is intended to be used within subclasses only. Dictionary contents are automatically updated and should not be changed by subclasses.
@see copyTemplateFilesToOutputPath:
+ @see templateFileKeyEndingWith:
*/
@property (readonly) NSMutableDictionary *templateFiles;
View
7 Generating/GBOutputGenerator.m
@@ -125,6 +125,13 @@ - (BOOL)isPathRepresentingIgnoredFile:(NSString *)path {
#pragma mark Helper methods
+- (NSString *)templateFileKeyEndingWith:(NSString *)suffix {
+ for (NSString *template in [self.templateFiles allKeys]) {
+ if ([template hasSuffix:suffix]) return template;
+ }
+ return nil;
+}
+
- (BOOL)writeString:(NSString *)string toFile:(NSString *)path error:(NSError **)error {
NSString *standardized = [path stringByStandardizingPath];
NSString *directory = [standardized stringByDeletingLastPathComponent];
View
2  Templates/docset/Contents/info-template.plist
@@ -11,7 +11,7 @@
DocSetFeedName = "{{feedName}}";
DocSetFeedURL = "{{feedURL}}";
"DocSetMinimumXcodeVersion" = "{{minimumXcodeVersion}}";
- DocSetPlatformFamily = macosx;
+ DocSetPlatformFamily = "{{platformFamily}}";
"DocSetPublisherIdentifier" = "{{publisherIdentifier}}";
DocSetPublisherName = "{{publisherName}}";
"NSHumanReadableCopyright" = "{{copyrightMessage}}";
View
6 appledoc.xcodeproj/project.pbxproj
@@ -120,6 +120,7 @@
7359B16A129A5A0700F67AD1 /* GRMustacheVariableElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 7359B146129A5A0600F67AD1 /* GRMustacheVariableElement.m */; };
7359B16B129A5A0700F67AD1 /* GRMustacheVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 7359B148129A5A0700F67AD1 /* GRMustacheVersion.m */; };
7359B16C129A5A0700F67AD1 /* GRMustacheVersion.m in Sources */ = {isa = PBXBuildFile; fileRef = 7359B148129A5A0700F67AD1 /* GRMustacheVersion.m */; };
+ 7367298412A3D7A000879D1B /* NSError+GBError.m in Sources */ = {isa = PBXBuildFile; fileRef = 7367298312A3D7A000879D1B /* NSError+GBError.m */; };
7367B84E11FEF496005ED6CD /* GBCategoryData.m in Sources */ = {isa = PBXBuildFile; fileRef = 7367B84D11FEF496005ED6CD /* GBCategoryData.m */; };
7367BB3612003CAB005ED6CD /* GBModelBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 7367BB3512003CAB005ED6CD /* GBModelBase.m */; };
736A2751125841420078F4FE /* GBTemplateVariablesProvider-ObjectSpecificationsTesting.m in Sources */ = {isa = PBXBuildFile; fileRef = 736A2750125841420078F4FE /* GBTemplateVariablesProvider-ObjectSpecificationsTesting.m */; };
@@ -277,6 +278,8 @@
7359B148129A5A0700F67AD1 /* GRMustacheVersion.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GRMustacheVersion.m; path = GRMustache/GRMustacheVersion.m; sourceTree = "<group>"; };
735BCB49124EE92F00FB6C4A /* timing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timing.h; sourceTree = "<group>"; };
7367298112A3BD9D00879D1B /* docset */ = {isa = PBXFileReference; lastKnownFileType = folder; path = docset; sourceTree = "<group>"; };
+ 7367298212A3D7A000879D1B /* NSError+GBError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+GBError.h"; sourceTree = "<group>"; };
+ 7367298312A3D7A000879D1B /* NSError+GBError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+GBError.m"; sourceTree = "<group>"; };
7367B6EA11FE3788005ED6CD /* GBTestObjectsRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GBTestObjectsRegistry.h; sourceTree = "<group>"; };
7367B6EB11FE3788005ED6CD /* GBTestObjectsRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GBTestObjectsRegistry.m; sourceTree = "<group>"; };
7367B82111FEEB52005ED6CD /* GBObjectsAssertor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GBObjectsAssertor.h; sourceTree = "<group>"; };
@@ -706,6 +709,8 @@
7340F02511FCC63100E712A4 /* NSFileManager+GBFileManager.m */,
731E7CE611F9962D00AAF15D /* NSException+GBException.h */,
731E7CE711F9962D00AAF15D /* NSException+GBException.m */,
+ 7367298212A3D7A000879D1B /* NSError+GBError.h */,
+ 7367298312A3D7A000879D1B /* NSError+GBError.m */,
73D54C9511F8D1F500CCDDB0 /* ThirdParty */,
);
path = Common;
@@ -1279,6 +1284,7 @@
73D2524612A2ED610024F9F9 /* GBOutputGenerator.m in Sources */,
73473D3112A38B730011336C /* GBHTMLOutputGenerator.m in Sources */,
731872C512A3B75C0035509F /* GBDocSetOutputGenerator.m in Sources */,
+ 7367298412A3D7A000879D1B /* NSError+GBError.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
1  appledoc_Prefix.pch
@@ -11,6 +11,7 @@
#import "NSObject+GBObject.h"
#import "NSString+GBString.h"
#import "NSException+GBException.h"
+ #import "NSError+GBError.h"
#import "NSFileManager+GBFileManager.h"
#import "GBLog.h"
#endif
Please sign in to comment.
Something went wrong with that request. Please try again.