From 176fe8de5c704a0051572a2b636b2d30581679d4 Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Tue, 8 Mar 2016 16:45:33 +0800 Subject: [PATCH] Make it so --- .gitignore | 185 +++++++++++++ README.md | 67 +++++ macdown-gistit.xcodeproj/project.pbxproj | 258 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + macdown-gistit/Info.plist | 28 ++ macdown-gistit/MacDownGistItController.h | 15 + macdown-gistit/MacDownGistItController.m | 121 ++++++++ 7 files changed, 681 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 macdown-gistit.xcodeproj/project.pbxproj create mode 100644 macdown-gistit.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 macdown-gistit/Info.plist create mode 100644 macdown-gistit/MacDownGistItController.h create mode 100644 macdown-gistit/MacDownGistItController.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5f8a14a --- /dev/null +++ b/.gitignore @@ -0,0 +1,185 @@ +######################### +# .gitignore file for Xcode4 and Xcode5 Source projects +# +# Apple bugs, waiting for Apple to fix/respond: +# +# 15564624 - what does the xccheckout file in Xcode5 do? Where's the documentation? +# +# Version 2.1 +# For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects +# +# 2013 updates: +# - fixed the broken "save personal Schemes" +# - added line-by-line explanations for EVERYTHING (some were missing) +# +# NB: if you are storing "built" products, this WILL NOT WORK, +# and you should use a different .gitignore (or none at all) +# This file is for SOURCE projects, where there are many extra +# files that we want to exclude +# +######################### + +##### +# OS X temporary files that should never be committed +# +# c.f. http://www.westwind.com/reference/os-x/invisibles.html + +.DS_Store + +# c.f. http://www.westwind.com/reference/os-x/invisibles.html + +.Trashes + +# c.f. http://www.westwind.com/reference/os-x/invisibles.html + +*.swp + +# *.lock - this is used and abused by many editors for many different things. +# For the main ones I use (e.g. Eclipse), it should be excluded +# from source-control, but YMMV + +*.lock + +# +# profile - REMOVED temporarily (on double-checking, this seems incorrect; I can't find it in OS X docs?) +#profile + + +#### +# Xcode temporary files that should never be committed +# +# NB: NIB/XIB files still exist even on Storyboard projects, so we want this... + +*~.nib + + +#### +# Xcode build files - +# +# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" + +DerivedData/ + +# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" + +build/ + + +##### +# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) +# +# This is complicated: +# +# SOMETIMES you need to put this file in version control. +# Apple designed it poorly - if you use "custom executables", they are +# saved in this file. +# 99% of projects do NOT use those, so they do NOT want to version control this file. +# ..but if you're in the 1%, comment out the line "*.pbxuser" + +# .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html + +*.pbxuser + +# .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html + +*.mode1v3 + +# .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html + +*.mode2v3 + +# .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file + +*.perspectivev3 + +# NB: also, whitelist the default ones, some projects need to use these +!default.pbxuser +!default.mode1v3 +!default.mode2v3 +!default.perspectivev3 + + +#### +# Xcode 4 - semi-personal settings +# +# +# OPTION 1: --------------------------------- +# throw away ALL personal settings (including custom schemes! +# - unless they are "shared") +# +# NB: this is exclusive with OPTION 2 below +xcuserdata + +# OPTION 2: --------------------------------- +# get rid of ALL personal settings, but KEEP SOME OF THEM +# - NB: you must manually uncomment the bits you want to keep +# +# NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X, +# or manually install git over the top of the OS X version +# NB: this is exclusive with OPTION 1 above +# +#xcuserdata/**/* + +# (requires option 2 above): Personal Schemes +# +#!xcuserdata/**/xcschemes/* + +#### +# XCode 4 workspaces - more detailed +# +# Workspaces are important! They are a core feature of Xcode - don't exclude them :) +# +# Workspace layout is quite spammy. For reference: +# +# /(root)/ +# /(project-name).xcodeproj/ +# project.pbxproj +# /project.xcworkspace/ +# contents.xcworkspacedata +# /xcuserdata/ +# /(your name)/xcuserdatad/ +# UserInterfaceState.xcuserstate +# /xcsshareddata/ +# /xcschemes/ +# (shared scheme name).xcscheme +# /xcuserdata/ +# /(your name)/xcuserdatad/ +# (private scheme).xcscheme +# xcschememanagement.plist +# +# + +#### +# Xcode 4 - Deprecated classes +# +# Allegedly, if you manually "deprecate" your classes, they get moved here. +# +# We're using source-control, so this is a "feature" that we do not want! + +*.moved-aside + +#### +# UNKNOWN: recommended by others, but I can't discover what these files are +# +# ...none. Everything is now explained. + + +#### +# Other files +# + +# This needs to be included explicitly because we excluded *.lock previously. +!Podfile.lock + +Build/ +Pods/ +Dependency/version/version.h +Dependency/peg-markdown-highlight/pmh_parser_core.c +Dependency/peg-markdown-highlight/pmh_parser.c +Dependency/peg-markdown-highlight/*.o +Dependency/peg-markdown-highlight/greg/*.o +Dependency/peg-markdown-highlight/greg/*.o-* +Dependency/peg-markdown-highlight/greg/greg + +# Generated by build script +MacDown/Resources/Prism/* diff --git a/README.md b/README.md new file mode 100644 index 0000000..7029006 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +Gist it! for MacDown +===================== + +This repository illustrates a basic example of a plug-in for [MacDown], the open source Markdown editor for OS X. It provides a menu item "Gist it!" that uploads the current document (if available) as a public [GitHub Gist]. + +> Note: Plug-ins are available in MacDown 0.6+ only. This particular plug-in works only under OS X 10.9 or later, not 10.8. + +[MacDown]: http://macdown.uranusjr.com +[GitHub Gist]: https://gist.github.com + +### Installation + +Put the `macdown-gistit.plugin` file in `~/Library/Application Support/MacDown/PlugIns`. + +### Usage + +Open a document, and select menu item **Plug-ins → Gist it!** to upload. An alert dialog will appear to indicate whether the operation is successful. If the gist is creation successfully, its URL will be copied automatically into your +clipboard, so that you can easily share, or open it inside a browser. + +### License + +[![Created Commons License](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/)
+This work is licensed under a [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). + + +## The MacDown Plug-in Architecture + +This section serves as a simple walkthrough to how plug-ins work in MacDown until proper documentation is written. Hopefully not by myself. :p + +### Introduction + +A plugin in MacDown is a regular Cocoa [dynamic-loading bundle], with extension `.plugin`. MacDown searches `~/Library/Application Support/MacDown/PlugIns`, and build menu items for loadable bundles inside the directory. A plug-in in invoked when the user clicks on its corresponding menu item. + +[dynamic-loading bundle]: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/LoadingCode/LoadingCode.html#//apple_ref/doc/uid/10000052-SW1 + + +### Plug-in Architecture + +A plug-in project can be created via Xcode’s **OS X → Framework & Library → Bundle** project template. You should set up the project meta data according to Apple’s documentation, specifically provide a *Principle Class* config that points to the appropriate class inside the project as your plug-in’s entry class. + +A plug-in should provide two methods inside the principle class: + +**`- (NSString *)name`** + +This indicates the name of the plug-in. MacDown will use the value returned by this method as the menu item’s title for your plug-in. + +**`- (BOOL)run:(id)sender`** + +This method will be invoked when your plug-in is run. the `sender` argument indicates the UI item that triggers the invocation—usually the `NSMenuItem` object the user clicked on, but could also be `nil` if the plug-in is triggered programmatically. + +The return value indicates whether the plug-in is invoked successfully. + +This method may be invoked in the UI thread. Therefore, it is strongly recommended you push long operations into background threads, and/or run them asynchronously. + +### Tips + +MacDown uses the standard OS X document-based application structure. This means that you can get almost all information via the standard `NSDocumentController` API. Refer to the official documentation for more detail. + +A document instance in MacDown provides two additional properties: + +**`@property (nonatomic, readwrite) NSString *markdown`** + +This holds the string inside the editor. Writing to this property modifies the editor content. + +**`@property (nonatomic, readonly) NSString *html`** + +This holds the *rendered* HTML content. diff --git a/macdown-gistit.xcodeproj/project.pbxproj b/macdown-gistit.xcodeproj/project.pbxproj new file mode 100644 index 0000000..f96629d --- /dev/null +++ b/macdown-gistit.xcodeproj/project.pbxproj @@ -0,0 +1,258 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1F62698C1C8E98B000E87C30 /* MacDownGistItController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F62698B1C8E98B000E87C30 /* MacDownGistItController.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1F6269811C8E987F00E87C30 /* macdown-gistit.plugin */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "macdown-gistit.plugin"; sourceTree = BUILT_PRODUCTS_DIR; }; + 1F6269841C8E987F00E87C30 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 1F62698A1C8E98B000E87C30 /* MacDownGistItController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacDownGistItController.h; sourceTree = ""; }; + 1F62698B1C8E98B000E87C30 /* MacDownGistItController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MacDownGistItController.m; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1F62697E1C8E987F00E87C30 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 1F6269781C8E987F00E87C30 = { + isa = PBXGroup; + children = ( + 1F6269831C8E987F00E87C30 /* macdown-gistit */, + 1F6269821C8E987F00E87C30 /* Products */, + ); + sourceTree = ""; + }; + 1F6269821C8E987F00E87C30 /* Products */ = { + isa = PBXGroup; + children = ( + 1F6269811C8E987F00E87C30 /* macdown-gistit.plugin */, + ); + name = Products; + sourceTree = ""; + }; + 1F6269831C8E987F00E87C30 /* macdown-gistit */ = { + isa = PBXGroup; + children = ( + 1F6269841C8E987F00E87C30 /* Info.plist */, + 1F62698A1C8E98B000E87C30 /* MacDownGistItController.h */, + 1F62698B1C8E98B000E87C30 /* MacDownGistItController.m */, + ); + path = "macdown-gistit"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1F6269801C8E987F00E87C30 /* macdown-gistit */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1F6269871C8E987F00E87C30 /* Build configuration list for PBXNativeTarget "macdown-gistit" */; + buildPhases = ( + 1F62697D1C8E987F00E87C30 /* Sources */, + 1F62697E1C8E987F00E87C30 /* Frameworks */, + 1F62697F1C8E987F00E87C30 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "macdown-gistit"; + productName = "macdown-gistit"; + productReference = 1F6269811C8E987F00E87C30 /* macdown-gistit.plugin */; + productType = "com.apple.product-type.bundle"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 1F6269791C8E987F00E87C30 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0720; + ORGANIZATIONNAME = uranusjr; + TargetAttributes = { + 1F6269801C8E987F00E87C30 = { + CreatedOnToolsVersion = 7.2.1; + }; + }; + }; + buildConfigurationList = 1F62697C1C8E987F00E87C30 /* Build configuration list for PBXProject "macdown-gistit" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 1F6269781C8E987F00E87C30; + productRefGroup = 1F6269821C8E987F00E87C30 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1F6269801C8E987F00E87C30 /* macdown-gistit */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1F62697F1C8E987F00E87C30 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1F62697D1C8E987F00E87C30 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1F62698C1C8E98B000E87C30 /* MacDownGistItController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1F6269851C8E987F00E87C30 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 1F6269861C8E987F00E87C30 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.11; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + }; + name = Release; + }; + 1F6269881C8E987F00E87C30 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "macdown-gistit/Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Application Support/MacDown/PlugIns"; + PRODUCT_BUNDLE_IDENTIFIER = "com.uranusjr.macdown-gistit"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = plugin; + }; + name = Debug; + }; + 1F6269891C8E987F00E87C30 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = "macdown-gistit/Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Application Support/MacDown/PlugIns"; + PRODUCT_BUNDLE_IDENTIFIER = "com.uranusjr.macdown-gistit"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + WRAPPER_EXTENSION = plugin; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1F62697C1C8E987F00E87C30 /* Build configuration list for PBXProject "macdown-gistit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F6269851C8E987F00E87C30 /* Debug */, + 1F6269861C8E987F00E87C30 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 1F6269871C8E987F00E87C30 /* Build configuration list for PBXNativeTarget "macdown-gistit" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1F6269881C8E987F00E87C30 /* Debug */, + 1F6269891C8E987F00E87C30 /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + }; + rootObject = 1F6269791C8E987F00E87C30 /* Project object */; +} diff --git a/macdown-gistit.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/macdown-gistit.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..59f553f --- /dev/null +++ b/macdown-gistit.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macdown-gistit/Info.plist b/macdown-gistit/Info.plist new file mode 100644 index 0000000..6068f0c --- /dev/null +++ b/macdown-gistit/Info.plist @@ -0,0 +1,28 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + NSHumanReadableCopyright + Copyright © 2016 uranusjr. All rights reserved. + NSPrincipalClass + MacDownGistItController + + diff --git a/macdown-gistit/MacDownGistItController.h b/macdown-gistit/MacDownGistItController.h new file mode 100644 index 0000000..b91c745 --- /dev/null +++ b/macdown-gistit/MacDownGistItController.h @@ -0,0 +1,15 @@ +// +// MacDownGistItController.h +// macdown-gistit +// +// Created by Tzu-ping Chung on 08/3. +// Copyright © 2016 uranusjr. All rights reserved. +// + +#import + +@interface MacDownGistItController : NSObject + +@property (readonly) NSString *name; + +@end diff --git a/macdown-gistit/MacDownGistItController.m b/macdown-gistit/MacDownGistItController.m new file mode 100644 index 0000000..336cfaa --- /dev/null +++ b/macdown-gistit/MacDownGistItController.m @@ -0,0 +1,121 @@ +// +// MacDownGistItController.m +// macdown-gistit +// +// Created by Tzu-ping Chung on 08/3. +// Copyright © 2016 uranusjr. All rights reserved. +// + +#import +#import "MacDownGistItController.h" + + +static NSString * const MacDownGistListLink = @"https://api.github.com/gists"; + + +@protocol MacDownMarkdownSource + +@property (readonly) NSString *markdown; + +@end + + +@implementation MacDownGistItController + +- (NSString *)name +{ + return @"Gist It!"; +} + +- (BOOL)run:(id)sender +{ + NSDocumentController *dc = [NSDocumentController sharedDocumentController]; + return [self gistify:dc.currentDocument]; +} + +- (BOOL)gistify:(NSDocument *)document +{ + id markdownSource = (id)document; + NSString *markdown = markdownSource.markdown; + if (!markdown.length) + return NO; + NSString *fileName = document.fileURL.path.lastPathComponent; + if (!fileName.length) + fileName = @"Untitled"; + + NSURL * url = [NSURL URLWithString:MacDownGistListLink]; + NSMutableURLRequest *req = + [NSMutableURLRequest requestWithURL:url + cachePolicy:NSURLRequestReloadIgnoringCacheData + timeoutInterval:0.0]; + [req addValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; + [req addValue:@"application/json" forHTTPHeaderField:@"Accept"]; + + NSDictionary *object = @{ + @"description": @"Uploaded by MacDown. http://macdown.uranusjr.com", + @"public": @YES, + @"files": @{fileName: @{@"content": markdown}}, + }; + NSData *data = [NSJSONSerialization dataWithJSONObject:object + options:0 error:NULL]; + if (!data) + return NO; + + req.HTTPMethod = @"POST"; + req.HTTPBody = data; + + NSURLSessionConfiguration *conf = + [NSURLSessionConfiguration defaultSessionConfiguration]; + NSURLSession *session = [NSURLSession sessionWithConfiguration:conf]; + NSURLSessionTask *task = [session dataTaskWithRequest:req + completionHandler:^( + NSData *data, NSURLResponse *res, NSError *error) { + + NSHTTPURLResponse *r = (id)res; + NSString *json = data ? + [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] : + nil; + NSDictionary *object = data ? + [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL] : + nil; + NSString *urlstring = object[@"html_url"]; + + NSAlert *alert = [[NSAlert alloc] init]; + if (error) + { + alert = [NSAlert alertWithError:error]; + } + else if (![res respondsToSelector:@selector(statusCode)]) + { + alert.alertStyle = NSWarningAlertStyle; + alert.messageText = @"Unknown error"; + } + else if (r.statusCode != 201 || !urlstring) + { + alert.alertStyle = NSWarningAlertStyle; + NSString *f = @"Unexpection return code %ld"; + alert.messageText = [NSString stringWithFormat:f, r.statusCode]; + if (json) + alert.informativeText = json; + } + + alert.alertStyle = NSInformationalAlertStyle; + alert.messageText = @"Gist created"; + alert.informativeText = [NSString stringWithFormat: + @"You gist is at %@\nThe URL has been copied into your clipboard.", + urlstring]; + + NSPasteboard *pb = [NSPasteboard generalPasteboard]; + [pb clearContents]; + [pb writeObjects:@[urlstring]]; + + dispatch_async(dispatch_get_main_queue(), ^{ + [alert runModal]; + }); + }]; + [task resume]; + + return YES; +} + +@end