Created
December 22, 2013 18:53
-
-
Save aglee/8086747 to your computer and use it in GitHub Desktop.
Category on NSApplication that makes it easy to use a Markdown-formatted Credits file, or to use your README as the Credits file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSApplication+MarkdownCredits.h | |
// ALUtilities | |
// | |
// Copyright (c) 2013 Andy Lee | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software | |
// and associated documentation files (the "Software"), to deal in the Software without restriction, | |
// including without limitation the rights to use, copy, modify, merge, publish, distribute, | |
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so. Attribution is not required for either source or binary forms of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | |
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
// | |
#import <Cocoa/Cocoa.h> | |
/*! | |
* This category adds a showAboutPanelWithDerivedCredits: method, plus methods | |
* that support it. This allows you to easily use a Markdown-formatted file as | |
* your Credits file in the standard info panel. The easiest way to do this is: | |
* | |
* - Replace Credits.rtf with Credits.markdown, or Credits.mdown or Credits.md | |
* if you prefer. | |
* - Change the action of the "About" menu item to showAboutPanelWithDerivedCredits:. | |
* - Add the MMMarkdown project to your project. <https://github.com/mdiep/MMMarkdown> | |
* | |
* If you prefer a Markdown library other than MMMarkdown, you'll have to | |
* implement application:creditsStringFromData: in your app delegate to use that | |
* library. You can also implement it if you don't want to use Markdown at all, | |
* and have another way you'd like to generate the attributed string used for | |
* Credits. | |
* | |
* If there is no Credits.(markdown|mdown|md) file, showAboutPanelWithDerivedCredits: | |
* searches for a README file with one of those extensions. If you want your | |
* README to be your Credits file, remember to add it to your application's | |
* build target. | |
* | |
* You can specify a different file name altogether by implementing | |
* creditsFileNameForApplication:. This will be used regardless of whether | |
* Credits or README files are present. | |
*/ | |
@interface NSApplication (MarkdownCredits) | |
/*! | |
* Used internally to provide the Credits string used by | |
* showAboutPanelWithDerivedCredits:. You might want to use this to implement | |
* your own info panel if you don't like the standard one. | |
*/ | |
- (NSAttributedString *)derivedCreditsString; | |
#pragma mark - Action methods | |
/*! | |
* Opens the standard info panel, using different logic to derive the | |
* attributed string used for Credits. | |
*/ | |
- (IBAction)showAboutPanelWithDerivedCredits:(id)sender; | |
@end | |
#pragma mark - Informal protocol that supports showAboutPanelWithDerivedCredits: | |
@interface NSObject (MarkdownCredits) | |
/*! | |
* File name to look for in the application bundle. showAboutPanelWithDerivedCredits: | |
* passes the contents of this file to application:creditsStringFromData:. If this | |
* method is not implemented or if it returns nil, a search is done for README.(markdown|mdown|md). | |
* If no credits file is found in the application bundle, we call orderFrontStandardAboutPanel:. | |
*/ | |
- (NSString *)creditsFileNameForApplication:(NSApplication *)application; | |
/*! | |
* If the app delegate doesn't implement this, showAboutPanelWithDerivedCredits: | |
* checks whether the MMMarkdown library is present. If so, uses it to convert | |
* the data, on the assumption that it's in Markdown format. | |
*/ | |
- (NSAttributedString *)application:(NSApplication *)application | |
creditsStringFromData:(NSData *)creditsData; | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// NSApplication+MarkdownCredits.m | |
// ALUtilities | |
// | |
// Copyright (c) 2013 Andy Lee | |
// | |
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software | |
// and associated documentation files (the "Software"), to deal in the Software without restriction, | |
// including without limitation the rights to use, copy, modify, merge, publish, distribute, | |
// sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is | |
// furnished to do so. Attribution is not required for either source or binary forms of the Software. | |
// | |
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | |
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, | |
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
// | |
#import "NSApplication+MarkdownCredits.h" | |
@implementation NSApplication (MarkdownCredits) | |
- (NSAttributedString *)derivedCreditsString | |
{ | |
// Load data from the credits file. | |
NSString *creditsFilePath = [self _creditsFilePath]; | |
if (creditsFilePath == nil) | |
{ | |
return nil; | |
} | |
NSData *creditsData = [NSData dataWithContentsOfFile:creditsFilePath]; | |
if (creditsData == nil) | |
{ | |
NSLog(@"+++ [ERROR] Could not load contents of file [%@].", creditsFilePath); | |
return nil; | |
} | |
// Convert the data to an attributed string. | |
NSAttributedString *creditsString; | |
if ([self.delegate respondsToSelector:@selector(application:creditsStringFromData:)]) | |
{ | |
creditsString = [(id)self.delegate application:self creditsStringFromData:creditsData]; | |
} | |
else | |
{ | |
creditsString = [self _creditsStringFromMarkdownData:creditsData]; | |
} | |
if (creditsString == nil) | |
{ | |
NSLog(@"+++ [ERROR] Could not convert contents of file [%@] to a Credits string.", | |
creditsFilePath); | |
} | |
return creditsString; | |
} | |
#pragma mark - Action methods | |
- (IBAction)showAboutPanelWithDerivedCredits:(id)sender | |
{ | |
NSAttributedString *creditsString = [self derivedCreditsString]; | |
if (creditsString == nil) | |
{ | |
[self orderFrontStandardAboutPanel:sender]; | |
} | |
else | |
{ | |
[self orderFrontStandardAboutPanelWithOptions:@{ @"Credits" : creditsString }]; | |
} | |
} | |
#pragma mark - Private methods | |
- (NSString *)_creditsFilePath | |
{ | |
if ([self.delegate respondsToSelector:@selector(creditsFileNameForApplication:)]) | |
{ | |
NSString *creditsFileName = [(id)self.delegate creditsFileNameForApplication:self]; | |
if (creditsFileName) | |
{ | |
NSString *resourcePath = [self _pathForResourceWithFileName:creditsFileName]; | |
if (resourcePath) | |
{ | |
return resourcePath; | |
} | |
} | |
} | |
for (NSString *fileName in @[ @"Credits.markdown", @"Credits.mdown", @"Credits.md", @"README.markdown", @"README.mdown", @"README.md" ]) | |
{ | |
NSString *resourcePath = [self _pathForResourceWithFileName:fileName]; | |
if (resourcePath) | |
{ | |
return resourcePath; | |
} | |
} | |
// If we got this far, we failed. | |
return nil; | |
} | |
// Assume creditsData contains Markdown. Check for the presence of various | |
// Markdown libraries. If one is found, use it to generate the credits string. | |
- (NSAttributedString *)_creditsStringFromMarkdownData:(NSData *)markdownData | |
{ | |
NSAttributedString *creditsString; | |
NSString *markdownString = [[NSString alloc] initWithData:markdownData | |
encoding:NSUTF8StringEncoding]; | |
if (markdownString == nil) | |
{ | |
return nil; | |
} | |
// See if the MMMarkdown library is present. | |
if ((creditsString = [self _mmmarkdownCreditsStringFromMarkdownString:markdownString])) | |
{ | |
return creditsString; | |
} | |
// | |
// ...[agl] Check for other Markdown libraries -- what are some popular ones?... | |
// | |
// If we got this far, we failed. | |
return nil; | |
} | |
// This method is never called. It's just here to provide a method prototype. | |
- (NSString *)HTMLStringWithMarkdown:(NSString *)markdownString error:(NSError **)errorPtr | |
{ | |
return nil; | |
} | |
- (NSAttributedString *)_mmmarkdownCreditsStringFromMarkdownString:(NSString *)markdownString | |
{ | |
Class mmmarkdownClass = NSClassFromString(@"MMMarkdown"); | |
if (mmmarkdownClass == nil) | |
{ | |
return nil; | |
} | |
NSError *error; | |
NSString *htmlString = [(id)mmmarkdownClass HTMLStringWithMarkdown:markdownString error:&error]; | |
if (htmlString == nil) | |
{ | |
return nil; | |
} | |
return [self _creditsStringFromHTMLString:htmlString]; | |
} | |
- (NSString *)_pathForResourceWithFileName:(NSString *)fileName | |
{ | |
return [[NSBundle mainBundle] pathForResource:[fileName stringByDeletingPathExtension] | |
ofType:[fileName pathExtension]]; | |
} | |
- (NSAttributedString *)_creditsStringFromHTMLString:(NSString *)htmlString | |
{ | |
return [[NSAttributedString alloc] initWithHTML:[htmlString dataUsingEncoding:NSUTF8StringEncoding] | |
documentAttributes:NULL]; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment