diff --git a/Example/MarkdownKitViewModel.swift b/Example/MarkdownKitViewModel.swift new file mode 100644 index 0000000..dbcd4d1 --- /dev/null +++ b/Example/MarkdownKitViewModel.swift @@ -0,0 +1,45 @@ +// +// MarkdownKitViewModel.swift +// Example +// +// Created by Bruno Oliveira on 21/01/2019. +// Copyright © 2019 Ivan Bruel. All rights reserved. +// + +import Foundation +import MarkdownKit +import Alamofire + +class MarkdownKitViewModel { + + let markdownParser: MarkdownParser + + fileprivate let testingURL: String + + var markdownAttributedStringChanged: ((NSAttributedString?, Error?) -> ())? = nil + + init(markdownParser: MarkdownParser, + testingURL: String = "https://raw.githubusercontent.com/apple/swift-evolution/master/proposals/0240-ordered-collection-diffing.md") { + self.markdownParser = markdownParser + self.testingURL = testingURL + } +} + +extension MarkdownKitViewModel { + func parseString(markdownString: String) { + markdownAttributedStringChanged?(markdownParser.parse(markdownString), nil) + } + + func requestTestPage() { + AF.request(testingURL).responseString { [weak self]response in + if let error = response.error { + self?.markdownAttributedStringChanged?(nil, error) + return + } + + response.result.withValue { [weak self]markdownString in + self?.parseString(markdownString: markdownString) + } + } + } +} diff --git a/Example/Resources/Base.lproj/Main.storyboard b/Example/Resources/Base.lproj/Main.storyboard index d51c65f..84cbf5b 100644 --- a/Example/Resources/Base.lproj/Main.storyboard +++ b/Example/Resources/Base.lproj/Main.storyboard @@ -1,5 +1,5 @@ - + @@ -12,7 +12,7 @@ - + @@ -22,7 +22,7 @@ - + Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. @@ -33,16 +33,40 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/ViewController.swift b/Example/ViewController.swift index b5d9f11..f205b14 100644 --- a/Example/ViewController.swift +++ b/Example/ViewController.swift @@ -10,33 +10,87 @@ import UIKit import MarkdownKit class ViewController: UIViewController { - @IBOutlet fileprivate weak var textView: UITextView! { didSet { textView.delegate = self + textView.isScrollEnabled = false } } - // Example with custom font - // fileprivate let markdownParser = MarkdownParser(font: UIFont(name: "Product Sans", size: UIFont.systemFontSize)!) + fileprivate lazy var attributedStringFromResources: String = { + return NSLocalizedString("Markdown", comment: "").stringByDecodingHTMLEntities + }() + + fileprivate lazy var viewModel: MarkdownKitViewModel = { + // Example with custom font + // fileprivate let markdownParser = MarkdownParser(font: UIFont(name: "Product Sans", size: UIFont.systemFontSize)!) + let parser = MarkdownParser() + parser.addCustomElement(MarkdownSubreddit()) + + let viewModel = MarkdownKitViewModel(markdownParser: parser) + viewModel.markdownAttributedStringChanged = { [weak self](attributtedString, error) in + if let error = error { + NSLog("Error requesting -> \(error)") + return + } + + guard let attributedText = attributtedString else { + NSLog("No error nor string found") + return + } + + self?.textView.attributedText = attributedText + } + + return viewModel + }() + + fileprivate var resourcesAction: UIAlertAction { + return UIAlertAction(title: "Resources", + style: .default, + handler: { [unowned self]_ in + self.viewModel.parseString(markdownString: self.attributedStringFromResources) + }) + } + + fileprivate var internetAction: UIAlertAction { + return UIAlertAction(title: "Internet", + style: .default, + handler: { [unowned self]_ in + self.viewModel.requestTestPage() + }) + } + + fileprivate var actionSheetController: UIAlertController { + let alert = UIAlertController(title: "Choose the Markdown source", message: nil, preferredStyle: .actionSheet) + alert.addAction(resourcesAction) + alert.addAction(internetAction) + alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: { _ in + alert.dismiss(animated: true, completion: nil) + })) + return alert + } - fileprivate let markdownParser = MarkdownParser() override func viewDidLoad() { super.viewDidLoad() - markdownParser.addCustomElement(MarkdownSubreddit()) - textView.attributedText = markdownParser.parse(NSLocalizedString("Markdown", comment: "").stringByDecodingHTMLEntities) - // Do any additional setup after loading the view, typically from a nib. + self.navigationItem.title = "MarkdownKit" + viewModel.parseString(markdownString: attributedStringFromResources) } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - // Dispose of any resources that can be recreated. + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + if (!textView.isScrollEnabled) { + textView.isScrollEnabled = true + textView.setContentOffset(.zero, animated: false) + } } + @IBAction func userDidTapSwitch(_ sender: Any) { + present(actionSheetController, animated: true, completion: nil) + } } extension ViewController: UITextViewDelegate { - func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool { UIApplication.shared.open(URL, options: [:]) @@ -45,3 +99,4 @@ extension ViewController: UITextViewDelegate { } } + diff --git a/MarkdownKit.podspec b/MarkdownKit.podspec index 268310c..1289532 100644 --- a/MarkdownKit.podspec +++ b/MarkdownKit.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "MarkdownKit" - s.version = "1.3" + s.version = "1.4" s.summary = "MarkdownKit is a customizable and extensible Markdown parser for iOS." s.description = <<-DESC MarkdownKit is a customizable and extensible Markdown parser for iOS. diff --git a/MarkdownKit.xcodeproj/project.pbxproj b/MarkdownKit.xcodeproj/project.pbxproj index f0dd0fb..bff83a4 100644 --- a/MarkdownKit.xcodeproj/project.pbxproj +++ b/MarkdownKit.xcodeproj/project.pbxproj @@ -7,6 +7,8 @@ objects = { /* Begin PBXBuildFile section */ + 6CBBF757D7C5F868299202E2 /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2009DA929218EA48384D9545 /* Pods_Example.framework */; }; + B06D95C41727E6744BAFB130 /* Pods_MarkdownKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9BB616C620AA78CC178349EA /* Pods_MarkdownKit.framework */; }; B62C1BEB21EF7D8D00308C8C /* String+HTMLDecode.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62C1BE221EF7D8C00308C8C /* String+HTMLDecode.swift */; }; B62C1BEC21EF7D8D00308C8C /* MarkdownSubreddit.swift in Sources */ = {isa = PBXBuildFile; fileRef = B62C1BE321EF7D8C00308C8C /* MarkdownSubreddit.swift */; }; B62C1BEE21EF7D8D00308C8C /* Product Sans Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B62C1BE521EF7D8C00308C8C /* Product Sans Regular.ttf */; }; @@ -38,9 +40,14 @@ B672002C21EF8A96008649E1 /* MarkdownLevelElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = B672001821EF8A96008649E1 /* MarkdownLevelElement.swift */; }; B672002D21EF8A96008649E1 /* MarkdownElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = B672001921EF8A96008649E1 /* MarkdownElement.swift */; }; B672002E21EF8A96008649E1 /* MarkdownStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B672001A21EF8A96008649E1 /* MarkdownStyle.swift */; }; + B695DA0E21F5E60300FC6FCD /* MarkdownKitViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B695DA0D21F5E60300FC6FCD /* MarkdownKitViewModel.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 2009DA929218EA48384D9545 /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 71F56393B2792188BC560048 /* Pods-MarkdownKit.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MarkdownKit.release.xcconfig"; path = "Target Support Files/Pods-MarkdownKit/Pods-MarkdownKit.release.xcconfig"; sourceTree = ""; }; + 7D049EC64593E526238AC045 /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; + 9BB616C620AA78CC178349EA /* Pods_MarkdownKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MarkdownKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B62C1BAD21EF7C8000308C8C /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; B62C1BE221EF7D8C00308C8C /* String+HTMLDecode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+HTMLDecode.swift"; sourceTree = ""; }; B62C1BE321EF7D8C00308C8C /* MarkdownSubreddit.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownSubreddit.swift; sourceTree = ""; }; @@ -75,6 +82,9 @@ B672001821EF8A96008649E1 /* MarkdownLevelElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownLevelElement.swift; sourceTree = ""; }; B672001921EF8A96008649E1 /* MarkdownElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownElement.swift; sourceTree = ""; }; B672001A21EF8A96008649E1 /* MarkdownStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MarkdownStyle.swift; sourceTree = ""; }; + B695DA0D21F5E60300FC6FCD /* MarkdownKitViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkdownKitViewModel.swift; sourceTree = ""; }; + D541903D4B863D139D52AF42 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; + E0F59E3C6A539A19D874DE27 /* Pods-MarkdownKit.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MarkdownKit.debug.xcconfig"; path = "Target Support Files/Pods-MarkdownKit/Pods-MarkdownKit.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -83,6 +93,7 @@ buildActionMask = 2147483647; files = ( B672000021EF8825008649E1 /* MarkdownKit.framework in Frameworks */, + 6CBBF757D7C5F868299202E2 /* Pods_Example.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -90,12 +101,25 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B06D95C41727E6744BAFB130 /* Pods_MarkdownKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 9958FA90ED0DF60AFA5C69DA /* Pods */ = { + isa = PBXGroup; + children = ( + D541903D4B863D139D52AF42 /* Pods-Example.debug.xcconfig */, + 7D049EC64593E526238AC045 /* Pods-Example.release.xcconfig */, + E0F59E3C6A539A19D874DE27 /* Pods-MarkdownKit.debug.xcconfig */, + 71F56393B2792188BC560048 /* Pods-MarkdownKit.release.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; B62C1BA421EF7C8000308C8C = { isa = PBXGroup; children = ( @@ -103,6 +127,7 @@ B62C1C0021EF7EED00308C8C /* MarkdownKit */, B62C1BAE21EF7C8000308C8C /* Products */, B672FFFF21EF8825008649E1 /* Frameworks */, + 9958FA90ED0DF60AFA5C69DA /* Pods */, ); sourceTree = ""; }; @@ -124,6 +149,7 @@ B688EF9F21EF8519003FF4AC /* Extensions */, B688EF9E21EF850B003FF4AC /* Fonts */, B688EF9D21EF84D6003FF4AC /* Resources */, + B695DA0D21F5E60300FC6FCD /* MarkdownKitViewModel.swift */, ); path = Example; sourceTree = ""; @@ -208,6 +234,8 @@ B672FFFF21EF8825008649E1 /* Frameworks */ = { isa = PBXGroup; children = ( + 2009DA929218EA48384D9545 /* Pods_Example.framework */, + 9BB616C620AA78CC178349EA /* Pods_MarkdownKit.framework */, ); name = Frameworks; sourceTree = ""; @@ -258,9 +286,11 @@ isa = PBXNativeTarget; buildConfigurationList = B62C1BCA21EF7C8100308C8C /* Build configuration list for PBXNativeTarget "Example" */; buildPhases = ( + E8D1545A32A10AFAFF88C956 /* [CP] Check Pods Manifest.lock */, B62C1BA921EF7C8000308C8C /* Sources */, B62C1BAA21EF7C8000308C8C /* Frameworks */, B62C1BAB21EF7C8000308C8C /* Resources */, + 52B210B76D0B5A10B67EBBEE /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -275,6 +305,7 @@ isa = PBXNativeTarget; buildConfigurationList = B62C1C1021EF7EED00308C8C /* Build configuration list for PBXNativeTarget "MarkdownKit" */; buildPhases = ( + 30227220D940239A6198465A /* [CP] Check Pods Manifest.lock */, B62C1BFA21EF7EED00308C8C /* Headers */, B62C1BFB21EF7EED00308C8C /* Sources */, B62C1BFC21EF7EED00308C8C /* Frameworks */, @@ -350,6 +381,75 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 30227220D940239A6198465A /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-MarkdownKit-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; + 52B210B76D0B5A10B67EBBEE /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/Alamofire/Alamofire.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + ); + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Alamofire.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + E8D1545A32A10AFAFF88C956 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Example-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ B62C1BA921EF7C8000308C8C /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -357,6 +457,7 @@ files = ( B62C1BEF21EF7D8D00308C8C /* AppDelegate.swift in Sources */, B62C1BEB21EF7D8D00308C8C /* String+HTMLDecode.swift in Sources */, + B695DA0E21F5E60300FC6FCD /* MarkdownKitViewModel.swift in Sources */, B62C1BF121EF7D8D00308C8C /* ViewController.swift in Sources */, B62C1BEC21EF7D8D00308C8C /* MarkdownSubreddit.swift in Sources */, ); @@ -529,6 +630,7 @@ }; B62C1BCB21EF7C8100308C8C /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = D541903D4B863D139D52AF42 /* Pods-Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -548,6 +650,7 @@ }; B62C1BCC21EF7C8100308C8C /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 7D049EC64593E526238AC045 /* Pods-Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -566,6 +669,7 @@ }; B62C1C1121EF7EED00308C8C /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = E0F59E3C6A539A19D874DE27 /* Pods-MarkdownKit.debug.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; @@ -595,6 +699,7 @@ }; B62C1C1221EF7EED00308C8C /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = 71F56393B2792188BC560048 /* Pods-MarkdownKit.release.xcconfig */; buildSettings = { CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = ""; diff --git a/MarkdownKit.xcworkspace/contents.xcworkspacedata b/MarkdownKit.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..6fd33ed --- /dev/null +++ b/MarkdownKit.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/MarkdownKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/MarkdownKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/MarkdownKit.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/MarkdownKit/Sources/Elements/MarkdownCode.swift b/MarkdownKit/Sources/Elements/MarkdownCode.swift index c1cee99..81f96d6 100644 --- a/MarkdownKit/Sources/Elements/MarkdownCode.swift +++ b/MarkdownKit/Sources/Elements/MarkdownCode.swift @@ -10,7 +10,7 @@ import UIKit open class MarkdownCode: MarkdownCommonElement { - fileprivate static let regex = "(.?|^)(\\`+)(.+?)(\\2)" + fileprivate static let regex = "(.?|^)(\\`{1,3})(.+?)(\\2)" open var font: UIFont? open var color: UIColor? diff --git a/MarkdownKit/Sources/Extensions/String+UTF16.swift b/MarkdownKit/Sources/Extensions/String+UTF16.swift index 65b9e71..29c9717 100644 --- a/MarkdownKit/Sources/Extensions/String+UTF16.swift +++ b/MarkdownKit/Sources/Extensions/String+UTF16.swift @@ -21,6 +21,12 @@ extension String { /// Converts each 4 digit characters to its String form (e.g. "0048" -> "H") func unescapeUTF16() -> String? { + + //This is an hot fix for the crash when a regular string is passed here. + guard count % 4 == 0 else { + return self + } + var utf16Array = [UInt16]() stride(from: 0, to: count, by: 4).forEach { let startIndex = index(self.startIndex, offsetBy: $0) diff --git a/Podfile b/Podfile new file mode 100644 index 0000000..f22ef4c --- /dev/null +++ b/Podfile @@ -0,0 +1,12 @@ +# Uncomment the next line to define a global platform for your project +platform :ios, '10.0' + +target 'Example' do + use_frameworks! + pod 'Alamofire', '~> 5.0.0.beta.1' +end + +target 'MarkdownKit' do + use_frameworks! + +end diff --git a/Podfile.lock b/Podfile.lock new file mode 100644 index 0000000..c8337f7 --- /dev/null +++ b/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - Alamofire (5.0.0.beta.1) + +DEPENDENCIES: + - Alamofire (~> 5.0.0.beta.1) + +SPEC REPOS: + https://github.com/cocoapods/specs.git: + - Alamofire + +SPEC CHECKSUMS: + Alamofire: 2ef6d6c984c5d21c366e9b41a9ae7dfee2b67a44 + +PODFILE CHECKSUM: 056fb12cb831c84165a65378ddd59f3ad8c252bd + +COCOAPODS: 1.6.0.beta.2